HV: vdev passthough hidding SRIOV

Support hide SRIOV extend capability for passthough device

Tracked-On: #5041
Signed-off-by: Tao Yuhong <yuhong.tao@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
Reviewed-by: Fei Li <fei1.li@intel.com>
This commit is contained in:
yuhong.tao@intel.com 2020-07-15 22:46:33 +08:00 committed by wenlingz
parent 585c652f81
commit eb36337622
6 changed files with 68 additions and 38 deletions

View File

@ -345,6 +345,21 @@ static void init_bars(struct pci_vdev *vdev, bool is_sriov_bar)
} }
} }
void vdev_pt_hide_sriov_cap(struct pci_vdev *vdev)
{
uint32_t pre_pos = vdev->pdev->sriov.pre_pos;
uint32_t pre_hdr, hdr, vhdr;
pre_hdr = pci_pdev_read_cfg(vdev->pdev->bdf, pre_pos, 4U);
hdr = pci_pdev_read_cfg(vdev->pdev->bdf, vdev->pdev->sriov.capoff, 4U);
vhdr = pre_hdr & 0xfffffU;
vhdr |= hdr & 0xfff00000U;
pci_vdev_write_vcfg(vdev, pre_pos, 4U, vhdr);
vdev->pdev->sriov.hide_sriov = true;
pr_acrnlog("Hide sriov cap for %02x:%02x.%x", vdev->pdev->bdf.bits.b, vdev->pdev->bdf.bits.d, vdev->pdev->bdf.bits.f);
}
/* /*
* @brief Initialize a specified passthrough vdev structure. * @brief Initialize a specified passthrough vdev structure.
* *

View File

@ -494,11 +494,13 @@ static int32_t write_pt_dev_cfg(struct pci_vdev *vdev, uint32_t offset,
} else if (sriovcap_access(vdev, offset)) { } else if (sriovcap_access(vdev, offset)) {
write_sriov_cap_reg(vdev, offset, bytes, val); write_sriov_cap_reg(vdev, offset, bytes, val);
} else { } else {
if (!is_quirk_ptdev(vdev)) { if (offset != vdev->pdev->sriov.pre_pos) {
/* passthru to physical device */ if (!is_quirk_ptdev(vdev)) {
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val); /* passthru to physical device */
} else { pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
ret = -ENODEV; } else {
ret = -ENODEV;
}
} }
} }
@ -519,7 +521,9 @@ static int32_t read_pt_dev_cfg(const struct pci_vdev *vdev, uint32_t offset,
} else if (sriovcap_access(vdev, offset)) { } else if (sriovcap_access(vdev, offset)) {
read_sriov_cap_reg(vdev, offset, bytes, val); read_sriov_cap_reg(vdev, offset, bytes, val);
} else { } else {
if (!is_quirk_ptdev(vdev)) { if (offset == vdev->pdev->sriov.pre_pos) {
*val = pci_vdev_read_vcfg(vdev, offset, bytes);
} else if (!is_quirk_ptdev(vdev)) {
/* passthru to physical device */ /* passthru to physical device */
*val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes); *val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes);
} else { } else {

View File

@ -156,4 +156,6 @@ void pci_vdev_write_vcfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes,
uint32_t pci_vdev_read_vbar(const struct pci_vdev *vdev, uint32_t idx); uint32_t pci_vdev_read_vbar(const struct pci_vdev *vdev, uint32_t idx);
void pci_vdev_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val); void pci_vdev_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val);
void vdev_pt_hide_sriov_cap(struct pci_vdev *vdev);
#endif /* VPCI_PRIV_H_ */ #endif /* VPCI_PRIV_H_ */

View File

@ -273,8 +273,12 @@ 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 read_sriov_cap_reg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val)
{ {
/* no need to do emulation, passthrough to physical device directly */ if (!vdev->pdev->sriov.hide_sriov) {
*val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes); /* no need to do emulation, passthrough to physical device directly */
*val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes);
} else {
*val = 0xffffffffU;
}
} }
/** /**
@ -287,41 +291,43 @@ void write_sriov_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes,
uint32_t reg; uint32_t reg;
reg = offset - vdev->sriov.capoff; reg = offset - vdev->sriov.capoff;
if (reg == PCIR_SRIOV_CONTROL) { if (!vdev->pdev->sriov.hide_sriov) {
bool enable; if (reg == PCIR_SRIOV_CONTROL) {
bool enable;
enable = (((val & PCIM_SRIOV_VF_ENABLE) != 0U) ? true : false); enable = (((val & PCIM_SRIOV_VF_ENABLE) != 0U) ? true : false);
if (enable != is_vf_enabled(vdev)) { if (enable != is_vf_enabled(vdev)) {
if (enable) { if (enable) {
/* /*
* set VF_ENABLE to PF physical device before enable_vfs * set VF_ENABLE to PF physical device before enable_vfs
* since need to ask hardware to create VF physical * since need to ask hardware to create VF physical
* devices firstly * devices firstly
*/ */
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val); pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
enable_vfs(vdev); enable_vfs(vdev);
} else {
disable_vfs(vdev);
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
}
} else { } else {
disable_vfs(vdev); pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
}
} else if (reg == PCIR_SRIOV_NUMVFS) {
uint16_t total;
total = read_sriov_reg(vdev, PCIR_SRIOV_TOTAL_VFS);
/*
* sanity check for NumVFs register based on PCE Express Base 4.0 9.3.3.7 chapter
* The results are undefined if NumVFs is set to a value greater than TotalVFs
* NumVFs may only be written while VF Enable is Clear
* If NumVFs is written when VF Enable is Set, the results are undefined
*/
if ((((uint16_t)(val & 0xFFU)) <= total) && (!is_vf_enabled(vdev))) {
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val); pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
} }
} else { } else {
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val); pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
} }
} else if (reg == PCIR_SRIOV_NUMVFS) {
uint16_t total;
total = read_sriov_reg(vdev, PCIR_SRIOV_TOTAL_VFS);
/*
* sanity check for NumVFs register based on PCE Express Base 4.0 9.3.3.7 chapter
* The results are undefined if NumVFs is set to a value greater than TotalVFs
* NumVFs may only be written while VF Enable is Clear
* If NumVFs is written when VF Enable is Set, the results are undefined
*/
if ((((uint16_t)(val & 0xFFU)) <= total) && (!is_vf_enabled(vdev))) {
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
}
} else {
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
} }
} }

View File

@ -663,7 +663,7 @@ static inline uint32_t pci_pdev_get_nr_bars(uint8_t hdr_type)
*/ */
static void pci_enumerate_ext_cap(struct pci_pdev *pdev) { static void pci_enumerate_ext_cap(struct pci_pdev *pdev) {
uint32_t hdr, pos; uint32_t hdr, pos, pre_pos = 0U;
pos = PCI_ECAP_BASE_PTR; pos = PCI_ECAP_BASE_PTR;
@ -673,12 +673,13 @@ static void pci_enumerate_ext_cap(struct pci_pdev *pdev) {
if (PCI_ECAP_ID(hdr) == PCIZ_SRIOV) { if (PCI_ECAP_ID(hdr) == PCIZ_SRIOV) {
pdev->sriov.capoff = pos; pdev->sriov.capoff = pos;
pdev->sriov.caplen = PCI_SRIOV_CAP_LEN; pdev->sriov.caplen = PCI_SRIOV_CAP_LEN;
pdev->sriov.pre_pos = pre_pos;
} }
pre_pos = pos;
pos = PCI_ECAP_NEXT(hdr); pos = PCI_ECAP_NEXT(hdr);
if (pos == 0U) { if (pos == 0U) {
break; break;
} }
hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U); hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U);
}; };
} }

View File

@ -221,6 +221,8 @@ struct pci_msix_cap {
struct pci_sriov_cap { struct pci_sriov_cap {
uint32_t capoff; uint32_t capoff;
uint32_t caplen; uint32_t caplen;
uint32_t pre_pos;
bool hide_sriov;
}; };
struct pci_pdev { struct pci_pdev {