HV: enable bar emulation for sos

For sos, its vbar base address is set to pbar base address (vbar gpa = pbar
hpa)

For pre-launched VMs, vbar base address is pre-assigned in vm_config

Rename vdev_pt_remap_msix_table_bar to vdev_pt_remap_msix_table_vbar and make it
a static function

Remove unused function prototye vdev_pt_remap_msix_table_bar() in vpci_priv.h

Tracked-On: #3241
Signed-off-by: dongshen <dongsheng.x.zhang@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
dongshen 2019-06-25 14:03:39 -07:00 committed by wenlingz
parent af163d579f
commit 4be09f24f3
3 changed files with 47 additions and 47 deletions

View File

@ -127,14 +127,12 @@ static uint64_t get_pbar_base(const struct pci_pdev *pdev, uint32_t idx)
/** /**
* @pre vdev != NULL * @pre vdev != NULL
* @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; int32_t ret = -ENODEV;
if (is_prelaunched_vm(vdev->vpci->vm) && is_bar_offset(vdev->nr_bars, offset)) { if (is_bar_offset(vdev->nr_bars, offset)) {
*val = pci_vdev_read_cfg(vdev, offset, bytes); *val = pci_vdev_read_cfg(vdev, offset, bytes);
ret = 0; ret = 0;
} }
@ -149,7 +147,7 @@ int32_t vdev_pt_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t
* @pre vdev->pdev != NULL * @pre vdev->pdev != NULL
* @pre vdev->pdev->msix.table_bar < vdev->nr_bars * @pre vdev->pdev->msix.table_bar < vdev->nr_bars
*/ */
void vdev_pt_remap_msix_table_bar(struct pci_vdev *vdev) static void vdev_pt_remap_msix_table_vbar(struct pci_vdev *vdev)
{ {
uint32_t i; uint32_t i;
struct pci_msix *msix = &vdev->msix; struct pci_msix *msix = &vdev->msix;
@ -315,7 +313,7 @@ static void vdev_pt_remap_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)); is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar));
if (is_msix_table_bar) { if (is_msix_table_bar) {
vdev_pt_remap_msix_table_bar(vdev); vdev_pt_remap_msix_table_vbar(vdev);
} else { } else {
vdev_pt_remap_generic_mem_vbar(vdev, idx); vdev_pt_remap_generic_mem_vbar(vdev, idx);
} }
@ -403,17 +401,14 @@ static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t
/** /**
* @pre vdev != NULL * @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 * 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; int32_t ret = -ENODEV;
/* bar write access must be 4 bytes and offset must also be 4 bytes aligned */ /* 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) if (is_bar_offset(vdev->nr_bars, offset) && (bytes == 4U) && ((offset & 0x3U) == 0U)) {
&& (bytes == 4U) && ((offset & 0x3U) == 0U)) {
vdev_pt_write_vbar(vdev, offset, val); vdev_pt_write_vbar(vdev, offset, val);
ret = 0; ret = 0;
} }
@ -457,50 +452,60 @@ void init_vdev_pt(struct pci_vdev *vdev)
ASSERT(vdev->nr_bars > 0U, "vdev->nr_bars should be greater than 0!"); ASSERT(vdev->nr_bars > 0U, "vdev->nr_bars should be greater than 0!");
if (is_prelaunched_vm(vdev->vpci->vm)) { for (idx = 0U; idx < vdev->nr_bars; idx++) {
for (idx = 0U; idx < vdev->nr_bars; idx++) { pbar = &vdev->pdev->bar[idx];
pbar = &vdev->pdev->bar[idx]; vbar = &vdev->bar[idx];
vbar = &vdev->bar[idx];
vbar->size = 0UL; vbar->size = 0UL;
vbar->reg.value = pbar->reg.value; vbar->reg.value = pbar->reg.value;
vbar->is_64bit_high = pbar->is_64bit_high; vbar->is_64bit_high = pbar->is_64bit_high;
if (pbar->is_64bit_high) { if (pbar->is_64bit_high) {
ASSERT(idx > 0U, "idx for upper 32-bit of the 64-bit bar should be greater than 0!"); ASSERT(idx > 0U, "idx for upper 32-bit of the 64-bit bar should be greater than 0!");
if (idx > 0U) { if (is_sos_vm(vdev->vpci->vm)) {
/* For pre-launched VMs: vbar base is predefined in vm_config */ /* For SOS: vbar base (GPA) = pbar base (HPA) */
vbar_base = vdev->ptdev_config->vbar_base[idx - 1U]; vbar_base = get_pbar_base(vdev->pdev, idx);
/* Write the upper 32-bit of a 64-bit bar */ } else if (idx > 0U) {
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)(vbar_base >> 32U)); /* For pre-launched VMs: vbar base is predefined in vm_config */
} vbar_base = vdev->ptdev_config->vbar_base[idx - 1U];
} else { } else {
enum pci_bar_type type = pci_get_bar_type(pbar->reg.value); vbar_base = 0UL;
}
/* Write the upper 32-bit of a 64-bit bar */
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)(vbar_base >> 32U));
} else {
enum pci_bar_type type = pci_get_bar_type(pbar->reg.value);
switch (type) { switch (type) {
case PCIBAR_MEM32: case PCIBAR_MEM32:
case PCIBAR_MEM64: case PCIBAR_MEM64:
/** /**
* If vbar->base is 0 (unassigned), Linux kernel will reprogram the vbar on * If vbar->base is 0 (unassigned), Linux kernel will reprogram the vbar on
* its bar size boundary, so in order to ensure the MMIO vbar allocated by guest * its bar size boundary, so in order to ensure the MMIO vbar allocated by guest
* is 4k aligned, set its size to be 4K aligned. * is 4k aligned, set its size to be 4K aligned.
*/ */
vbar->size = round_page_up(pbar->size); vbar->size = round_page_up(pbar->size);
if (is_sos_vm(vdev->vpci->vm)) {
/* For SOS: vbar base (GPA) = pbar base (HPA) */
vbar_base = get_pbar_base(vdev->pdev, idx);
} else {
/* For pre-launched VMs: vbar base is predefined in vm_config */ /* For pre-launched VMs: vbar base is predefined in vm_config */
vbar_base = vdev->ptdev_config->vbar_base[idx]; vbar_base = vdev->ptdev_config->vbar_base[idx];
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)vbar_base);
break;
default:
vbar->reg.value = 0x0U;
vbar->size = 0UL;
break;
} }
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)vbar_base);
break;
default:
vbar->reg.value = 0x0U;
vbar->size = 0UL;
break;
} }
} }
}
if (is_prelaunched_vm(vdev->vpci->vm)) {
pci_command = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U); pci_command = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U);
/* Disable INTX */ /* Disable INTX */

View File

@ -436,10 +436,6 @@ static void init_vdev_for_pdev(struct pci_pdev *pdev, const struct acrn_vm *vm)
*/ */
init_vdev_pt(vdev); init_vdev_pt(vdev);
if (has_msix_cap(vdev)) {
vdev_pt_remap_msix_table_bar(vdev);
}
/* /*
* For pre-launched VM, the host bridge is fully virtualized and it does not have a physical * For pre-launched VM, the host bridge is fully virtualized and it does not have a physical
* host bridge counterpart. * host bridge counterpart.

View File

@ -116,7 +116,6 @@ int32_t vmsi_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, u
void deinit_vmsi(const struct pci_vdev *vdev); void deinit_vmsi(const struct pci_vdev *vdev);
void init_vmsix(struct pci_vdev *vdev); void init_vmsix(struct pci_vdev *vdev);
void vdev_pt_remap_msix_table_bar(struct pci_vdev *vdev);
int32_t vmsix_table_mmio_access_handler(struct io_request *io_req, void *handler_private_data); int32_t vmsix_table_mmio_access_handler(struct io_request *io_req, void *handler_private_data);
int32_t vmsix_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val); int32_t vmsix_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val);
int32_t vmsix_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val); int32_t vmsix_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);