IOMMU SNP support introduces two new IOMMU events:
  * RMP Page Fault event
  * RMP Hardware Error event

Hence, add reporting functions for these events.

Cc: Brijesh Singh <brijesh.si...@amd.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpa...@amd.com>
---
 drivers/iommu/amd/amd_iommu_types.h |  2 +
 drivers/iommu/amd/iommu.c           | 67 +++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 4c80483e78ec..1e7966c73707 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -128,6 +128,8 @@
 #define EVENT_TYPE_IOTLB_INV_TO        0x7
 #define EVENT_TYPE_INV_DEV_REQ 0x8
 #define EVENT_TYPE_INV_PPR_REQ 0x9
+#define EVENT_TYPE_RMP_FAULT   0xd
+#define EVENT_TYPE_RMP_HW_ERR  0xe
 #define EVENT_DEVID_MASK       0xffff
 #define EVENT_DEVID_SHIFT      0
 #define EVENT_DOMID_MASK_LO    0xffff
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 9e9898683537..ea64fa8a9418 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -486,6 +486,67 @@ static void dump_command(unsigned long phys_addr)
                pr_err("CMD[%d]: %08x\n", i, cmd->data[i]);
 }
 
+static void amd_iommu_report_rmp_hw_error(volatile u32 *event)
+{
+       struct iommu_dev_data *dev_data = NULL;
+       int devid, vmg_tag, flags;
+       struct pci_dev *pdev;
+       u64 spa;
+
+       devid   = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
+       vmg_tag = (event[1]) & 0xFFFF;
+       flags   = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
+       spa     = ((u64)event[3] << 32) | (event[2] & 0xFFFFFFF8);
+
+       pdev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(devid),
+                                          devid & 0xff);
+       if (pdev)
+               dev_data = dev_iommu_priv_get(&pdev->dev);
+
+       if (dev_data && __ratelimit(&dev_data->rs)) {
+               pci_err(pdev, "Event logged [RMP_HW_ERROR vmg_tag=0x%04x, 
spa=0x%llx, flags=0x%04x]\n",
+                       vmg_tag, spa, flags);
+       } else {
+               pr_err_ratelimited("Event logged [RMP_HW_ERROR 
device=%02x:%02x.%x, vmg_tag=0x%04x, spa=0x%llx, flags=0x%04x]\n",
+                       PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                       vmg_tag, spa, flags);
+       }
+
+       if (pdev)
+               pci_dev_put(pdev);
+}
+
+static void amd_iommu_report_rmp_fault(volatile u32 *event)
+{
+       struct iommu_dev_data *dev_data = NULL;
+       int devid, flags_rmp, vmg_tag, flags;
+       struct pci_dev *pdev;
+       u64 gpa;
+
+       devid     = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
+       flags_rmp = (event[0] >> EVENT_FLAGS_SHIFT) & 0xFF;
+       vmg_tag   = (event[1]) & 0xFFFF;
+       flags     = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
+       gpa       = ((u64)event[3] << 32) | event[2];
+
+       pdev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(devid),
+                                          devid & 0xff);
+       if (pdev)
+               dev_data = dev_iommu_priv_get(&pdev->dev);
+
+       if (dev_data && __ratelimit(&dev_data->rs)) {
+               pci_err(pdev, "Event logged [RMP_PAGE_FAULT vmg_tag=0x%04x, 
gpa=0x%llx, flags_rmp=0x%04x, flags=0x%04x]\n",
+                       vmg_tag, gpa, flags_rmp, flags);
+       } else {
+               pr_err_ratelimited("Event logged [RMP_PAGE_FAULT 
device=%02x:%02x.%x, vmg_tag=0x%04x, gpa=0x%llx, flags_rmp=0x%04x, 
flags=0x%04x]\n",
+                       PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                       vmg_tag, gpa, flags_rmp, flags);
+       }
+
+       if (pdev)
+               pci_dev_put(pdev);
+}
+
 static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
                                        u64 address, int flags)
 {
@@ -577,6 +638,12 @@ static void iommu_print_event(struct amd_iommu *iommu, 
void *__evt)
                        PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                        pasid, address, flags);
                break;
+       case EVENT_TYPE_RMP_FAULT:
+               amd_iommu_report_rmp_fault(event);
+               break;
+       case EVENT_TYPE_RMP_HW_ERR:
+               amd_iommu_report_rmp_hw_error(event);
+               break;
        case EVENT_TYPE_INV_PPR_REQ:
                pasid = PPR_PASID(*((u64 *)__evt));
                tag = event[1] & 0x03FF;
-- 
2.17.1

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to