AMD IOMMU: add event handling code
This patch adds code for polling and printing out events generated by the AMD IOMMU. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Родитель
a80dc3e0e0
Коммит
90008ee4b8
|
@ -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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче