On Sat, Dec 30, 2023 at 10:19:35AM -0600, Michael Roth wrote: > + while (pfn_current < pfn_end) { > + e = __snp_lookup_rmpentry(pfn_current, &level); > + if (IS_ERR(e)) { > + pfn_current++; > + continue; > + } > + > + e_data = (u64 *)e; > + if (e_data[0] || e_data[1]) { > + pr_info("No assigned RMP entry for PFN 0x%llx, but the 2MB region contains populated RMP entries, e.g.: PFN 0x%llx: [high=0x%016llx low=0x%016llx]\n", > + pfn, pfn_current, e_data[1], e_data[0]); > + return; > + } > + pfn_current++; > + } > + > + pr_info("No populated RMP entries in the 2MB region containing PFN 0x%llx\n", > + pfn); > +} Ok, I went and reworked this, see below. Yes, I think it is important - at least in the beginning - to dump the whole 2M PFN region for debugging purposes. If that output starts becoming too unwieldy and overflowing terminals or log files, we'd shorten it or put it behind a debug option or so. Thx. --- diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index a8cf33b7da71..259a1dd655a7 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -35,16 +35,21 @@ * Family 19h Model 01h, Rev B1 processor. */ struct rmpentry { - u64 assigned : 1, - pagesize : 1, - immutable : 1, - rsvd1 : 9, - gpa : 39, - asid : 10, - vmsa : 1, - validated : 1, - rsvd2 : 1; - u64 rsvd3; + union { + struct { + u64 assigned : 1, + pagesize : 1, + immutable : 1, + rsvd1 : 9, + gpa : 39, + asid : 10, + vmsa : 1, + validated : 1, + rsvd2 : 1; + }; + u64 lo; + }; + u64 hi; } __packed; /* @@ -272,22 +277,20 @@ EXPORT_SYMBOL_GPL(snp_lookup_rmpentry); */ static void dump_rmpentry(u64 pfn) { - u64 pfn_current, pfn_end; + u64 pfn_i, pfn_end; struct rmpentry *e; - u64 *e_data; int level; e = __snp_lookup_rmpentry(pfn, &level); if (IS_ERR(e)) { - pr_info("Failed to read RMP entry for PFN 0x%llx, error %ld\n", - pfn, PTR_ERR(e)); + pr_err("Error %ld reading RMP entry for PFN 0x%llx\n", + PTR_ERR(e), pfn); return; } - e_data = (u64 *)e; if (e->assigned) { - pr_info("RMP entry for PFN 0x%llx: [high=0x%016llx low=0x%016llx]\n", - pfn, e_data[1], e_data[0]); + pr_info("PFN 0x%llx, RMP entry: [0x%016llx - 0x%016llx]\n", + pfn, e->lo, e->hi); return; } @@ -299,27 +302,28 @@ static void dump_rmpentry(u64 pfn) * certain situations, such as when the PFN is being accessed via a 2MB * mapping in the host page table. */ - pfn_current = ALIGN(pfn, PTRS_PER_PMD); - pfn_end = pfn_current + PTRS_PER_PMD; + pfn_i = ALIGN(pfn, PTRS_PER_PMD); + pfn_end = pfn_i + PTRS_PER_PMD; - while (pfn_current < pfn_end) { - e = __snp_lookup_rmpentry(pfn_current, &level); + pr_info("PFN 0x%llx unassigned, dumping the whole 2M PFN region: [0x%llx - 0x%llx]\n", + pfn, pfn_i, pfn_end); + + while (pfn_i < pfn_end) { + e = __snp_lookup_rmpentry(pfn_i, &level); if (IS_ERR(e)) { - pfn_current++; + pr_err("Error %ld reading RMP entry for PFN 0x%llx\n", + PTR_ERR(e), pfn_i); + pfn_i++; continue; } - e_data = (u64 *)e; - if (e_data[0] || e_data[1]) { - pr_info("No assigned RMP entry for PFN 0x%llx, but the 2MB region contains populated RMP entries, e.g.: PFN 0x%llx: [high=0x%016llx low=0x%016llx]\n", - pfn, pfn_current, e_data[1], e_data[0]); - return; - } - pfn_current++; - } + if (e->lo || e->hi) + pr_info("PFN: 0x%llx, [0x%016llx - 0x%016llx]\n", pfn_i, e->lo, e->hi); + else + pr_info("PFN: 0x%llx ...\n", pfn_i); - pr_info("No populated RMP entries in the 2MB region containing PFN 0x%llx\n", - pfn); + pfn_i++; + } } void snp_dump_hva_rmpentry(unsigned long hva) @@ -339,4 +343,3 @@ void snp_dump_hva_rmpentry(unsigned long hva) dump_rmpentry(pte_pfn(*pte)); } -EXPORT_SYMBOL_GPL(snp_dump_hva_rmpentry); -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette