aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-07-31 09:48:46 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-07-31 09:48:46 +0100
commitc7e9fa23fd0623fb45e80fa873da1765a1ee4d4b (patch)
tree2d8a04dff76bca0cb336b4196415a6f903645423
parentcd1f9abc4a88725a7a889c80ecaa2a64804816c4 (diff)
downloadxen-c7e9fa23fd0623fb45e80fa873da1765a1ee4d4b.tar.gz
xen-c7e9fa23fd0623fb45e80fa873da1765a1ee4d4b.tar.bz2
xen-c7e9fa23fd0623fb45e80fa873da1765a1ee4d4b.zip
vtd: Add a debug key 'V' to dump some iommu info.
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
-rw-r--r--xen/drivers/passthrough/vtd/extern.h1
-rw-r--r--xen/drivers/passthrough/vtd/iommu.c3
-rw-r--r--xen/drivers/passthrough/vtd/utils.c106
3 files changed, 110 insertions, 0 deletions
diff --git a/xen/drivers/passthrough/vtd/extern.h b/xen/drivers/passthrough/vtd/extern.h
index 0220ae97b3..19091216e9 100644
--- a/xen/drivers/passthrough/vtd/extern.h
+++ b/xen/drivers/passthrough/vtd/extern.h
@@ -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);
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index b5454f4108..8de32f476b 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -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:
diff --git a/xen/drivers/passthrough/vtd/utils.c b/xen/drivers/passthrough/vtd/utils.c
index 9f26c1a088..96710eb627 100644
--- a/xen/drivers/passthrough/vtd/utils.c
+++ b/xen/drivers/passthrough/vtd/utils.c
@@ -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