xen-devel.lists.xenproject.org archive mirror
 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
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
2011-12-23 11:29   ` [PATCH 00 of 16] [V2] amd iommu: support ATS device passthru on IOMMUv2 systems 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
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
2011-12-23 11:29     ` [PATCH 16 of 16] libxl: pass iommu parameter to qemu-dm Wei Wang
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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).