diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-07-31 09:48:46 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-07-31 09:48:46 +0100 |
commit | c7e9fa23fd0623fb45e80fa873da1765a1ee4d4b (patch) | |
tree | 2d8a04dff76bca0cb336b4196415a6f903645423 | |
parent | cd1f9abc4a88725a7a889c80ecaa2a64804816c4 (diff) | |
download | xen-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.h | 1 | ||||
-rw-r--r-- | xen/drivers/passthrough/vtd/iommu.c | 3 | ||||
-rw-r--r-- | xen/drivers/passthrough/vtd/utils.c | 106 |
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 |