Skip to content

Commit 6ceb93f

Browse files
duanzhenzhongjoergroedel
authored andcommitted
iommu/vt-d: Fix checks and print in dmar_fault_dump_ptes()
There are some issues in dmar_fault_dump_ptes(): 1. return value of phys_to_virt() is used for checking if an entry is present. 2. dump is confusing, e.g., "pasid table entry is not present", confusing by unpresent pasid table vs. unpresent pasid table entry. Current code means the former. 3. pgtable_walk() is called without checking if page table is present. Fix 1 by checking present bit of an entry before dump a lower level entry. Fix 2 by removing "entry" string, e.g., "pasid table is not present". Fix 3 by checking page table present before walk. Take issue 3 for example, before fix: [ 442.240357] DMAR: pasid dir entry: 0x000000012c83e001 [ 442.246661] DMAR: pasid table entry[0]: 0x0000000000000000 [ 442.253429] DMAR: pasid table entry[1]: 0x0000000000000000 [ 442.260203] DMAR: pasid table entry[2]: 0x0000000000000000 [ 442.266969] DMAR: pasid table entry[3]: 0x0000000000000000 [ 442.273733] DMAR: pasid table entry[4]: 0x0000000000000000 [ 442.280479] DMAR: pasid table entry[5]: 0x0000000000000000 [ 442.287234] DMAR: pasid table entry[6]: 0x0000000000000000 [ 442.293989] DMAR: pasid table entry[7]: 0x0000000000000000 [ 442.300742] DMAR: PTE not present at level 2 After fix: ... [ 357.241214] DMAR: pasid table entry[6]: 0x0000000000000000 [ 357.248022] DMAR: pasid table entry[7]: 0x0000000000000000 [ 357.254824] DMAR: scalable mode page table is not present Fixes: 914ff77 ("iommu/vt-d: Dump DMAR translation structure when DMA fault occurs") Signed-off-by: Zhenzhong Duan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Lu Baolu <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent 4f178e0 commit 6ceb93f

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -626,11 +626,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
626626
pr_info("Dump %s table entries for IOVA 0x%llx\n", iommu->name, addr);
627627

628628
/* root entry dump */
629-
rt_entry = &iommu->root_entry[bus];
630-
if (!rt_entry) {
631-
pr_info("root table entry is not present\n");
629+
if (!iommu->root_entry) {
630+
pr_info("root table is not present\n");
632631
return;
633632
}
633+
rt_entry = &iommu->root_entry[bus];
634634

635635
if (sm_supported(iommu))
636636
pr_info("scalable mode root entry: hi 0x%016llx, low 0x%016llx\n",
@@ -641,7 +641,7 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
641641
/* context entry dump */
642642
ctx_entry = iommu_context_addr(iommu, bus, devfn, 0);
643643
if (!ctx_entry) {
644-
pr_info("context table entry is not present\n");
644+
pr_info("context table is not present\n");
645645
return;
646646
}
647647

@@ -650,17 +650,23 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
650650

651651
/* legacy mode does not require PASID entries */
652652
if (!sm_supported(iommu)) {
653+
if (!context_present(ctx_entry)) {
654+
pr_info("legacy mode page table is not present\n");
655+
return;
656+
}
653657
level = agaw_to_level(ctx_entry->hi & 7);
654658
pgtable = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
655659
goto pgtable_walk;
656660
}
657661

658-
/* get the pointer to pasid directory entry */
659-
dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
660-
if (!dir) {
661-
pr_info("pasid directory entry is not present\n");
662+
if (!context_present(ctx_entry)) {
663+
pr_info("pasid directory table is not present\n");
662664
return;
663665
}
666+
667+
/* get the pointer to pasid directory entry */
668+
dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
669+
664670
/* For request-without-pasid, get the pasid from context entry */
665671
if (intel_iommu_sm && pasid == IOMMU_PASID_INVALID)
666672
pasid = IOMMU_NO_PASID;
@@ -672,14 +678,19 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
672678
/* get the pointer to the pasid table entry */
673679
entries = get_pasid_table_from_pde(pde);
674680
if (!entries) {
675-
pr_info("pasid table entry is not present\n");
681+
pr_info("pasid table is not present\n");
676682
return;
677683
}
678684
index = pasid & PASID_PTE_MASK;
679685
pte = &entries[index];
680686
for (i = 0; i < ARRAY_SIZE(pte->val); i++)
681687
pr_info("pasid table entry[%d]: 0x%016llx\n", i, pte->val[i]);
682688

689+
if (!pasid_pte_is_present(pte)) {
690+
pr_info("scalable mode page table is not present\n");
691+
return;
692+
}
693+
683694
if (pasid_pte_get_pgtt(pte) == PASID_ENTRY_PGTT_FL_ONLY) {
684695
level = pte->val[2] & BIT_ULL(2) ? 5 : 4;
685696
pgtable = phys_to_virt(pte->val[2] & VTD_PAGE_MASK);

0 commit comments

Comments
 (0)