Hi Rui & Dave,
On Thu, Sep 3, 2026 at 12:05 AM Rui Qi <qirui.001(a)bytedance.com> wrote:
On 9/2/26 2:26 PM, Dave Young wrote:
> 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 for pointing this out.
>
>> 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.
Awesome! Thanks for your work on this!.
Thanks,
Tao Liu