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.

Reply via email to