vtd: Add a debug key 'V' to dump some iommu info.
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 31 Jul 2008 08:48:46 +0000 (09:48 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 31 Jul 2008 08:48:46 +0000 (09:48 +0100)
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
xen/drivers/passthrough/vtd/extern.h
xen/drivers/passthrough/vtd/iommu.c
xen/drivers/passthrough/vtd/utils.c

index 0220ae97b306167472431fabcedc9bd9318ef504..19091216e9ab85788c8c0b70aa93bc87fb4fcb9c 100644 (file)
@@ -28,6 +28,7 @@ extern struct ir_ctrl *ir_ctrl;
 
 void print_iommu_regs(struct acpi_drhd_unit *drhd);
 void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn);
+void dump_iommu_info(unsigned char key);
 
 int qinval_setup(struct iommu *iommu);
 int intremap_setup(struct iommu *iommu);
index b5454f410866e0d56ac1fd68cf3a2ace494ce0d1..8de32f476bb5c2bb051d3e955ff5b904b69dc508 100644 (file)
@@ -28,6 +28,7 @@
 #include <xen/time.h>
 #include <xen/pci.h>
 #include <xen/pci_regs.h>
+#include <xen/keyhandler.h>
 #include <asm/paging.h>
 #include <asm/msi.h>
 #include "iommu.h"
@@ -1765,6 +1766,8 @@ int intel_vtd_setup(void)
 
     init_vtd_hw();
 
+    register_keyhandler('V', dump_iommu_info, "dump iommu info");
+
     return 0;
 
  error:
index 9f26c1a08842d227740eac5047df0118ca05428e..96710eb627d7b74e2d606c375155867230b82363 100644 (file)
@@ -27,6 +27,7 @@
 #include "iommu.h"
 #include "dmar.h"
 #include "vtd.h"
+#include "extern.h"
 
 #define INTEL   0x8086
 #define SEABURG 0x4000
@@ -232,6 +233,111 @@ void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn)
     } while ( --level );
 }
 
+void dump_iommu_info(unsigned char key)
+{
+    struct acpi_drhd_unit *drhd;
+    struct iommu *iommu;
+    int i;
+
+    for_each_drhd_unit ( drhd )
+    {
+        u32 status = 0;
+
+        iommu = drhd->iommu;
+        printk("\niommu %x: nr_pt_levels = %x.\n", iommu->index,
+            iommu->nr_pt_levels);
+
+        if ( ecap_queued_inval(iommu->ecap) ||  ecap_intr_remap(iommu->ecap) )
+            status = dmar_readl(iommu->reg, DMAR_GSTS_REG);
+
+        printk("  Queued Invalidation: %ssupported%s.\n",
+            ecap_queued_inval(iommu->ecap) ? "" : "not ",
+           (status & DMA_GSTS_QIES) ? " and enabled" : "" );
+
+
+        printk("  Interrupt Remapping: %ssupported%s.\n",
+            ecap_intr_remap(iommu->ecap) ? "" : "not ",
+            (status & DMA_GSTS_IRES) ? " and enabled" : "" );
+
+        if ( status & DMA_GSTS_IRES )
+        {
+            /* Dump interrupt remapping table. */
+            u64 iremap_maddr = dmar_readq(iommu->reg, DMAR_IRTA_REG);
+            int nr_entry = 1 << ((iremap_maddr & 0xF) + 1);
+            struct iremap_entry *iremap_entries =
+                (struct iremap_entry *)map_vtd_domain_page(iremap_maddr);
+
+            printk("  Interrupt remapping table (nr_entry=0x%x. "
+                "Only dump P=1 entries here):\n", nr_entry);
+            printk("       SVT  SQ   SID      DST  V  AVL DLM TM RH DM "
+                   "FPD P\n");
+            for ( i = 0; i < nr_entry; i++ )
+            {
+                struct iremap_entry *p = iremap_entries + i;
+
+                if ( !p->lo.p )
+                    continue;
+                printk("  %04x:  %x   %x  %04x %08x %02x    %x   %x  %x  %x  %x"
+                    "   %x %x\n", i,
+                    (u32)p->hi.svt, (u32)p->hi.sq, (u32)p->hi.sid,
+                    (u32)p->lo.dst, (u32)p->lo.vector, (u32)p->lo.avail,
+                    (u32)p->lo.dlm, (u32)p->lo.tm, (u32)p->lo.rh,
+                    (u32)p->lo.dm, (u32)p->lo.fpd, (u32)p->lo.p);
+            }
+
+            unmap_vtd_domain_page(iremap_entries);
+        }
+    }
+
+    /* Dump the I/O xAPIC redirection table(s). */
+    if ( vtd_enabled )
+    {
+        int apic, reg;
+        union IO_APIC_reg_01 reg_01;
+        struct IO_APIC_route_entry rte = { 0 };
+        struct IO_APIC_route_remap_entry *remap;
+        struct ir_ctrl *ir_ctrl;
+
+        for ( apic = 0; apic < nr_ioapics; apic++ )
+        {
+            iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
+            ir_ctrl = iommu_ir_ctrl(iommu);
+            if ( !iommu || !ir_ctrl || ir_ctrl->iremap_maddr == 0 ||
+                ir_ctrl->iremap_index == -1 )
+                continue;
+
+            printk( "\nRedirection table of IOAPIC %x:\n", apic);
+
+            reg = 1; /* IO xAPIC Version Register. */
+            *IO_APIC_BASE(apic) = reg;
+            reg_01.raw = *(IO_APIC_BASE(apic)+4);
+
+            printk("  #entry IDX FMT MASK TRIG IRR POL STAT DELI  VECTOR\n");
+            for ( i = 0; i <= reg_01.bits.entries; i++ )
+            {
+                reg = 0x10 + i*2;
+                *IO_APIC_BASE(apic) = reg;
+                *(((u32 *)&rte) + 0) = *(IO_APIC_BASE(apic)+4);
+
+                *IO_APIC_BASE(apic) = reg + 1;
+                *(((u32 *)&rte) + 1) = *(IO_APIC_BASE(apic)+4);
+
+                remap = (struct IO_APIC_route_remap_entry *) &rte;
+                if ( !remap->format )
+                    continue;
+
+                printk("   %02x:  %04x   %x    %x   %x   %x   %x    %x"
+                    "    %x     %02x\n", i,
+                    (u32)remap->index_0_14 | ((u32)remap->index_15 << 15),
+                    (u32)remap->format, (u32)remap->mask, (u32)remap->trigger,
+                    (u32)remap->irr, (u32)remap->polarity,
+                    (u32)remap->delivery_status, (u32)remap->delivery_mode,
+                    (u32)remap->vector);
+            }
+        }
+    }
+}
+
 /*
  * Local variables:
  * mode: C