diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index c7eb9a0e4..07f3368ae 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -215,26 +215,46 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) * Hypervisor traps guest changes to the mmio vbar (gpa) to establish ept mapping * between vbar(gpa) and pbar(hpa). pbar should always align on 4K boundary. * + * @param vdev Pointer to a vdev structure + * @param is_sriov_bar When the first parameter vdev is a SRIOV PF vdev, the function + * init_bars is used to initialize normal PCIe BARs of PF vdev if the + * parameter is_sriov_bar is false, the function init_bars is used to + * initialize SRIOV VF BARs of PF vdev if parameter is_sriov_bar is true + * Otherwise, the parameter is_sriov_bar should be false if the first + * parameter vdev is not SRIOV PF vdev + * * @pre vdev != NULL * @pre vdev->vpci != NULL * @pre vdev->vpci->vm != NULL * @pre vdev->pdev != NULL + * + * @return None */ -static void init_bars(struct pci_vdev *vdev) +static void init_bars(struct pci_vdev *vdev, bool is_sriov_bar) { enum pci_bar_type type; - uint32_t idx; + uint32_t idx, bar_cnt; struct pci_vbar *vbar; uint32_t size32, offset, lo, hi = 0U; union pci_bdf pbdf; uint64_t mask; - vdev->nr_bars = vdev->pdev->nr_bars; + if (is_sriov_bar) { + bar_cnt = PCI_BAR_COUNT; + } else { + vdev->nr_bars = vdev->pdev->nr_bars; + bar_cnt = vdev->nr_bars; + } pbdf.value = vdev->pdev->bdf.value; - for (idx = 0U; idx < vdev->nr_bars; idx++) { - vbar = &vdev->vbars[idx]; - offset = pci_bar_offset(idx); + for (idx = 0U; idx < bar_cnt; idx++) { + if (is_sriov_bar) { + vbar = &vdev->sriov.vbars[idx]; + offset = sriov_bar_offset(vdev, idx); + } else { + vbar = &vdev->vbars[idx]; + offset = pci_bar_offset(idx); + } lo = pci_pdev_read_cfg(pbdf, offset, 4U); type = pci_get_bar_type(lo); @@ -265,7 +285,11 @@ static void init_bars(struct pci_vdev *vdev) if (type == PCIBAR_MEM64) { idx++; - offset = pci_bar_offset(idx); + if (is_sriov_bar) { + offset = sriov_bar_offset(vdev, idx); + } else { + offset = pci_bar_offset(idx); + } pci_pdev_write_cfg(pbdf, offset, 4U, ~0U); size32 = pci_pdev_read_cfg(pbdf, offset, 4U); pci_pdev_write_cfg(pbdf, offset, 4U, hi); @@ -274,21 +298,32 @@ static void init_bars(struct pci_vdev *vdev) vbar->size = vbar->size & ~(vbar->size - 1UL); vbar->size = round_page_up(vbar->size); - vbar = &vdev->vbars[idx]; + if (is_sriov_bar) { + vbar = &vdev->sriov.vbars[idx]; + } else { + vbar = &vdev->vbars[idx]; + } + vbar->mask = size32; vbar->type = PCIBAR_MEM64HI; if (is_prelaunched_vm(vdev->vpci->vm)) { hi = (uint32_t)(vdev->pci_dev_config->vbar_base[idx - 1U] >> 32U); } - pci_vdev_write_bar(vdev, idx - 1U, lo); - pci_vdev_write_bar(vdev, idx, hi); + /* if it is parsing SRIOV VF BARs, no need to write vdev bars */ + if (!is_sriov_bar) { + pci_vdev_write_bar(vdev, idx - 1U, lo); + pci_vdev_write_bar(vdev, idx, hi); + } } else { vbar->size = vbar->size & ~(vbar->size - 1UL); if (type == PCIBAR_MEM32) { vbar->size = round_page_up(vbar->size); } - pci_vdev_write_bar(vdev, idx, lo); + /* if it is parsing SRIOV VF BARs, no need to write vdev bar */ + if (!is_sriov_bar) { + pci_vdev_write_bar(vdev, idx, lo); + } } } } @@ -316,11 +351,8 @@ void init_vdev_pt(struct pci_vdev *vdev, bool is_pf_vdev) { uint16_t pci_command; - /* SRIOV capability initialization implementaion in next patch */ - (void) is_pf_vdev; - - init_bars(vdev); - if (is_prelaunched_vm(vdev->vpci->vm)) { + 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 */ diff --git a/hypervisor/dm/vpci/vpci_priv.h b/hypervisor/dm/vpci/vpci_priv.h index dd89a76d6..a0d1c2305 100644 --- a/hypervisor/dm/vpci/vpci_priv.h +++ b/hypervisor/dm/vpci/vpci_priv.h @@ -159,6 +159,7 @@ void deinit_vmsix(const struct pci_vdev *vdev); 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); 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 25b650fc0..a88eb858c 100644 --- a/hypervisor/dm/vpci/vsriov.c +++ b/hypervisor/dm/vpci/vsriov.c @@ -74,8 +74,7 @@ static bool is_vf_enabled(const struct pci_vdev *pf_vdev) */ static void init_sriov_vf_bar(struct pci_vdev *pf_vdev) { - /* Implementation in next patch */ - (void)pf_vdev; + init_vdev_pt(pf_vdev, true); } /** @@ -234,3 +233,12 @@ void write_sriov_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val); } } + + +/** + * @pre vdev != NULL + */ +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)); +} diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index 722cfff4d..a04883fee 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -252,7 +252,7 @@ static bool is_hv_owned_pdev(union pci_bdf pbdf) static void pci_init_pdev(union pci_bdf pbdf, uint32_t drhd_index) { if (!is_hv_owned_pdev(pbdf)) { - init_pdev(pbdf.value, drhd_index); + (void)init_pdev(pbdf.value, drhd_index); } } @@ -469,7 +469,7 @@ static void init_all_dev_config(void) total += cnt; } } - init_one_dev_config(pdev); + (void)init_one_dev_config(pdev); } } diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index defb075c3..ed8aeeb1f 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -73,6 +73,12 @@ struct pci_msix { struct pci_cap_sriov { uint32_t capoff; uint32_t caplen; + + /* + * If the vdev is a SRIOV PF vdev, the vbars is used to store + * the bar information that is using to initialize SRIOV VF vdev bar. + */ + struct pci_vbar vbars[PCI_BAR_COUNT]; }; union pci_cfgdata { diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 911c0ee2f..6715aac4a 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -120,6 +120,7 @@ #define PCIR_SRIOV_NUMVFS 0x10U #define PCIR_SRIOV_FST_VF_OFF 0x14U #define PCIR_SRIOV_VF_STRIDE 0x16U +#define PCIR_SRIOV_VF_BAR_OFF 0x24U #define PCIM_SRIOV_VF_ENABLE 0x1U /* PCI Message Signalled Interrupts (MSI) */