diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index ecb2b699b..26fa84813 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -311,6 +311,7 @@ void init_vdev_pt(struct pci_vdev *vdev) pbar = &vdev->pdev->bar[idx]; vbar = &vdev->bar[idx]; + vbar->base = 0UL; if (is_bar_supported(pbar)) { /** * If vbar->base is 0 (unassigned), Linux kernel will reprogram the vbar on @@ -324,6 +325,11 @@ void init_vdev_pt(struct pci_vdev *vdev) * are reported to guest as PCIBAR_MEM32 */ vbar->type = PCIBAR_MEM32; + + /* 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])); + } } else { vbar->size = 0UL; vbar->type = PCIBAR_NONE; diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index 298b41ed7..2c3174bce 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -415,6 +415,7 @@ static void init_vdev_for_pdev(struct pci_pdev *pdev, const void *vm) vdev->vpci = vpci; vdev->pdev = pdev; + vdev->ptdev_config = ptdev_config; if (ptdev_config != NULL) { /* vbdf is defined in vm_config */ @@ -425,10 +426,16 @@ static void init_vdev_for_pdev(struct pci_pdev *pdev, const void *vm) } init_vhostbridge(vdev); - init_vdev_pt(vdev); init_vmsi(vdev); init_vmsix(vdev); + /* + * Here init_vdev_pt() needs to be called after init_vmsix() for the following reason: + * init_vdev_pt() will indirectly call has_msix_cap(), which + * requires init_vmsix() to be called first. + */ + init_vdev_pt(vdev); + if (has_msix_cap(vdev)) { vdev_pt_remap_msix_table_bar(vdev); } diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h index 75872e73d..6a199e192 100644 --- a/hypervisor/include/arch/x86/vm_config.h +++ b/hypervisor/include/arch/x86/vm_config.h @@ -68,6 +68,7 @@ struct acrn_vm_os_config { struct acrn_vm_pci_ptdev_config { union pci_bdf vbdf; /* virtual BDF of PCI PT device */ union pci_bdf pbdf; /* physical BDF of PCI PT device */ + uint64_t vbar[PCI_BAR_COUNT]; /* vbar base address of PCI PT device */ } __aligned(8); struct acrn_vm_config { diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index e3bb5c571..3b7b93a19 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -78,6 +78,9 @@ struct pci_vdev { struct pci_msi msi; struct pci_msix msix; + + /* Pointer to corresponding PCI PT device's vm_config */ + struct acrn_vm_pci_ptdev_config *ptdev_config; }; struct pci_addr_info { diff --git a/hypervisor/scenarios/logical_partition/pt_dev.c b/hypervisor/scenarios/logical_partition/pt_dev.c index 04b3b27b3..bdecdcbf1 100644 --- a/hypervisor/scenarios/logical_partition/pt_dev.c +++ b/hypervisor/scenarios/logical_partition/pt_dev.c @@ -14,10 +14,15 @@ struct acrn_vm_pci_ptdev_config vm0_pci_ptdevs[VM0_CONFIG_PCI_PTDEV_NUM] = { }, { .vbdf.bits = {.b = 0x00U, .d = 0x01U, .f = 0x00U}, + .vbar[0] = 0xc0084000UL, + .vbar[1] = 0xc0086000UL, + .vbar[5] = 0xc0087000UL, VM0_STORAGE_CONTROLLER }, { .vbdf.bits = {.b = 0x00U, .d = 0x02U, .f = 0x00U}, + .vbar[0] = 0xc0000000UL, + .vbar[3] = 0xc0080000UL, VM0_NETWORK_CONTROLLER }, }; @@ -29,6 +34,7 @@ struct acrn_vm_pci_ptdev_config vm1_pci_ptdevs[VM1_CONFIG_PCI_PTDEV_NUM] = { }, { .vbdf.bits = {.b = 0x00U, .d = 0x01U, .f = 0x00U}, + .vbar[0] = 0xc0000000UL, VM1_STORAGE_CONTROLLER }, #if defined(VM1_NETWORK_CONTROLLER)