For AMD machine with SME feature, if SME is enabled in the first kernel, the crashed kernel's page table(pgd/pud/pmd/pte) contains the memory encryption mask, so makedumpfile needs to remove the memory encryption mask to obtain the true physical address. Signed-off-by: Lianbo Jiang <lijiang@xxxxxxxxxx> --- Changes since v1: 1. Merge them into a patch. 2. The sme_mask is not an enum number, remove it. 3. Sanity check whether the sme_mask is in vmcoreinfo. 4. Deal with the huge pages case. 5. Cover the 5-level path. arch/x86_64.c | 30 +++++++++++++++++------------- makedumpfile.c | 4 ++++ makedumpfile.h | 1 + 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/arch/x86_64.c b/arch/x86_64.c index 537fb78..7b3ed10 100644 --- a/arch/x86_64.c +++ b/arch/x86_64.c @@ -291,6 +291,7 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable) unsigned long page_dir, pgd, pud_paddr, pud_pte, pmd_paddr, pmd_pte; unsigned long pte_paddr, pte; unsigned long p4d_paddr, p4d_pte; + unsigned long sme_me_mask = ~0UL; /* * Get PGD. @@ -302,6 +303,9 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable) return NOT_PADDR; } + if (NUMBER(sme_mask) != NOT_FOUND_NUMBER) + sme_me_mask = ~(NUMBER(sme_mask)); + if (check_5level_paging()) { page_dir += pgd5_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, page_dir, &pgd, sizeof pgd)) { @@ -309,7 +313,7 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable) return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) - MSG(" PGD : %16lx => %16lx\n", page_dir, pgd); + MSG(" PGD : %16lx => %16lx\n", page_dir, (pgd & sme_me_mask)); if (!(pgd & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pgd.\n"); @@ -318,20 +322,20 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable) /* * Get P4D. */ - p4d_paddr = pgd & ENTRY_MASK; + p4d_paddr = pgd & ENTRY_MASK & sme_me_mask; p4d_paddr += p4d_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, p4d_paddr, &p4d_pte, sizeof p4d_pte)) { ERRMSG("Can't get p4d_pte (p4d_paddr:%lx).\n", p4d_paddr); return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) - MSG(" P4D : %16lx => %16lx\n", p4d_paddr, p4d_pte); + MSG(" P4D : %16lx => %16lx\n", p4d_paddr, (p4d_pte & sme_me_mask)); if (!(p4d_pte & _PAGE_PRESENT)) { ERRMSG("Can't get a valid p4d_pte.\n"); return NOT_PADDR; } - pud_paddr = p4d_pte & ENTRY_MASK; + pud_paddr = p4d_pte & ENTRY_MASK & sme_me_mask; }else { page_dir += pgd_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, page_dir, &pgd, sizeof pgd)) { @@ -339,13 +343,13 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable) return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) - MSG(" PGD : %16lx => %16lx\n", page_dir, pgd); + MSG(" PGD : %16lx => %16lx\n", page_dir, (pgd & sme_me_mask)); if (!(pgd & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pgd.\n"); return NOT_PADDR; } - pud_paddr = pgd & ENTRY_MASK; + pud_paddr = pgd & ENTRY_MASK & sme_me_mask; } /* @@ -357,47 +361,47 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable) return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) - MSG(" PUD : %16lx => %16lx\n", pud_paddr, pud_pte); + MSG(" PUD : %16lx => %16lx\n", pud_paddr, (pud_pte & sme_me_mask)); if (!(pud_pte & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pud_pte.\n"); return NOT_PADDR; } if (pud_pte & _PAGE_PSE) /* 1GB pages */ - return (pud_pte & ENTRY_MASK & PUD_MASK) + + return (pud_pte & ENTRY_MASK & PUD_MASK & sme_me_mask) + (vaddr & ~PUD_MASK); /* * Get PMD. */ - pmd_paddr = pud_pte & ENTRY_MASK; + pmd_paddr = pud_pte & ENTRY_MASK & sme_me_mask; pmd_paddr += pmd_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, pmd_paddr, &pmd_pte, sizeof pmd_pte)) { ERRMSG("Can't get pmd_pte (pmd_paddr:%lx).\n", pmd_paddr); return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) - MSG(" PMD : %16lx => %16lx\n", pmd_paddr, pmd_pte); + MSG(" PMD : %16lx => %16lx\n", pmd_paddr, (pmd_pte & sme_me_mask)); if (!(pmd_pte & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pmd_pte.\n"); return NOT_PADDR; } if (pmd_pte & _PAGE_PSE) /* 2MB pages */ - return (pmd_pte & ENTRY_MASK & PMD_MASK) + + return (pmd_pte & ENTRY_MASK & PMD_MASK & sme_me_mask) + (vaddr & ~PMD_MASK); /* * Get PTE. */ - pte_paddr = pmd_pte & ENTRY_MASK; + pte_paddr = pmd_pte & ENTRY_MASK & sme_me_mask; pte_paddr += pte_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, pte_paddr, &pte, sizeof pte)) { ERRMSG("Can't get pte (pte_paddr:%lx).\n", pte_paddr); return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) - MSG(" PTE : %16lx => %16lx\n", pte_paddr, pte); + MSG(" PTE : %16lx => %16lx\n", pte_paddr, (pte & sme_me_mask)); if (!(pte & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pte.\n"); diff --git a/makedumpfile.c b/makedumpfile.c index 8923538..2237eb8 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -977,6 +977,8 @@ next_page: read_size = MIN(info->page_size - PAGEOFFSET(paddr), size); pgaddr = PAGEBASE(paddr); + if (NUMBER(sme_mask) != NOT_FOUND_NUMBER) + pgaddr = pgaddr & ~(NUMBER(sme_mask)); pgbuf = cache_search(pgaddr, read_size); if (!pgbuf) { ++cache_miss; @@ -2276,6 +2278,7 @@ write_vmcoreinfo_data(void) WRITE_NUMBER("NR_FREE_PAGES", NR_FREE_PAGES); WRITE_NUMBER("N_ONLINE", N_ONLINE); WRITE_NUMBER("pgtable_l5_enabled", pgtable_l5_enabled); + WRITE_NUMBER("sme_mask", sme_mask); WRITE_NUMBER("PG_lru", PG_lru); WRITE_NUMBER("PG_private", PG_private); @@ -2672,6 +2675,7 @@ read_vmcoreinfo(void) READ_NUMBER("NR_FREE_PAGES", NR_FREE_PAGES); READ_NUMBER("N_ONLINE", N_ONLINE); READ_NUMBER("pgtable_l5_enabled", pgtable_l5_enabled); + READ_NUMBER("sme_mask", sme_mask); READ_NUMBER("PG_lru", PG_lru); READ_NUMBER("PG_private", PG_private); diff --git a/makedumpfile.h b/makedumpfile.h index 73813ed..e97b2e7 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -1912,6 +1912,7 @@ struct number_table { long NR_FREE_PAGES; long N_ONLINE; long pgtable_l5_enabled; + long sme_mask; /* * Page flags -- 2.17.1 _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec