All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wei Wang <wei.wang2@amd.com>
To: JBeulich@suse.com, Ian.Jackson@eu.citrix.com,
	Ian.Campbell@citrix.com, keir@xen.org
Cc: xen-devel@lists.xensource.com
Subject: [PATCH 06 of 14 V3] amd iommu: add ppr log processing into iommu interrupt handling
Date: Tue, 10 Jan 2012 18:07:12 +0100	[thread overview]
Message-ID: <3d252e3969bae12e85e5.1326215232@gran.amd.com> (raw)
In-Reply-To: <patchbomb.1326215226@gran.amd.com>

# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1326213597 -3600
# Node ID 3d252e3969bae12e85e5a1f2f339dad169d0d892
# Parent  e698b7b63a9dc75c5cad4dbe02d38d90bdaf1512
amd iommu: add ppr log processing into iommu interrupt handling
PPR log and event log share the same interrupt source. Interrupt handler
should check both of them.

Signed-off-by: Wei Wang <wei.wang2@amd.com>

diff -r e698b7b63a9d -r 3d252e3969ba xen/drivers/passthrough/amd/iommu_init.c
--- a/xen/drivers/passthrough/amd/iommu_init.c	Tue Jan 10 17:39:53 2012 +0100
+++ b/xen/drivers/passthrough/amd/iommu_init.c	Tue Jan 10 17:39:57 2012 +0100
@@ -355,75 +355,92 @@ static void set_iommu_ppr_log_control(st
         AMD_IOMMU_DEBUG("PPR Log Enabled.\n");
 }
 
