diff options
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 87 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 1 | ||||
-rw-r--r-- | 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 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 | ||
58 | static 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 | |||
118 | static 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 | |||
58 | irqreturn_t amd_iommu_int_handler(int irq, void *data) | 138 | irqreturn_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. |