Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VPCI code cleanup/reorg #3334

Merged
merged 6 commits into from
Jun 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
100 changes: 49 additions & 51 deletions hypervisor/dm/vpci/pci_pt.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
*
* $FreeBSD$
*/

/* Passthrough PCI device related operations */

#include <vm.h>
#include <errno.h>
#include <ept.h>
Expand All @@ -46,13 +43,11 @@ static inline uint32_t get_bar_base(uint32_t bar)
* @pre vdev->vpci != NULL
* @pre vdev->vpci->vm != NULL
*/
int32_t vdev_pt_read_cfg(const struct pci_vdev *vdev, uint32_t offset,
uint32_t bytes, uint32_t *val)
int32_t vdev_pt_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val)
{
int32_t ret = -ENODEV;

/* PCI BARs is emulated */
if (is_prelaunched_vm(vdev->vpci->vm) && pci_bar_access(offset)) {
if (is_prelaunched_vm(vdev->vpci->vm) && is_bar_offset(vdev->nr_bars, offset)) {
*val = pci_vdev_read_cfg(vdev, offset, bytes);
ret = 0;
}
Expand All @@ -65,7 +60,7 @@ int32_t vdev_pt_read_cfg(const struct pci_vdev *vdev, uint32_t offset,
* @pre vdev->vpci != NULL
* @pre vdev->vpci->vm != NULL
* @pre vdev->pdev != NULL
* @pre vdev->pdev->msix.table_bar < (PCI_BAR_COUNT - 1U)
* @pre vdev->pdev->msix.table_bar < vdev->nr_bars
*/
void vdev_pt_remap_msix_table_bar(struct pci_vdev *vdev)
{
Expand All @@ -75,7 +70,7 @@ void vdev_pt_remap_msix_table_bar(struct pci_vdev *vdev)
struct pci_pdev *pdev = vdev->pdev;
struct pci_bar *bar;

ASSERT(vdev->pdev->msix.table_bar < (PCI_BAR_COUNT - 1U), "msix->table_bar is out of range");
ASSERT(vdev->pdev->msix.table_bar < vdev->nr_bars, "msix->table_bar is out of range");

/* Mask all table entries */
for (i = 0U; i < msix->table_count; i++) {
Expand Down Expand Up @@ -167,14 +162,14 @@ void vdev_pt_remap_msix_table_bar(struct pci_vdev *vdev)
}

/**
* @brief Remaps guest BARs other than MSI-x Table BAR
* @brief Remaps guest MMIO BARs other than MSI-x Table BAR
* This API is invoked upon guest re-programming PCI BAR with MMIO region
* after a new vbar is set.
* @pre vdev != NULL
* @pre vdev->vpci != NULL
* @pre vdev->vpci->vm != NULL
*/
static void vdev_pt_remap_generic_bar(const struct pci_vdev *vdev, uint32_t idx,
uint32_t new_base)
static void vdev_pt_remap_generic_mem_vbar(const struct pci_vdev *vdev, uint32_t idx, uint32_t new_base)
{
struct acrn_vm *vm = vdev->vpci->vm;

Expand All @@ -196,64 +191,63 @@ static void vdev_pt_remap_generic_bar(const struct pci_vdev *vdev, uint32_t idx,

/**
* @pre vdev != NULL
* @pre (vdev->bar[idx].type == PCIBAR_NONE) || (vdev->bar[idx].type == PCIBAR_MEM32)
*/
static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t new_bar_uos)
static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t val)
{
uint32_t idx;
uint32_t new_bar, mask;
bool bar_update_normal;
bool is_msix_table_bar;

/* Bar access must be 4 bytes aligned */
if ((bytes == 4U) && ((offset & 0x3U) == 0U)) {
new_bar = 0U;
idx = (offset - pci_bar_offset(0U)) >> 2U;
mask = ~(vdev->bar[idx].size - 1U);

switch (vdev->bar[idx].type) {
case PCIBAR_NONE:
vdev->bar[idx].base = 0UL;
break;

case PCIBAR_MEM32:
bar_update_normal = (new_bar_uos != (uint32_t)~0U);
is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar));
new_bar = new_bar_uos & mask;
if (bar_update_normal) {
if (is_msix_table_bar) {
vdev->bar[idx].base = get_bar_base(new_bar);
vdev_pt_remap_msix_table_bar(vdev);
} else {
vdev_pt_remap_generic_bar(vdev, idx,
get_bar_base(new_bar));

vdev->bar[idx].base = get_bar_base(new_bar);
}
}
break;
new_bar = 0U;
idx = (offset - pci_bar_offset(0U)) >> 2U;
mask = ~(vdev->bar[idx].size - 1U);

switch (vdev->bar[idx].type) {
case PCIBAR_NONE:
vdev->bar[idx].base = 0UL;
break;

case PCIBAR_MEM32:
bar_update_normal = (val != (uint32_t)~0U);
is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar));
new_bar = val & mask;
if (bar_update_normal) {
if (is_msix_table_bar) {
vdev->bar[idx].base = get_bar_base(new_bar);
vdev_pt_remap_msix_table_bar(vdev);
} else {
vdev_pt_remap_generic_mem_vbar(vdev, idx,
get_bar_base(new_bar));

default:
pr_err("Unknown bar type, idx=%d", idx);
break;
vdev->bar[idx].base = get_bar_base(new_bar);
}
}
break;

pci_vdev_write_cfg_u32(vdev, offset, new_bar);
default:
/* Should never reach here, init_vdev_pt() only sets vbar type to PCIBAR_NONE and PCIBAR_MEM32 */
break;
}

pci_vdev_write_cfg_u32(vdev, offset, new_bar);
}

/**
* @pre vdev != NULL
* @pre vdev->vpci != NULL
* @pre vdev->vpci->vm != NULL
* bar write access must be 4 bytes and offset must also be 4 bytes aligned, it will be dropped otherwise
*/
int32_t vdev_pt_write_cfg(struct pci_vdev *vdev, uint32_t offset,
uint32_t bytes, uint32_t val)
int32_t vdev_pt_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val)
{
int32_t ret = -ENODEV;

/* PCI BARs are emulated */
if (is_prelaunched_vm(vdev->vpci->vm) && pci_bar_access(offset)) {
vdev_pt_write_vbar(vdev, offset, bytes, val);
/* bar write access must be 4 bytes and offset must also be 4 bytes aligned */
if (is_prelaunched_vm(vdev->vpci->vm) && is_bar_offset(vdev->nr_bars, offset)
&& (bytes == 4U) && ((offset & 0x3U) == 0U)) {
vdev_pt_write_vbar(vdev, offset, val);
ret = 0;
}

Expand Down Expand Up @@ -300,8 +294,12 @@ void init_vdev_pt(struct pci_vdev *vdev)
struct pci_bar *pbar, *vbar;
uint16_t pci_command;

vdev->nr_bars = vdev->pdev->nr_bars;

ASSERT(vdev->nr_bars > 0U, "vdev->nr_bars should be greater than 0!");

if (is_prelaunched_vm(vdev->vpci->vm)) {
for (idx = 0U; idx < (uint32_t)PCI_BAR_COUNT; idx++) {
for (idx = 0U; idx < vdev->nr_bars; idx++) {
pbar = &vdev->pdev->bar[idx];
vbar = &vdev->bar[idx];

Expand All @@ -322,7 +320,7 @@ void init_vdev_pt(struct pci_vdev *vdev)

/* Set the new vbar base */
if (vdev->ptdev_config->vbar[idx] != 0UL) {
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), 4U, (uint32_t)(vdev->ptdev_config->vbar[idx]));
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)(vdev->ptdev_config->vbar[idx]));
}
} else {
vbar->size = 0UL;
Expand Down
2 changes: 1 addition & 1 deletion hypervisor/dm/vpci/vhostbridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ int32_t vhostbridge_write_cfg(struct pci_vdev *vdev, uint32_t offset,
int32_t ret = -ENODEV;

if (is_hostbridge(vdev) && is_prelaunched_vm(vdev->vpci->vm)) {
if (!pci_bar_access(offset)) {
if (!is_bar_offset(PCI_BAR_COUNT, offset)) {
pci_vdev_write_cfg(vdev, offset, bytes, val);
}

Expand Down