-static void parse_event_log_entry(struct amd_iommu *, u32 entry[]);
+/* read event log or ppr log from iommu ring buffer */
+static int iommu_read_log(struct amd_iommu *iommu, 
+                          struct ring_buffer *log,
+                          unsigned int entry_size,
+                          void (*parse_func)(struct amd_iommu *, u32 *))
+{
+    u32 tail, head, *entry, tail_offest, head_offset;
 
-static int amd_iommu_read_event_log(struct amd_iommu *iommu)
-{
-    u32 tail, head, *event_log;
-
-    BUG_ON( !iommu );
+    BUG_ON( !iommu || ((log != &iommu->event_log) && 
+            (log != &iommu->ppr_log)) );
 
     /* make sure there's an entry in the log */
-    tail = readl(iommu->mmio_base + IOMMU_EVENT_LOG_TAIL_OFFSET);
-    tail = get_field_from_reg_u32(tail,
-                                  IOMMU_EVENT_LOG_TAIL_MASK,
-                                  IOMMU_EVENT_LOG_TAIL_SHIFT);
+    tail_offest = ( log == &iommu->event_log ) ?
+        IOMMU_EVENT_LOG_TAIL_OFFSET:
+        IOMMU_PPR_LOG_TAIL_OFFSET;
 
-    while ( tail != iommu->event_log.head )
+    head_offset = ( log == &iommu->event_log ) ?
+        IOMMU_EVENT_LOG_HEAD_OFFSET:
+        IOMMU_PPR_LOG_HEAD_OFFSET;
+
+    tail = readl(iommu->mmio_base + tail_offest);
+    tail = iommu_get_rb_pointer(tail);
+
+    while ( tail != log->head )
     {
         /* read event log entry */
-        event_log = (u32 *)(iommu->event_log.buffer +
-                           (iommu->event_log.head *
-                           IOMMU_EVENT_LOG_ENTRY_SIZE));
+        entry = (u32 *)(log->buffer + log->head * entry_size);
 
-        parse_event_log_entry(iommu, event_log);
-
-        if ( ++iommu->event_log.head == iommu->event_log.entries )
-            iommu->event_log.head = 0;
+        parse_func(iommu, entry);
+        if ( ++log->head == log->entries )
+            log->head = 0;
 
         /* update head pointer */
-        set_field_in_reg_u32(iommu->event_log.head, 0,
-                             IOMMU_EVENT_LOG_HEAD_MASK,
-                             IOMMU_EVENT_LOG_HEAD_SHIFT, &head);
-        writel(head, iommu->mmio_base + IOMMU_EVENT_LOG_HEAD_OFFSET);
+        head = 0;
+        iommu_set_rb_pointer(&head, log->head);
+
+        writel(head, iommu->mmio_base + head_offset);
     }
 
     return 0;
 }
 
-static void amd_iommu_reset_event_log(struct amd_iommu *iommu)
+/* reset event log or ppr log when overflow */
+static void iommu_reset_log(struct amd_iommu *iommu,
+                            struct ring_buffer *log,
+                            void (*ctrl_func)(struct amd_iommu *iommu, int))
 {
     u32 entry;
-    int log_run;
+    int log_run, run_bit, of_bit;
     int loop_count = 1000;
 
+    BUG_ON( !iommu || ((log != &iommu->event_log) && 
+            (log != &iommu->ppr_log)) );
+
+    run_bit = ( log == &iommu->event_log ) ?
+        IOMMU_STATUS_EVENT_LOG_RUN_SHIFT:
+        IOMMU_STATUS_PPR_LOG_RUN_SHIFT;
+
+    of_bit = ( log == &iommu->event_log ) ?
+        IOMMU_STATUS_EVENT_OVERFLOW_SHIFT:
+        IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT;
+
     /* wait until EventLogRun bit = 0 */
     do {
         entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
-        log_run = iommu_get_bit(entry, IOMMU_STATUS_EVENT_LOG_RUN_SHIFT);
+        log_run = iommu_get_bit(entry, run_bit);
         loop_count--;
     } while ( log_run && loop_count );
 
     if ( log_run )
     {
-        AMD_IOMMU_DEBUG("Warning: EventLogRun bit is not cleared"
-                        "before reset!\n");
+        AMD_IOMMU_DEBUG("Warning: Log Run bit %d is not cleared"
+                        "before reset! \n", run_bit);
         return;
     }
 
-    set_iommu_event_log_control(iommu, IOMMU_CONTROL_DISABLED);
+    ctrl_func(iommu, IOMMU_CONTROL_DISABLED);
 
-    /* read event log for debugging */
-    amd_iommu_read_event_log(iommu);
     /*clear overflow bit */
-    iommu_clear_bit(&entry, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT);
-
-    writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET);
+    iommu_clear_bit(&entry, of_bit);
+    writel(entry, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
 
     /*reset event log base address */
-    iommu->event_log.head = 0;
+    log->head = 0;
 
-    set_iommu_event_log_control(iommu, IOMMU_CONTROL_ENABLED);
+    ctrl_func(iommu, IOMMU_CONTROL_ENABLED);
 }
 
 static void iommu_msi_set_affinity(struct irq_desc *desc, const cpumask_t *mask)
@@ -595,30 +612,95 @@ static void parse_event_log_entry(struct
     }
 }
 
