|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] 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#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |