From 657af925c1bc5ef43c84d43d20a86eadf35df89f Mon Sep 17 00:00:00 2001 From: Yuan Liu Date: Mon, 9 Mar 2020 22:30:41 +0800 Subject: [PATCH] hv: passthrough a VF device Emulate Device ID, Vendor ID and MSE(Memory Space Enable) bit in configuration space for an assigned VF, initialize assgined VF Bars. The Device ID comes from PF's SRIOV capability The Vendor ID comes from PF's Vendor ID The PCI MSE bit always be set when VM reads from an assigned VF. Tracked-On: #4433 Signed-off-by: Yuan Liu Acked-by: Eddie Dong --- hypervisor/dm/vpci/pci_pt.c | 13 +++++++++++++ hypervisor/dm/vpci/vpci.c | 16 +++++++++++++++- hypervisor/include/hw/pci.h | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index c39b31777..99c962b1d 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -387,5 +387,18 @@ void init_vdev_pt(struct pci_vdev *vdev, bool is_pf_vdev) pci_command |= 0x400U; pci_pdev_write_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U, pci_command); } + } else { + /* VF is assigned to a UOS */ + if (vdev->vpci != vdev->phyfun->vpci) { + uint32_t vid, did; + + vdev->nr_bars = PCI_BAR_COUNT; + /* SRIOV VF Vendor ID and Device ID initialization */ + vid = pci_pdev_read_cfg(vdev->phyfun->bdf, PCIR_VENDOR, 2U); + did = pci_pdev_read_cfg(vdev->phyfun->bdf, + (vdev->phyfun->sriov.capoff + PCIR_SRIOV_VF_DEV_ID), 2U); + pci_vdev_write_vcfg(vdev, PCIR_VENDOR, 2U, vid); + pci_vdev_write_vcfg(vdev, PCIR_DEVICE, 2U, did); + } } } diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index 21e19a906..c1a35cc2d 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -425,6 +425,12 @@ static void read_cfg_header(const struct pci_vdev *vdev, } else { if (bitmap32_test(((uint16_t)offset) >> 2U, &cfg_hdr_perm.pt_mask)) { *val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes); + + /* MSE(Memory Space Enable) bit always be set for an assigned VF */ + if ((vdev->phyfun != NULL) && (offset == PCIR_COMMAND) && + (vdev->vpci != vdev->phyfun->vpci)) { + *val |= PCIM_CMD_MEMEN; + } } else { *val = pci_vdev_read_vcfg(vdev, offset, bytes); } @@ -721,10 +727,18 @@ int32_t vpci_assign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev *pc vdev_in_sos->vpci = vpci; spinlock_obtain(&tgt_vm->vpci.lock); - vdev = vpci_init_vdev(vpci, vdev_in_sos->pci_dev_config, NULL); + vdev = vpci_init_vdev(vpci, vdev_in_sos->pci_dev_config, vdev_in_sos->phyfun); pci_vdev_write_vcfg(vdev, PCIR_INTERRUPT_LINE, 1U, pcidev->intr_line); pci_vdev_write_vcfg(vdev, PCIR_INTERRUPT_PIN, 1U, pcidev->intr_pin); for (idx = 0U; idx < vdev->nr_bars; idx++) { + /* VF is assigned to a UOS */ + if (vdev->phyfun != NULL) { + vdev->vbars[idx] = vdev_in_sos->vbars[idx]; + if (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)) { + vdev->msix.mmio_hpa = vdev->vbars[idx].base_hpa; + vdev->msix.mmio_size = vdev->vbars[idx].size; + } + } pci_vdev_write_vbar(vdev, idx, pcidev->bar[idx]); } diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 77c60e8ea..c594e77f8 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -122,6 +122,7 @@ #define PCIR_SRIOV_NUMVFS 0x10U #define PCIR_SRIOV_FST_VF_OFF 0x14U #define PCIR_SRIOV_VF_STRIDE 0x16U +#define PCIR_SRIOV_VF_DEV_ID 0x1AU #define PCIR_SRIOV_VF_BAR_OFF 0x24U #define PCIM_SRIOV_VF_ENABLE 0x1U