aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/amd_iommu.c87
-rw-r--r--arch/x86/kernel/amd_iommu_init.c1
-rw-r--r--include/asm-x86/amd_iommu_types.h22
3 files changed, 108 insertions, 2 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 0e494b9d5f20..0cb8fd2359f5 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)
55 * 55 *
56 ****************************************************************************/ 56 ****************************************************************************/
57 57
58static void iommu_print_event(void *__evt)
59{
60 u32 *event = __evt;
61 int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
62 int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
63 int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
64 int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
65 u64 address = (u64)(((u64)event[3]) << 32) | event[2];
66
67 printk(KERN_ERR "AMD IOMMU: Event logged [");
68
69 switch (type) {
70 case EVENT_TYPE_ILL_DEV:
71 printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
72 "address=0x%016llx flags=0x%04x]\n",
73 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
74 address, flags);
75 break;
76 case EVENT_TYPE_IO_FAULT:
77 printk("IO_PAGE_FAULT device=%02x:%02x.%x "
78 "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
79 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
80 domid, address, flags);
81 break;
82 case EVENT_TYPE_DEV_TAB_ERR:
83 printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
84 "address=0x%016llx flags=0x%04x]\n",
85 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
86 address, flags);
87 break;
88 case EVENT_TYPE_PAGE_TAB_ERR:
89 printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
90 "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
91 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
92 domid, address, flags);
93 break;
94 case EVENT_TYPE_ILL_CMD:
95 printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
96 break;
97 case EVENT_TYPE_CMD_HARD_ERR:
98 printk("COMMAND_HARDWARE_ERROR address=0x%016llx "
99 "flags=0x%04x]\n", address, flags);
100 break;
101 case EVENT_TYPE_IOTLB_INV_TO:
102 printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
103 "address=0x%016llx]\n",
104 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
105 address);
106 break;
107 case EVENT_TYPE_INV_DEV_REQ:
108 printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
109 "address=0x%016llx flags=0x%04x]\n",
110 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
111 address, flags);
112 break;
113 default:
114 printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
115 }
116}
117
118static void iommu_poll_events(struct amd_iommu *iommu)
119{
120 u32 head, tail;
121 unsigned long flags;
122
123 spin_lock_irqsave(&iommu->lock, flags);
124
125 head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
126 tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
127
128 while (head != tail) {
129 iommu_print_event(iommu->evt_buf + head);
130 head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size;
131 }
132
133 writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
134
135 spin_unlock_irqrestore(&iommu->lock, flags);
136}
137
58irqreturn_t amd_iommu_int_handler(int irq, void *data) 138irqreturn_t amd_iommu_int_handler(int irq, void *data)
59{ 139{
60 return IRQ_NONE; 140 struct amd_iommu *iommu;
141
142 list_for_each_entry(iommu, &amd_iommu_list, list)
143 iommu_poll_events(iommu);
144
145 return IRQ_HANDLED;
61} 146}
62 147
63/**************************************************************************** 148/****************************************************************************
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 14a06464a694..eed488892c01 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -32,7 +32,6 @@
32/* 32/*
33 * definitions for the ACPI scanning code 33 * definitions for the ACPI scanning code
34 */ 34 */
35#define PCI_BUS(x) (((x) >> 8) & 0xff)
36#define IVRS_HEADER_LENGTH 48 35#define IVRS_HEADER_LENGTH 48
37 36
38#define ACPI_IVHD_TYPE 0x10 37#define ACPI_IVHD_TYPE 0x10
diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h
index 8533f09b34b7..d8c5a6c69955 100644
--- a/include/asm-x86/amd_iommu_types.h
+++ b/include/asm-x86/amd_iommu_types.h
@@ -71,6 +71,25 @@
71/* MMIO status bits */ 71/* MMIO status bits */
72#define MMIO_STATUS_COM_WAIT_INT_MASK 0x04 72#define MMIO_STATUS_COM_WAIT_INT_MASK 0x04
73 73
74/* event logging constants */
75#define EVENT_ENTRY_SIZE 0x10
76#define EVENT_TYPE_SHIFT 28
77#define EVENT_TYPE_MASK 0xf
78#define EVENT_TYPE_ILL_DEV 0x1
79#define EVENT_TYPE_IO_FAULT 0x2
80#define EVENT_TYPE_DEV_TAB_ERR 0x3
81#define EVENT_TYPE_PAGE_TAB_ERR 0x4
82#define EVENT_TYPE_ILL_CMD 0x5
83#define EVENT_TYPE_CMD_HARD_ERR 0x6
84#define EVENT_TYPE_IOTLB_INV_TO 0x7
85#define EVENT_TYPE_INV_DEV_REQ 0x8
86#define EVENT_DEVID_MASK 0xffff
87#define EVENT_DEVID_SHIFT 0
88#define EVENT_DOMID_MASK 0xffff
89#define EVENT_DOMID_SHIFT 0
90#define EVENT_FLAGS_MASK 0xfff
91#define EVENT_FLAGS_SHIFT 0x10
92
74/* feature control bits */ 93/* feature control bits */
75#define CONTROL_IOMMU_EN 0x00ULL 94#define CONTROL_IOMMU_EN 0x00ULL
76#define CONTROL_HT_TUN_EN 0x01ULL 95#define CONTROL_HT_TUN_EN 0x01ULL
@@ -165,6 +184,9 @@
165 184
166#define MAX_DOMAIN_ID 65536 185#define MAX_DOMAIN_ID 65536
167 186
187/* FIXME: move this macro to <linux/pci.h> */
188#define PCI_BUS(x) (((x) >> 8) & 0xff)
189
168/* 190/*
169 * This structure contains generic data for IOMMU protection domains 191 * This structure contains generic data for IOMMU protection domains
170 * independent of their use. 192 * independent of their use.