hv: add max payload to vrp

It seems important that passthru device's max payload settings match
the settings on the native device otherwise passthru device may not work.
So we have to set vrp's max payload capacity as native root port
otherwise we may accidentally change passthru device's max payload
since during guest OS's pci device enumeration, pass-thru device will
renegotiate its max payload's setting with vrp.

Tracked-On: #5915

Signed-off-by: Rong Liu <rong.l.liu@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Rong Liu 2021-06-10 06:28:04 +00:00 committed by wenlingz
parent 48c5fc5124
commit 321e560968
4 changed files with 28 additions and 2 deletions

View File

@ -40,10 +40,32 @@ static void init_vrp(struct pci_vdev *vdev)
/* capability pointer */
pci_vdev_write_vcfg(vdev, PCIR_CAP_PTR, 1U, PCIE_CAP_VPOS);
/* pcie capability registers */
pci_vdev_write_vcfg(vdev, PCIE_CAP_VPOS + PCICAP_ID, 1U, 0x10);
/* pcie capability registers */
pci_vdev_write_vcfg(vdev, PCIE_CAP_VPOS + PCICAP_ID, 1U, PCIY_PCIE);
/* bits (3:0): capability version = 010b
* bits (7:4) device/port type = 0100b (root port of pci-e)
* bits (8) -- slot implemented = 1b
*/
pci_vdev_write_vcfg(vdev, PCIE_CAP_VPOS + PCICAP_EXP_CAP, 2U, 0x0142);
/* It seems important that passthru device's max payload settings match
* the settings on the native device otherwise passthru device may not work.
* So we have to set vrp's max payload capacity as native root port
* otherwise we may accidentally change passthru device's max payload since
* during guest OS's pci device enumeration, pass-thru device will renegotiate
* its max payload's setting with vrp.
*/
pci_vdev_write_vcfg(vdev, PCIE_CAP_VPOS + PCIR_PCIE_DEVCAP, 4U,
vdev->pci_dev_config->vrp_max_payload);
/* In theory, we don't need to program dev ctr's max payload and hopefully OS
* will program it but we cannot always rely on OS to program
* this register.
*/
pci_vdev_write_vcfg(vdev, PCIE_CAP_VPOS + PCIR_PCIE_DEVCTRL, 2U,
(vdev->pci_dev_config->vrp_max_payload << 5) & PCIM_PCIE_DEV_CTRL_MAX_PAYLOAD);
vdev->parent_user = NULL;
vdev->user = vdev;
}
@ -114,6 +136,7 @@ int32_t create_vrp(struct acrn_vm *vm, struct acrn_emul_dev *dev)
if (dev_config->vrp_sec_bus == vrp_config->secondary_bus) {
dev_config->vbdf.value = dev->slot;
dev_config->pbdf.value = vrp_config->phy_bdf;
dev_config->vrp_max_payload = vrp_config->max_payload;
dev_config->vdev_ops = &vrp_ops;
vdev = vpci_init_vdev(&vm->vpci, dev_config, NULL);

View File

@ -154,6 +154,7 @@ struct acrn_vm_pci_dev_config {
struct target_vuart t_vuart;
uint16_t vuart_idx;
uint16_t vrp_sec_bus; /* use virtual root port's secondary bus as unique identification */
uint8_t vrp_max_payload; /* vrp's dev cap's max payload */
uint64_t vbar_base[PCI_BAR_COUNT]; /* vbar base address of PCI device, which is power-on default value */
struct pci_pdev *pdev; /* the physical PCI device if it's a PT device */
const struct pci_vdev_ops *vdev_ops; /* operations for PCI CFG read/write */

View File

@ -185,6 +185,7 @@
#define PCIY_PCIE 0x10U
#define PCIR_PCIE_DEVCAP 0x04U
#define PCIR_PCIE_DEVCTRL 0x08U
#define PCIM_PCIE_DEV_CTRL_MAX_PAYLOAD 0x00E0U
#define PCIM_PCIE_FLRCAP (0x1U << 28U)
#define PCIM_PCIE_FLR (0x1U << 15U)

View File

@ -672,6 +672,7 @@ struct acrn_intr_monitor {
struct vrp_config
{
uint16_t phy_bdf;
uint8_t max_payload; /* dev cap's max payload */
uint8_t primary_bus;
uint8_t secondary_bus;
uint8_t subordinate_bus;