Before Jailhouse claims devices, disable AER reporting altogether on them, because otherwise they could hit their root complexes, which would be in the root cell. When the hypervisor is disabled, turn back whatever values where on those previous configurations.
Signed-off-by: Gustavo Lima Chaves <[email protected]> --- hypervisor/include/jailhouse/pci.h | 12 +++++++++ hypervisor/pci.c | 54 +++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/hypervisor/include/jailhouse/pci.h b/hypervisor/include/jailhouse/pci.h index 720ecacd..bed1498a 100644 --- a/hypervisor/include/jailhouse/pci.h +++ b/hypervisor/include/jailhouse/pci.h @@ -39,6 +39,14 @@ #define PCI_CAP_MSIX 0x11 #define PCI_CAP_EXPRESS 0x10 +#define PCI_CAP_PCIE 0x10 +#define PCIE_CONTROL_REG 0x08 + +#define PCIE_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ +#define PCIE_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ +#define PCIE_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */ +#define PCIE_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ + #define PCI_IVSHMEM_NUM_MMIO_REGIONS 2 struct cell; @@ -131,6 +139,10 @@ struct pci_device { /** Shadow BAR */ u32 bar[PCI_NUM_BARS]; + /** Shadow state of Device Control Register. */ + u16 dev_ctrl_reg; + bool aer_override; + /** Shadow state of MSI config space registers. */ union pci_msi_registers msi_registers; diff --git a/hypervisor/pci.c b/hypervisor/pci.c index 60d877fc..00ba041f 100644 --- a/hypervisor/pci.c +++ b/hypervisor/pci.c @@ -538,6 +538,55 @@ static void pci_restore_msix(struct pci_device *device, pci_suppress_msix(device, cap, false); } +static const struct jailhouse_pci_capability *pci_get_cap(struct pci_device *device, u16 cap_id) +{ + const struct jailhouse_pci_capability *cap; + unsigned int n; + + for_each_pci_cap(cap, device, n) + if (cap->id == cap_id) + return cap; + + return NULL; +} + +static void pci_suppress_aer(struct pci_device *device) +{ + const struct jailhouse_pci_capability *cap; + u16 bdf = device->info->bdf; + u16 dev_ctrl_reg; + + cap = pci_get_cap(device, PCI_CAP_EXPRESS); + if (!cap) + return; + + device->dev_ctrl_reg = pci_read_config(bdf, cap->start + + PCIE_CONTROL_REG, + sizeof(device->dev_ctrl_reg)); + dev_ctrl_reg = device->dev_ctrl_reg; + dev_ctrl_reg &= ~(PCIE_DEVCTL_CERE | PCIE_DEVCTL_NFERE | + PCIE_DEVCTL_FERE | PCIE_DEVCTL_URRE); + device->aer_override = true; + + pci_write_config(bdf, cap->start + PCIE_CONTROL_REG, dev_ctrl_reg, + sizeof(dev_ctrl_reg)); +} + +static void pci_restore_aer(struct pci_device *device) +{ + const struct jailhouse_pci_capability *cap; + + if (!device->aer_override) + return; + + cap = pci_get_cap(device, PCI_CAP_EXPRESS); + if (!cap) + return; + + pci_write_config(device->info->bdf, cap->start + PCIE_CONTROL_REG, + device->dev_ctrl_reg, sizeof(device->dev_ctrl_reg)); +} + /** * Prepare the handover of PCI devices to Jailhouse or back to Linux. */ @@ -726,8 +775,10 @@ int pci_cell_init(struct cell *cell) root_device = pci_get_assigned_device(&root_cell, dev_infos[ndev].bdf); - if (root_device) + if (root_device) { + pci_suppress_aer(root_device); pci_remove_physical_device(root_device); + } err = pci_add_physical_device(cell, device); if (err) @@ -799,6 +850,7 @@ void pci_cell_exit(struct cell *cell) } else { pci_remove_physical_device(device); pci_return_device_to_root_cell(device); + pci_restore_aer(device); } } -- 2.14.3 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
