mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
VT-d: Improve page table debug output
Ignore 'current' domain when dumping VT-d page tables. Also add page type summary for domain pages output. Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com>
This commit is contained in:
1 parent
70a2ba87b7
commit
ea3cb6b367
3 files changed
+87
-98
No files matched your search
@@ -27,8 +27,7 @@ extern struct qi_ctrl *qi_ctrl;
|
||||
extern struct ir_ctrl *ir_ctrl;
|
||||
|
||||
void print_iommu_regs(struct acpi_drhd_unit *drhd);
|
||||
void print_vtd_entries(struct domain *d, struct iommu *iommu,
|
||||
int bus, int devfn, unsigned long gmfn);
|
||||
void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn);
|
||||
void pdev_flr(u8 bus, u8 devfn);
|
||||
|
||||
int qinval_setup(struct iommu *iommu);
|
||||
|
||||
@@ -777,16 +777,17 @@ int iommu_disable_translation(struct iommu *iommu)
|
||||
|
||||
static struct iommu *vector_to_iommu[NR_VECTORS];
|
||||
static int iommu_page_fault_do_one(struct iommu *iommu, int type,
|
||||
u8 fault_reason, u16 source_id, u32 addr)
|
||||
u8 fault_reason, u16 source_id, u64 addr)
|
||||
{
|
||||
dprintk(XENLOG_WARNING VTDPREFIX,
|
||||
"iommu_fault:%s: %x:%x.%x addr %x REASON %x iommu->reg = %p\n",
|
||||
"iommu_fault:%s: %x:%x.%x addr %"PRIx64" REASON %x "
|
||||
"iommu->reg = %p\n",
|
||||
(type ? "DMA Read" : "DMA Write"), (source_id >> 8),
|
||||
PCI_SLOT(source_id & 0xFF), PCI_FUNC(source_id & 0xFF), addr,
|
||||
fault_reason, iommu->reg);
|
||||
|
||||
if ( fault_reason < 0x20 )
|
||||
print_vtd_entries(current->domain, iommu, (source_id >> 8),
|
||||
print_vtd_entries(iommu, (source_id >> 8),
|
||||
(source_id & 0xff), (addr >> PAGE_SHIFT));
|
||||
|
||||
return 0;
|
||||
@@ -844,7 +845,8 @@ static void iommu_page_fault(int vector, void *dev_id,
|
||||
{
|
||||
u8 fault_reason;
|
||||
u16 source_id;
|
||||
u32 guest_addr, data;
|
||||
u32 data;
|
||||
u64 guest_addr;
|
||||
int type;
|
||||
|
||||
/* highest 32 bits */
|
||||
|
||||
@@ -213,109 +213,97 @@ u32 get_level_index(unsigned long gmfn, int level)
|
||||
return gmfn & LEVEL_MASK;
|
||||
}
|
||||
|
||||
void print_vtd_entries(
|
||||
struct domain *d,
|
||||
struct iommu *iommu,
|
||||
int bus, int devfn,
|
||||
unsigned long gmfn)
|
||||
void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn)
|
||||
{
|
||||
struct hvm_iommu *hd = domain_hvm_iommu(d);
|
||||
struct acpi_drhd_unit *drhd;
|
||||
struct context_entry *ctxt_entry;
|
||||
struct root_entry *root_entry;
|
||||
struct dma_pte pte;
|
||||
u64 *l;
|
||||
u32 l_index;
|
||||
u32 i = 0;
|
||||
int level = agaw_to_level(hd->agaw);
|
||||
u32 l_index, level;
|
||||
|
||||
printk("print_vtd_entries: domain_id = %x bdf = %x:%x:%x gmfn = %lx\n",
|
||||
d->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
|
||||
printk("print_vtd_entries: iommu = %p bdf = %x:%x:%x gmfn = %"PRIx64"\n",
|
||||
iommu, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
|
||||
|
||||
if ( hd->pgd_maddr == 0 )
|
||||
if ( iommu->root_maddr == 0 )
|
||||
{
|
||||
printk(" hd->pgd_maddr == 0\n");
|
||||
printk(" iommu->root_maddr = 0\n");
|
||||
return;
|
||||
}
|
||||
printk(" hd->pgd_maddr = %"PRIx64"\n", hd->pgd_maddr);
|
||||
|
||||
for_each_drhd_unit ( drhd )
|
||||
{
|
||||
printk("---- print_vtd_entries %d ----\n", i++);
|
||||
|
||||
if ( iommu->root_maddr == 0 )
|
||||
{
|
||||
printk(" iommu->root_maddr = 0\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
root_entry =
|
||||
(struct root_entry *)map_vtd_domain_page(iommu->root_maddr);
|
||||
root_entry = (struct root_entry *)map_vtd_domain_page(iommu->root_maddr);
|
||||
|
||||
printk(" root_entry = %p\n", root_entry);
|
||||
printk(" root_entry[%x] = %"PRIx64"\n", bus, root_entry[bus].val);
|
||||
if ( !root_present(root_entry[bus]) )
|
||||
{
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" root_entry[%x] not present\n", bus);
|
||||
continue;
|
||||
}
|
||||
|
||||
ctxt_entry =
|
||||
(struct context_entry *)map_vtd_domain_page(root_entry[bus].val);
|
||||
if ( ctxt_entry == NULL )
|
||||
{
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" ctxt_entry == NULL\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
printk(" context = %p\n", ctxt_entry);
|
||||
printk(" context[%x] = %"PRIx64" %"PRIx64"\n",
|
||||
devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
|
||||
if ( !context_present(ctxt_entry[devfn]) )
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" ctxt_entry[%x] not present\n", devfn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( level != VTD_PAGE_TABLE_LEVEL_3 &&
|
||||
level != VTD_PAGE_TABLE_LEVEL_4)
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk("Unsupported VTD page table level (%d)!\n", level);
|
||||
continue;
|
||||
}
|
||||
|
||||
l = maddr_to_virt(ctxt_entry[devfn].lo);
|
||||
do
|
||||
{
|
||||
l = (u64*)(((unsigned long)l >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
|
||||
printk(" l%d = %p\n", level, l);
|
||||
if ( l == NULL )
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" l%d == NULL\n", level);
|
||||
break;
|
||||
}
|
||||
l_index = get_level_index(gmfn, level);
|
||||
printk(" l%d_index = %x\n", level, l_index);
|
||||
printk(" l%d[%x] = %"PRIx64"\n", level, l_index, l[l_index]);
|
||||
|
||||
pte.val = l[l_index];
|
||||
if ( !dma_pte_present(pte) )
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" l%d[%x] not present\n", level, l_index);
|
||||
break;
|
||||
}
|
||||
|
||||
l = maddr_to_virt(l[l_index]);
|
||||
} while ( --level );
|
||||
printk(" root_entry = %p\n", root_entry);
|
||||
printk(" root_entry[%x] = %"PRIx64"\n", bus, root_entry[bus].val);
|
||||
if ( !root_present(root_entry[bus]) )
|
||||
{
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" root_entry[%x] not present\n", bus);
|
||||
return;
|
||||
}
|
||||
|
||||
ctxt_entry =
|
||||
(struct context_entry *)map_vtd_domain_page(root_entry[bus].val);
|
||||
if ( ctxt_entry == NULL )
|
||||
{
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" ctxt_entry == NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(" context = %p\n", ctxt_entry);
|
||||
printk(" context[%x] = %"PRIx64"_%"PRIx64"\n",
|
||||
devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
|
||||
if ( !context_present(ctxt_entry[devfn]) )
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" ctxt_entry[%x] not present\n", devfn);
|
||||
return;
|
||||
}
|
||||
|
||||
level = agaw_to_level(context_address_width(ctxt_entry[devfn]));
|
||||
if ( level != VTD_PAGE_TABLE_LEVEL_3 &&
|
||||
level != VTD_PAGE_TABLE_LEVEL_4)
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk("Unsupported VTD page table level (%d)!\n", level);
|
||||
}
|
||||
|
||||
l = maddr_to_virt(ctxt_entry[devfn].lo);
|
||||
do
|
||||
{
|
||||
l = (u64*)(((unsigned long)l >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
|
||||
printk(" l%d = %p\n", level, l);
|
||||
if ( l == NULL )
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" l%d == NULL\n", level);
|
||||
break;
|
||||
}
|
||||
l_index = get_level_index(gmfn, level);
|
||||
printk(" l%d_index = %x\n", level, l_index);
|
||||
printk(" l%d[%x] = %"PRIx64"\n", level, l_index, l[l_index]);
|
||||
|
||||
pte.val = l[l_index];
|
||||
if ( !dma_pte_present(pte) )
|
||||
{
|
||||
unmap_vtd_domain_page(ctxt_entry);
|
||||
unmap_vtd_domain_page(root_entry);
|
||||
printk(" l%d[%x] not present\n", level, l_index);
|
||||
break;
|
||||
}
|
||||
|
||||
l = maddr_to_virt(l[l_index]);
|
||||
} while ( --level );
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||