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.
>>
>
>
Hi Tao, Dave,
Thanks a lot for the heads-up, and sorry for the noise.
You are right — I didn't notice that the patch in [1] had already been
merged and is addressing exactly the same problem. I should have rebased
on the latest upstream and retested before sending this out.
I just re-tested with the current crash master and confirmed that `vtop
-k` on the previously failing RISC-V vmalloc/vmap addresses now works
correctly, so my patch is no longer needed. Please feel free to
drop/ignore it.
If I run into any remaining corner cases on top of the merged fix, I
will send separate follow-up patches instead.
[1]: