Hi Tao, Rui,
On 9/2/26 12:57 PM, Tao Liu wrote:
Hi Rui,
You may need to do a rebase on the latest upstream. I merged a patch
[1] and noticed yours conflicts with it.
[1]:
https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg02260.html
Looks like the above patch is trying to solve same problem, Rui may just retest the
latest crash, see if it works or not, send extra fixes if needed.
Thanks,
Tao Liu
On Wed, Sep 2, 2026 at 2:34 PM Rui Qi <qirui.001(a)bytedance.com> wrote:
>
> On 9/1/26 10:15 AM, Rui Qi wrote:
>> RISC-V page table entries at any level may be leaf entries when V is
>> set and any of R/W/X is set. The riscv64 vtop walkers currently treat
>> non-zero intermediate entries as pointers to the next page table, so a
>> PMD leaf can be used as a page table address and make vtop fail with a
>> physical seek error.
>>
>> Detect leaf entries at PGD/P4D/PUD/PMD levels and translate them using
>> the page size implied by that level. Continue walking only for non-leaf
>> table entries.
>>
>> Signed-off-by: Rui Qi <qirui.001(a)bytedance.com>
>> ---
>> riscv64.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 54 insertions(+)
>>
>> diff --git a/riscv64.c b/riscv64.c
>> index 4dcecc2f6b2c..ca26965421d7 100644
>> --- a/riscv64.c
>> +++ b/riscv64.c
>> @@ -602,6 +602,33 @@ riscv64_translate_pte(ulong pte, void *physaddr, ulonglong
unused)
>> return page_present;
>> }
>>
>> +static int
>> +riscv64_pte_is_leaf(ulong pte)
>> +{
>> + return ((pte & _PAGE_PRESENT) &&
>> + (pte & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)));
>> +}
>> +
>> +static int
>> +riscv64_handle_leaf_pte(ulong pte, ulong vaddr, int shift,
>> + physaddr_t *paddr, int verbose)
>> +{
>> + physaddr_t paddr_base, page_mask;
>> +
>> + pte &= PTE_PFN_PROT_MASK;
>> + paddr_base = PTOB(pte >> _PAGE_PFN_SHIFT);
>> + page_mask = ~(((physaddr_t)1 << shift) - 1);
>> + *paddr = (paddr_base & page_mask) + (vaddr & ~page_mask);
>> +
>> + if (verbose) {
>> + fprintf(fp, " PAGE: %016llx\n\n",
>> + (ulonglong)(*paddr & page_mask));
>> + riscv64_translate_pte(pte, 0, 0);
>> + }
>> +
>> + return TRUE;
>> +}
>> +
>> static void
>> riscv64_page_type_init(void)
>> {
>> @@ -655,6 +682,9 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr,
pgd_val);
>> if (!pgd_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pgd_val))
>> + return riscv64_handle_leaf_pte(pgd_val, vaddr,
>> + PGD_SHIFT_L3, paddr, verbose);
>> pgd_val &= PTE_PFN_PROT_MASK;
>> pmd_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -666,6 +696,9 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr,
pmd_val);
>> if (!pmd_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pmd_val))
>> + return riscv64_handle_leaf_pte(pmd_val, vaddr,
>> + PMD_SHIFT, paddr, verbose);
>> pmd_val &= PTE_PFN_PROT_MASK;
>> pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -1237,6 +1270,9 @@ riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr,
pgd_val);
>> if (!pgd_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pgd_val))
>> + return riscv64_handle_leaf_pte(pgd_val, vaddr,
>> + PGD_SHIFT_L4, paddr, verbose);
>> pgd_val &= PTE_PFN_PROT_MASK;
>> pud_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -1248,6 +1284,9 @@ riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr,
pud_val);
>> if (!pud_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pud_val))
>> + return riscv64_handle_leaf_pte(pud_val, vaddr,
>> + PUD_SHIFT, paddr, verbose);
>> pud_val &= PTE_PFN_PROT_MASK;
>> pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -1259,6 +1298,9 @@ riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr,
pmd_val);
>> if (!pmd_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pmd_val))
>> + return riscv64_handle_leaf_pte(pmd_val, vaddr,
>> + PMD_SHIFT, paddr, verbose);
>> pmd_val &= PTE_PFN_PROT_MASK;
>> pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -1316,6 +1358,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr,
pgd_val);
>> if (!pgd_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pgd_val))
>> + return riscv64_handle_leaf_pte(pgd_val, vaddr,
>> + PGD_SHIFT_L5, paddr, verbose);
>> pgd_val &= PTE_PFN_PROT_MASK;
>> p4d_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -1327,6 +1372,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " P4D: %016lx => %016lx\n", p4d_addr,
p4d_val);
>> if (!p4d_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(p4d_val))
>> + return riscv64_handle_leaf_pte(p4d_val, vaddr,
>> + P4D_SHIFT, paddr, verbose);
>> p4d_val &= PTE_PFN_PROT_MASK;
>> pud_base = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -1338,6 +1386,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr,
pud_val);
>> if (!pud_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pud_val))
>> + return riscv64_handle_leaf_pte(pud_val, vaddr,
>> + PUD_SHIFT, paddr, verbose);
>> pud_val &= PTE_PFN_PROT_MASK;
>> pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>> @@ -1349,6 +1400,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t
*paddr, int verbose)
>> fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr,
pmd_val);
>> if (!pmd_val)
>> goto no_page;
>> + if (riscv64_pte_is_leaf(pmd_val))
>> + return riscv64_handle_leaf_pte(pmd_val, vaddr,
>> + PMD_SHIFT, paddr, verbose);
>> pmd_val &= PTE_PFN_PROT_MASK;
>> pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>>
>
> Hi,
>
> This patch fixes a crash utility issue on RISC-V where `vtop -k` may
> fail to translate valid vmalloc/vmap addresses.
>
> The issue was observed while analyzing a RISC-V system running the
> 6.12.95 kernel. For some vmalloc addresses, `vtop` failed with:
>
> crash> vtop -k ffff8f8044680000
> VIRTUAL
> PHYSICAL
> vtop: seek error: physical address
>
> However, `kmem -v` showed that the same address belonged to a valid vmap
> area.
>
> Further investigation showed that the address was mapped by a leaf PTE at
> an intermediate page table level, such as PMD. On RISC-V, a PTE at any
> level may be a leaf entry when the V bit is set and at least one of the
> R/W/X bits is set. Leaf PTEs are therefore not limited to the last page
> table level.
>
> The existing crash RISC-V page table walkers only handled leaf entries at
> the final PTE level. For PGD/P4D/PUD/PMD entries, any non-zero entry was
> treated as a pointer to the next-level page table. When such an entry was
> actually a leaf PTE, crash incorrectly used its PFN as a page-table-page
> address, which led to a physical seek error.
>
> This patch fixes the issue by detecting leaf PTEs during the Sv39, Sv48,
> and Sv57 page table walks. When a leaf entry is found at PGD/P4D/PUD/PMD
> level, crash now translates the virtual address using the page size
> implied by that level. Non-leaf entries continue to be handled by walking
> to the next page table level.
>
> After the fix, the previously failing address can be translated correctly,
> for example:
>
> crash> vtop -k ffff8f803c000000
> VIRTUAL PHYSICAL
> ffff8f803c000000 b003c000000
>
> Addresses with an offset inside the same large mapping are also handled
> correctly:
>
> crash> vtop -k ffff8f803c123456
> VIRTUAL PHYSICAL
> ffff8f803c123456 b003c123456
>
> The normal 4KB PTE mapping path was also verified to continue working.
>
> This is a crash utility bug fix only. No kernel change is required.
>