[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] AMD/IOMMU: walk trees upon page fault
commit 0e461c2d7f45c50fcf4d26c7730cdd7cde77eb1f Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Fri May 20 12:24:11 2022 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Fri May 20 12:24:11 2022 +0200 AMD/IOMMU: walk trees upon page fault This is to aid diagnosing issues and largely matches VT-d's behavior. Since I'm adding permissions output here as well, take the opportunity and also add their displaying to amd_dump_page_table_level(). Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- xen/drivers/passthrough/amd/iommu.h | 2 ++ xen/drivers/passthrough/amd/iommu_init.c | 3 ++ xen/drivers/passthrough/amd/iommu_map.c | 44 +++++++++++++++++++++++++++++ xen/drivers/passthrough/amd/pci_amd_iommu.c | 5 ++-- 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu.h b/xen/drivers/passthrough/amd/iommu.h index 0a19d6a662..a05dd112bc 100644 --- a/xen/drivers/passthrough/amd/iommu.h +++ b/xen/drivers/passthrough/amd/iommu.h @@ -259,6 +259,8 @@ int __must_check cf_check amd_iommu_flush_iotlb_pages( struct domain *d, dfn_t dfn, unsigned long page_count, unsigned int flush_flags); int __must_check cf_check amd_iommu_flush_iotlb_all(struct domain *d); +void amd_iommu_print_entries(const struct amd_iommu *iommu, unsigned int dev_id, + dfn_t dfn); /* device table functions */ int get_dma_requestor_id(uint16_t seg, uint16_t bdf); diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 7d074ca843..e2166f534f 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -575,6 +575,9 @@ static void cf_check parse_event_log_entry(struct amd_iommu *iommu, u32 entry[]) (flags & 0x002) ? " NX" : "", (flags & 0x001) ? " GN" : ""); + if ( iommu_verbose ) + amd_iommu_print_entries(iommu, device_id, daddr_to_dfn(addr)); + for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ ) if ( get_dma_requestor_id(iommu->seg, bdf) == device_id ) pci_check_disable_device(iommu->seg, PCI_BUS(bdf), diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index a63eec477a..5ad33340e8 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -428,6 +428,50 @@ int cf_check amd_iommu_unmap_page( return 0; } +void amd_iommu_print_entries(const struct amd_iommu *iommu, unsigned int dev_id, + dfn_t dfn) +{ + mfn_t pt_mfn; + unsigned int level; + const struct amd_iommu_dte *dt = iommu->dev_table.buffer; + + if ( !dt[dev_id].tv ) + { + printk("%pp: no root\n", &PCI_SBDF(iommu->seg, dev_id)); + return; + } + + pt_mfn = _mfn(dt[dev_id].pt_root); + level = dt[dev_id].paging_mode; + printk("%pp root @ %"PRI_mfn" (%u levels) dfn=%"PRI_dfn"\n", + &PCI_SBDF(iommu->seg, dev_id), mfn_x(pt_mfn), level, dfn_x(dfn)); + + while ( level ) + { + const union amd_iommu_pte *pt = map_domain_page(pt_mfn); + unsigned int idx = pfn_to_pde_idx(dfn_x(dfn), level); + union amd_iommu_pte pte = pt[idx]; + + unmap_domain_page(pt); + + printk(" L%u[%03x] = %"PRIx64" %c%c\n", level, idx, pte.raw, + pte.pr ? pte.ir ? 'r' : '-' : 'n', + pte.pr ? pte.iw ? 'w' : '-' : 'p'); + + if ( !pte.pr ) + break; + + if ( pte.next_level >= level ) + { + printk(" L%u[%03x]: next: %u\n", level, idx, pte.next_level); + break; + } + + pt_mfn = _mfn(pte.mfn); + level = pte.next_level; + } +} + static unsigned long flush_count(unsigned long dfn, unsigned long page_count, unsigned int order) { diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 8c5d69a46a..4bf87e8c03 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -724,10 +724,11 @@ static void amd_dump_page_table_level(struct page_info *pg, int level, mfn_to_page(_mfn(pde->mfn)), pde->next_level, address, indent + 1); else - printk("%*sdfn: %08lx mfn: %08lx\n", + printk("%*sdfn: %08lx mfn: %08lx %c%c\n", indent, "", (unsigned long)PFN_DOWN(address), - (unsigned long)PFN_DOWN(pfn_to_paddr(pde->mfn))); + (unsigned long)PFN_DOWN(pfn_to_paddr(pde->mfn)), + pde->ir ? 'r' : '-', pde->iw ? 'w' : '-'); } unmap_domain_page(table_vaddr); -- generated by git-patchbot for /home/xen/git/xen.git#master
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |