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.
*

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)) {
write_sriov_cap_reg(vdev, offset, bytes, val);
} else {
if (!is_quirk_ptdev(vdev)) {
/* passthru to physical device */
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
} else {
ret = -ENODEV;
if (offset != vdev->pdev->sriov.pre_pos) {
if (!is_quirk_ptdev(vdev)) {
/* passthru to physical device */
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
} 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)) {
read_sriov_cap_reg(vdev, offset, bytes, val);
} 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 */
*val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes);
} 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);
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_ */

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)
{
/* no need to do emulation, passthrough to physical device directly */
*val = pci_pdev_read_cfg(vdev->pdev->bdf, offset, bytes);
if (!vdev->pdev->sriov.hide_sriov) {
/* 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;
reg = offset - vdev->sriov.capoff;
if (reg == PCIR_SRIOV_CONTROL) {
bool enable;
if (!vdev->pdev->sriov.hide_sriov) {
if (reg == PCIR_SRIOV_CONTROL) {
bool enable;
enable = (((val & PCIM_SRIOV_VF_ENABLE) != 0U) ? true : false);
if (enable != is_vf_enabled(vdev)) {
if (enable) {
/*
* set VF_ENABLE to PF physical device before enable_vfs
* since need to ask hardware to create VF physical
* devices firstly
*/
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
enable_vfs(vdev);
enable = (((val & PCIM_SRIOV_VF_ENABLE) != 0U) ? true : false);
if (enable != is_vf_enabled(vdev)) {
if (enable) {
/*
* set VF_ENABLE to PF physical device before enable_vfs
* since need to ask hardware to create VF physical
* devices firstly
*/
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
enable_vfs(vdev);
} else {
disable_vfs(vdev);
pci_pdev_write_cfg(vdev->pdev->bdf, offset, bytes, val);
}
} 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);
}
} else {
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) {
uint32_t hdr, pos;
uint32_t hdr, pos, pre_pos = 0U;
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) {
pdev->sriov.capoff = pos;
pdev->sriov.caplen = PCI_SRIOV_CAP_LEN;
pdev->sriov.pre_pos = pre_pos;
}
pre_pos = pos;
pos = PCI_ECAP_NEXT(hdr);
if (pos == 0U) {
break;
}
hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U);
};
}

View File

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