-static void amd_iommu_page_fault(int irq, void *dev_id,
-                             struct cpu_user_regs *regs)
+static void iommu_check_event_log(struct amd_iommu *iommu)
 {
     u32 entry;
     unsigned long flags;
-    struct amd_iommu *iommu = dev_id;
 
     spin_lock_irqsave(&iommu->lock, flags);
-    amd_iommu_read_event_log(iommu);
+
+    iommu_read_log(iommu, &iommu->event_log, 
+                   sizeof(event_entry_t), parse_event_log_entry);
 
     /*check event overflow */
     entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
 
     if ( iommu_get_bit(entry, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT) )
-        amd_iommu_reset_event_log(iommu);
+        iommu_reset_log(iommu, &iommu->event_log, set_iommu_event_log_control);
 
     /* reset interrupt status bit */
     entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
     iommu_set_bit(&entry, IOMMU_STATUS_EVENT_LOG_INT_SHIFT);
 
-    writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET);
+    writel(entry, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
+
     spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
+void parse_ppr_log_entry(struct amd_iommu *iommu, u32 entry[])
+{
+
+    u16 device_id;
+    u8 bus, devfn;
+    struct pci_dev *pdev;
+    struct domain *d;
+
+    /* here device_id is physical value */
+    device_id = iommu_get_devid_from_cmd(entry[0]);
+    bus = device_id >> 8;
+    devfn = device_id & 0xFF;
+
+    local_irq_enable();
+
+    spin_lock(&pcidevs_lock);
+    pdev = pci_get_pdev(0, bus, devfn);
+    spin_unlock(&pcidevs_lock);
+
+    local_irq_disable();
+
+    if ( pdev == NULL )
+        return; 
+
+    d = pdev->domain;
+
+    guest_iommu_add_ppr_log(d, entry);
+}
+
+static void iommu_check_ppr_log(struct amd_iommu *iommu)
+{
+    u32 entry;
+    unsigned long flags;
+
+    spin_lock_irqsave(&iommu->lock, flags);
+
+    iommu_read_log(iommu, &iommu->ppr_log, 
+                   sizeof(ppr_entry_t), parse_ppr_log_entry);
+
+    /*check event overflow */
+    entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
+
+    if ( iommu_get_bit(entry, IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT) )
+        iommu_reset_log(iommu, &iommu->ppr_log, set_iommu_ppr_log_control);
+
+    /* reset interrupt status bit */
+    entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
+    iommu_set_bit(&entry, IOMMU_STATUS_PPR_LOG_INT_SHIFT);
+
+    writel(entry, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
+
+    spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+static void iommu_interrupt_handler(int irq, void *dev_id,
+                                    struct cpu_user_regs *regs)
+{
+    struct amd_iommu *iommu = dev_id;
+    iommu_check_event_log(iommu);
+
+    if ( iommu->ppr_log.buffer != NULL )
+        iommu_check_ppr_log(iommu);
+}
+
 static int __init set_iommu_interrupt_handler(struct amd_iommu *iommu)
 {
     int irq, ret;
@@ -631,8 +713,7 @@ static int __init set_iommu_interrupt_ha
     }
     
     irq_desc[irq].handler = &iommu_msi_type;
-    ret = request_irq(irq, amd_iommu_page_fault, 0,
-                             "amd_iommu", iommu);
+    ret = request_irq(irq, iommu_interrupt_handler, 0, "amd_iommu", iommu);
     if ( ret )
     {
         irq_desc[irq].handler = &no_irq_type;

  parent reply	other threads:[~2012-01-10 17:07 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-10 17:07 [PATCH 00 of 14 V3] amd iommu: support ATS device passthru on IOMMUv2 systems Wei Wang
2011-12-23 11:29 ` [PATCH 00 of 16] [V2] " Wei Wang
2011-12-23 11:29   ` [PATCH 01 of 16] amd iommu: Refactoring iommu ring buffer definition Wei Wang
2012-01-02 12:44     ` Jan Beulich
2011-12-23 11:29   ` [PATCH 02 of 16] amd iommu: Introduces new helper functions to simplify iommu bitwise operations Wei Wang
2012-01-02 12:52     ` Jan Beulich
2011-12-23 11:29   ` [PATCH 03 of 16] amd iommu: Add iommu emulation for hvm guest Wei Wang
2011-12-23 11:29   ` [PATCH 04 of 16] amd iommu: Enable ppr log Wei Wang
2012-01-02 13:10     ` Jan Beulich
2011-12-23 11:29   ` [PATCH 05 of 16] amd iommu: Enable guest level translation Wei Wang
2011-12-23 11:29   ` [PATCH 06 of 16] amd iommu: add ppr log processing into iommu interrupt handling Wei Wang
2012-01-02 13:13     ` Jan Beulich
2012-01-03  8:58       ` Wei Wang2
2011-12-23 11:29   ` [PATCH 07 of 16] amd iommu: Add 2 hypercalls for libxc Wei Wang
2012-01-02 12:15     ` Jan Beulich
2011-12-23 11:29   ` [PATCH 08 of 16] amd iommu: Add a hypercall for hvmloader Wei Wang
2012-01-02 11:41     ` Jan Beulich
2011-12-23 11:29   ` [PATCH 09 of 16] amd iommu: add iommu mmio handler Wei Wang
2012-01-02 11:39     ` Jan Beulich
2011-12-23 11:29   ` [PATCH 10 of 16] amd iommu: Enable FC bit in iommu host level PTE Wei Wang
2012-01-02 11:36     ` Jan Beulich
2012-01-03 10:05       ` Wei Wang2
2012-01-03 10:12         ` Jan Beulich
2012-01-03 10:37           ` Wei Wang2
2011-12-23 11:29   ` [PATCH 11 of 16] amd iommu: Add a new flag to indication iommuv2 feature enabled or not Wei Wang
2012-01-02 11:29     ` Jan Beulich
2011-12-23 11:29   ` [PATCH 12 of 16] hvmloader: Build IVRS table Wei Wang
2011-12-23 11:36     ` Ian Campbell
2011-12-23 11:52       ` Wei Wang2
2011-12-23 11:29   ` [PATCH 13 of 16] libxc: add wrappers for new hypercalls Wei Wang
2011-12-23 11:29   ` [PATCH 14 of 16] libxl: bind virtual bdf to physical bdf after device assignment Wei Wang
2011-12-23 11:37     ` Ian Campbell
2011-12-23 11:56       ` Wei Wang2
2012-01-03 16:03     ` Ian Jackson
2011-12-23 11:29   ` [PATCH 15 of 16] libxl: Introduce a new guest config file parameter Wei Wang
2012-01-03 16:02     ` Ian Jackson
2011-12-23 11:29   ` [PATCH 16 of 16] libxl: pass iommu parameter to qemu-dm Wei Wang
2012-01-10 17:07 ` [PATCH 01 of 14 V3] amd iommu: Refactoring iommu ring buffer definition Wei Wang
2012-01-10 17:07 ` [PATCH 02 of 14 V3] amd iommu: Introduces new helper functions to simplify bitwise operations Wei Wang
2012-01-10 17:07 ` [PATCH 03 of 14 V3] amd iommu: Add iommu emulation for hvm guest Wei Wang
2012-01-12 11:36   ` Jan Beulich
2012-01-16 10:29     ` Wei Wang
2012-01-10 17:07 ` [PATCH 04 of 14 V3] amd iommu: Enable ppr log Wei Wang
2012-01-10 17:07 ` [PATCH 05 of 14 V3] amd iommu: Enable guest level translation Wei Wang
2012-01-10 17:07 ` Wei Wang [this message]
2012-01-10 17:07 ` [PATCH 07 of 14 V3] amd iommu: Add 2 hypercalls for libxc Wei Wang
2012-01-10 17:07 ` [PATCH 08 of 14 V3] amd iommu: Add a new flag to indication iommuv2 feature enabled or not Wei Wang
2012-01-10 17:07 ` [PATCH 09 of 14 V3] amd iommu: Add a hypercall for hvmloader Wei Wang
2012-01-10 17:07 ` [PATCH 10 of 14 V3] amd iommu: Enable FC bit in iommu host level PTE Wei Wang
2012-01-10 17:07 ` [PATCH 11 of 14 V3] hvmloader: Build IVRS table Wei Wang
2012-01-10 17:07 ` [PATCH 12 of 14 V3] libxc: add wrappers for new hypercalls Wei Wang
2012-01-10 17:07 ` [PATCH 13 of 14 V3] libxl: bind virtual bdf to physical bdf after device assignment Wei Wang
2012-01-10 17:13   ` Ian Jackson
2012-01-10 17:35     ` Wei Wang2
2012-01-10 17:07 ` [PATCH 14 of 14 V3] libxl: Introduce a new guest config file parameter Wei Wang
2012-01-10 17:12   ` [PATCH 15 of 16] libxl: Introduce a new guest config file parameter [and 1 more messages] Ian Jackson
2012-01-11 10:20     ` Wei Wang2
2012-01-23 13:59       ` Ian Jackson
2012-01-11  8:43   ` [PATCH 14 of 14 V3] libxl: Introduce a new guest config file parameter Ian Campbell
2012-01-11 10:47     ` Wei Wang2
2012-01-11 15:04 ` [PATCH 00 of 14 V3] amd iommu: support ATS device passthru on IOMMUv2 systems Jan Beulich
2012-01-11 17:36   ` Wei Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3d252e3969bae12e85e5.1326215232@gran.amd.com \
    --to=wei.wang2@amd.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=JBeulich@suse.com \
    --cc=keir@xen.org \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.