lkml.org 
[lkml]   [2008]   [Sep]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 10/23] AMD IOMMU: add event handling code
    Date
    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



    \
     
     \ /
      Last update: 2008-09-17 19:05    [W:0.040 / U:30.012 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site