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 <yuan1.liu@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yuan Liu 2020-03-09 22:30:41 +08:00 committed by wenlingz
parent 640cf57c14
commit 657af925c1
3 changed files with 29 additions and 1 deletions

View File

@ -387,5 +387,18 @@ void init_vdev_pt(struct pci_vdev *vdev, bool is_pf_vdev)
pci_command |= 0x400U; pci_command |= 0x400U;
pci_pdev_write_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U, pci_command); 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);
}
} }
} }

View File

@ -425,6 +425,12 @@ static void read_cfg_header(const struct pci_vdev *vdev,
} else { } else {
if (bitmap32_test(((uint16_t)offset) >> 2U, &cfg_hdr_perm.pt_mask)) { if (bitmap32_test(((uint16_t)offset) >> 2U, &cfg_hdr_perm.pt_mask)) {
*val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes); *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 { } else {
*val = pci_vdev_read_vcfg(vdev, offset, bytes); *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; vdev_in_sos->vpci = vpci;
spinlock_obtain(&tgt_vm->vpci.lock); 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_LINE, 1U, pcidev->intr_line);
pci_vdev_write_vcfg(vdev, PCIR_INTERRUPT_PIN, 1U, pcidev->intr_pin); pci_vdev_write_vcfg(vdev, PCIR_INTERRUPT_PIN, 1U, pcidev->intr_pin);
for (idx = 0U; idx < vdev->nr_bars; idx++) { 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]); pci_vdev_write_vbar(vdev, idx, pcidev->bar[idx]);
} }

View File

@ -122,6 +122,7 @@
#define PCIR_SRIOV_NUMVFS 0x10U #define PCIR_SRIOV_NUMVFS 0x10U
#define PCIR_SRIOV_FST_VF_OFF 0x14U #define PCIR_SRIOV_FST_VF_OFF 0x14U
#define PCIR_SRIOV_VF_STRIDE 0x16U #define PCIR_SRIOV_VF_STRIDE 0x16U
#define PCIR_SRIOV_VF_DEV_ID 0x1AU
#define PCIR_SRIOV_VF_BAR_OFF 0x24U #define PCIR_SRIOV_VF_BAR_OFF 0x24U
#define PCIM_SRIOV_VF_ENABLE 0x1U #define PCIM_SRIOV_VF_ENABLE 0x1U