diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index 07f3368ae..c79db4dbf 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -351,13 +351,17 @@ void init_vdev_pt(struct pci_vdev *vdev, bool is_pf_vdev) { uint16_t pci_command; - init_bars(vdev, is_pf_vdev); - if (is_prelaunched_vm(vdev->vpci->vm) && (!is_pf_vdev)) { - pci_command = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U); + if (vdev->phyfun != NULL) { + init_sriov_vf_vdev(vdev); + } else { + init_bars(vdev, is_pf_vdev); + if (is_prelaunched_vm(vdev->vpci->vm) && (!is_pf_vdev)) { + pci_command = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U); - /* Disable INTX */ - pci_command |= 0x400U; - pci_pdev_write_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U, pci_command); + /* Disable INTX */ + pci_command |= 0x400U; + pci_pdev_write_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U, pci_command); + } } } diff --git a/hypervisor/dm/vpci/vpci_priv.h b/hypervisor/dm/vpci/vpci_priv.h index a0d1c2305..72da8d243 100644 --- a/hypervisor/dm/vpci/vpci_priv.h +++ b/hypervisor/dm/vpci/vpci_priv.h @@ -160,6 +160,7 @@ void init_vsriov(struct pci_vdev *vdev); void read_sriov_cap_reg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val); void write_sriov_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val); uint32_t sriov_bar_offset(const struct pci_vdev *vdev, uint32_t bar_idx); +void init_sriov_vf_vdev(struct pci_vdev *vdev); uint32_t pci_vdev_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes); void pci_vdev_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val); diff --git a/hypervisor/dm/vpci/vsriov.c b/hypervisor/dm/vpci/vsriov.c index a88eb858c..257581978 100644 --- a/hypervisor/dm/vpci/vsriov.c +++ b/hypervisor/dm/vpci/vsriov.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "vpci_priv.h" @@ -82,9 +83,36 @@ static void init_sriov_vf_bar(struct pci_vdev *pf_vdev) */ static void create_vf(struct pci_vdev *pf_vdev, union pci_bdf vf_bdf) { - /* Implementation in next patch */ - (void)pf_vdev; - (void)vf_bdf; + struct pci_pdev *vf_pdev; + struct pci_vdev *vf_vdev = NULL; + + /* + * Per VT-d 8.3.3, the VFs are under the scope of the same + * remapping unit as the associated PF when SRIOV is enabled. + */ + vf_pdev = init_pdev(vf_bdf.value, pf_vdev->pdev->drhd_index); + if (vf_pdev != NULL) { + struct acrn_vm_pci_dev_config *dev_cfg; + + dev_cfg = init_one_dev_config(vf_pdev); + if (dev_cfg != NULL) { + vf_vdev = vpci_init_vdev(&pf_vdev->vpci->vm->vpci, dev_cfg, pf_vdev); + } + } + + /* + * if a VF vdev failed to be created, the VF number is less than requested number + * and the requested VF physical devices are ready at this time, clear VF_ENABLE. + */ + if (vf_vdev == NULL) { + uint16_t control; + + control = read_sriov_reg(pf_vdev, PCIR_SRIOV_CONTROL); + control &= (~PCIM_SRIOV_VF_ENABLE); + pci_pdev_write_cfg(pf_vdev->bdf, pf_vdev->sriov.capoff + PCIR_SRIOV_CONTROL, 2U, control); + pr_err("PF %x:%x.%x can't creat VF, unset VF_ENABLE", + pf_vdev->bdf.bits.b, pf_vdev->bdf.bits.d, pf_vdev->bdf.bits.f); + } } /** @@ -242,3 +270,12 @@ uint32_t sriov_bar_offset(const struct pci_vdev *vdev, uint32_t bar_idx) { return (vdev->sriov.capoff + PCIR_SRIOV_VF_BAR_OFF + (bar_idx << 2U)); } + +/** + * @pre vdev != NULL + */ +void init_sriov_vf_vdev(struct pci_vdev *vdev) +{ + /* Implementation in next path */ + (void)vdev; +}