[PATCH 10/23] AMD IOMMU: add event handling code

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Joerg Roedel
Date: Wednesday, September 17, 2008 - 9:52 am

This patch adds code for polling and printing out events generated by
the AMD IOMMU.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
 arch/x86/kernel/amd_iommu.c       |   87 ++++++++++++++++++++++++++++++++++++-
 arch/x86/kernel/amd_iommu_init.c  |    1 -
 include/asm-x86/amd_iommu_types.h |   22 +++++++++
 3 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 3caef6b..71e20ad 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -55,9 +55,94 @@ static int iommu_has_npcache(struct amd_iommu *iommu)
  *
  ****************************************************************************/
 
+static void iommu_print_event(void *__evt)
+{
+	u32 *event = __evt;
+	int type  = (event[1] >> EVENT_TYPE_SHIFT)  & EVENT_TYPE_MASK;
+	int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
+	int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
+	int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
+	u64 address = (u64)(((u64)event[3]) << 32) | event[2];
+
+	printk(KERN_ERR "AMD IOMMU: Event logged [");
+
+	switch (type) {
+	case EVENT_TYPE_ILL_DEV:
+		printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
+		       "address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address, flags);
+		break;
+	case EVENT_TYPE_IO_FAULT:
+		printk("IO_PAGE_FAULT device=%02x:%02x.%x "
+		       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       domid, address, flags);
+		break;
+	case EVENT_TYPE_DEV_TAB_ERR:
+		printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
+		       "address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address, flags);
+		break;
+	case EVENT_TYPE_PAGE_TAB_ERR:
+		printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
+		       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       domid, address, flags);
+		break;
+	case EVENT_TYPE_ILL_CMD:
+		printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
+		break;
+	case EVENT_TYPE_CMD_HARD_ERR:
+		printk("COMMAND_HARDWARE_ERROR address=0x%016llx "
+		       "flags=0x%04x]\n", address, flags);
+		break;
+	case EVENT_TYPE_IOTLB_INV_TO:
+		printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
+		       "address=0x%016llx]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address);
+		break;
+	case EVENT_TYPE_INV_DEV_REQ:
+		printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
+		       "address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address, flags);
+		break;
+	default:
+		printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
+	}
+}
+
+static void iommu_poll_events(struct amd_iommu *iommu)
+{
+	u32 head, tail;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
+	tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
+
+	while (head != tail) {
+		iommu_print_event(iommu->evt_buf + head);
+		head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size;
+	}
+
+	writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
 irqreturn_t amd_iommu_int_handler(int irq, void *data)
 {
-	return IRQ_NONE;
+	struct amd_iommu *iommu;
+
+	list_for_each_entry(iommu, &amd_iommu_list, list)
+		iommu_poll_events(iommu);
+
+	return IRQ_HANDLED;
 }
 
 /****************************************************************************
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index ce3130d..07709a9 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -32,7 +32,6 @@
 /*
  * definitions for the ACPI scanning code
  */
-#define PCI_BUS(x) (((x) >> 8) & 0xff)
 #define IVRS_HEADER_LENGTH 48
 
 #define ACPI_IVHD_TYPE                  0x10
diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h
index 6ed8ffa..1c9d8d4 100644
--- a/include/asm-x86/amd_iommu_types.h
+++ b/include/asm-x86/amd_iommu_types.h
@@ -71,6 +71,25 @@
 /* MMIO status bits */
 #define MMIO_STATUS_COM_WAIT_INT_MASK	0x04
 
+/* event logging constants */
+#define EVENT_ENTRY_SIZE	0x10
+#define EVENT_TYPE_SHIFT	28
+#define EVENT_TYPE_MASK		0xf
+#define EVENT_TYPE_ILL_DEV	0x1
+#define EVENT_TYPE_IO_FAULT	0x2
+#define EVENT_TYPE_DEV_TAB_ERR	0x3
+#define EVENT_TYPE_PAGE_TAB_ERR	0x4
+#define EVENT_TYPE_ILL_CMD	0x5
+#define EVENT_TYPE_CMD_HARD_ERR	0x6
+#define EVENT_TYPE_IOTLB_INV_TO	0x7
+#define EVENT_TYPE_INV_DEV_REQ	0x8
+#define EVENT_DEVID_MASK	0xffff
+#define EVENT_DEVID_SHIFT	0
+#define EVENT_DOMID_MASK	0xffff
+#define EVENT_DOMID_SHIFT	0
+#define EVENT_FLAGS_MASK	0xfff
+#define EVENT_FLAGS_SHIFT	0x10
+
 /* feature control bits */
 #define CONTROL_IOMMU_EN        0x00ULL
 #define CONTROL_HT_TUN_EN       0x01ULL
@@ -165,6 +184,9 @@
 
 #define MAX_DOMAIN_ID 65536
 
+/* FIXME: move this macro to <linux/pci.h> */
+#define PCI_BUS(x) (((x) >> 8) & 0xff)
+
 /*
  * This structure contains generic data for  IOMMU protection domains
  * independent of their use.
-- 
1.5.6.4


--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH 0/23] AMD IOMMU 2.6.28 updates for review, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 06/23] AMD IOMMU: add event buffer allocation, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 08/23] AMD IOMMU: save pci_dev instead of devid, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 09/23] AMD IOMMU: add MSI interrupt support, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 10/23] AMD IOMMU: add event handling code, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 11/23] AMD IOMMU: enable event logging, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 13/23] AMD IOMMU: add dma_supported callback, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 18/23] AMD IOMMU: simplify dma_mask_to_pages, Joerg Roedel, (Wed Sep 17, 9:52 am)
[PATCH 23/23] add AMD IOMMU tree to MAINTAINERS file, Joerg Roedel, (Wed Sep 17, 9:52 am)
Re: [PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, FUJITA Tomonori, (Wed Sep 17, 12:20 pm)
Re: [PATCH 18/23] AMD IOMMU: simplify dma_mask_to_pages, FUJITA Tomonori, (Wed Sep 17, 12:20 pm)
Re: [PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, FUJITA Tomonori, (Wed Sep 17, 6:29 pm)
Re: [PATCH 18/23] AMD IOMMU: simplify dma_mask_to_pages, Joerg Roedel, (Thu Sep 18, 12:32 am)
Re: [PATCH 18/23] AMD IOMMU: simplify dma_mask_to_pages, FUJITA Tomonori, (Thu Sep 18, 8:57 am)
Re: [PATCH 18/23] AMD IOMMU: simplify dma_mask_to_pages, Joerg Roedel, (Thu Sep 18, 9:39 am)
Re: [PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, FUJITA Tomonori, (Thu Sep 18, 4:10 pm)
Re: [PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, FUJITA Tomonori, (Fri Sep 19, 3:21 am)
Re: [PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, FUJITA Tomonori, (Fri Sep 19, 11:40 am)
RE: [PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, Keshavamurthy, Anil S, (Fri Sep 19, 11:47 am)
Re: [PATCH 03/23] AMD IOMMU: implement lazy IO/TLB flushing, Muli Ben-Yehuda, (Sat Sep 20, 10:27 pm)