<div dir="ltr"><div>Hi, Aditya</div>Thank you for the update.<br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Sep 25, 2023 at 5:28 PM Aditya Gupta <<a href="mailto:adityag@linux.ibm.com">adityag@linux.ibm.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Currently 'crash-tool' fails on vmcore collected on upstream kernel on<br>
PowerPC64 with the error:<br>
<br>
    crash: invalid kernel virtual address: 0  type: "first list entry<br>
<br>
Presently the address translation for vmemmap addresses is done using<br>
the vmemmap_list. But with the below commit in Linux, vmemmap_list can<br>
be empty, in case of Radix MMU on PowerPC64<br>
<br>
    368a0590d954: (powerpc/book3s64/vmemmap: switch radix to use a<br>
    different vmemmap handling function)<br>
<br>
In case vmemmap_list is empty, then it's head is NULL, which crash tries<br>
to access and fails due to accessing NULL.<br>
<br>
Instead of depending on 'vmemmap_list' for address translation for<br>
vmemmap addresses, do a kernel pagetable walk to get the physical<br>
address associated with given virtual address<br>
<br>
Tested-by: Sachin Sant <<a href="mailto:sachinp@linux.ibm.com" target="_blank">sachinp@linux.ibm.com</a>><br>
Reviewed-by: Hari Bathini <<a href="mailto:hbathini@linux.ibm.com" target="_blank">hbathini@linux.ibm.com</a>><br>
Signed-off-by: Aditya Gupta <<a href="mailto:adityag@linux.ibm.com" target="_blank">adityag@linux.ibm.com</a>><br>
<br>
---<br>
<br>
Testing<br>
=======<br>
<br>
Git tree with patch applied:<br>
<a href="https://github.com/adi-g15-ibm/crash/tree/bugzilla-203296-list-v2" rel="noreferrer" target="_blank">https://github.com/adi-g15-ibm/crash/tree/bugzilla-203296-list-v2</a><br>
<br>
This can be tested with '/proc/vmcore' as the vmcore, since makedumpfile<br>
also fails in absence of 'vmemmap_list' in upstream linux<br>
<br>
The fix for makedumpfile will also been sent to upstream<br>
<br>
Changelog<br>
=========<br>
<br>
V2<br>
+ handle the case of 'vmemmap_list' symbol missing according to reviews<br>
<br></blockquote><div><br></div><div>The v2 looks good to me, so: Ack.</div><div><br></div><div>Thanks</div><div>Lianbo</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
---<br>
---<br>
 ppc64.c | 51 +++++++++++++++++++++++++++++++++++----------------<br>
 1 file changed, 35 insertions(+), 16 deletions(-)<br>
<br>
diff --git a/ppc64.c b/ppc64.c<br>
index fc34006f4863..cd98a679c45e 100644<br>
--- a/ppc64.c<br>
+++ b/ppc64.c<br>
@@ -1280,10 +1280,32 @@ void ppc64_vmemmap_init(void)<br>
        long backing_size, virt_addr_offset, phys_offset, list_offset;<br>
        ulong *vmemmap_list;<br>
        char *vmemmap_buf;<br>
-       struct machine_specific *ms;<br>
-       <br>
-       if (!(kernel_symbol_exists("vmemmap_list")) ||<br>
-           !(kernel_symbol_exists("mmu_psize_defs")) ||<br>
+       struct machine_specific *ms = machdep->machspec;<br>
+<br>
+       ld = &list_data;<br>
+       BZERO(ld, sizeof(struct list_data));<br>
+<br>
+       /*<br>
+        * vmemmap_list is missing or set to 0 in the kernel would imply<br>
+        * vmemmap region is mapped in the kernel pagetable. So, read vmemmap_list<br>
+        * anyway and use the translation method accordingly.<br>
+        */<br>
+       if (kernel_symbol_exists("vmemmap_list"))<br>
+               readmem(symbol_value("vmemmap_list"), KVADDR, &ld->start,<br>
+                               sizeof(void *), "vmemmap_list", RETURN_ON_ERROR|QUIET);<br>
+       if (!ld->start) {<br>
+               /*<br>
+                * vmemmap_list is set to 0 or missing. Do kernel pagetable walk<br>
+                * for vmemmap address translation.<br>
+                */<br>
+               ms->vmemmap_list = NULL;<br>
+               ms->vmemmap_cnt = 0;<br>
+<br>
+               machdep->flags |= VMEMMAP_AWARE;<br>
+               return;<br>
+       }<br>
+<br>
+       if (!(kernel_symbol_exists("mmu_psize_defs")) ||<br>
            !(kernel_symbol_exists("mmu_vmemmap_psize")) ||<br>
            !STRUCT_EXISTS("vmemmap_backing") ||<br>
            !STRUCT_EXISTS("mmu_psize_def") ||<br>
@@ -1293,8 +1315,6 @@ void ppc64_vmemmap_init(void)<br>
            !MEMBER_EXISTS("vmemmap_backing", "list"))<br>
                return;<br>
<br>
-       ms = machdep->machspec;<br>
-<br>
        backing_size = STRUCT_SIZE("vmemmap_backing");<br>
        virt_addr_offset = MEMBER_OFFSET("vmemmap_backing", "virt_addr");<br>
        phys_offset = MEMBER_OFFSET("vmemmap_backing", "phys");<br>
@@ -1313,14 +1333,8 @@ void ppc64_vmemmap_init(void)<br>
<br>
        ms->vmemmap_psize = 1 << shift;<br>
<br>
-        ld =  &list_data;<br>
-        BZERO(ld, sizeof(struct list_data));<br>
-       if (!readmem(symbol_value("vmemmap_list"),<br>
-           KVADDR, &ld->start, sizeof(void *), "vmemmap_list",<br>
-           RETURN_ON_ERROR))<br>
-               return;<br>
-        ld->end = symbol_value("vmemmap_list");<br>
-        ld->list_head_offset = list_offset;<br>
+       ld->end = symbol_value("vmemmap_list");<br>
+       ld->list_head_offset = list_offset;<br>
<br>
         hq_open();<br>
        cnt = do_list(ld);<br>
@@ -1366,7 +1380,7 @@ ppc64_vmemmap_to_phys(ulong kvaddr, physaddr_t *paddr, int verbose)<br>
 {<br>
        int i;<br>
        ulong offset;<br>
-       struct machine_specific *ms;<br>
+       struct machine_specific *ms = machdep->machspec;<br>
<br>
        if (!(machdep->flags & VMEMMAP_AWARE)) {<br>
                /*<br>
@@ -1386,7 +1400,12 @@ ppc64_vmemmap_to_phys(ulong kvaddr, physaddr_t *paddr, int verbose)<br>
                return FALSE;<br>
        }<br>
<br>
-       ms = machdep->machspec;<br>
+       /**<br>
+        * When vmemmap_list is not populated, kernel does the mapping in init_mm<br>
+        * page table, so do a pagetable walk in kernel page table<br>
+        */<br>
+       if (!ms->vmemmap_list)<br>
+               return ppc64_vtop_level4(kvaddr, (ulong *)vt->kernel_pgd[0], paddr, verbose);<br>
<br>
        for (i = 0; i < ms->vmemmap_cnt; i++) {<br>
                if ((kvaddr >= ms->vmemmap_list[i].virt) &&<br>
-- <br>
2.41.0<br>
<br>
</blockquote></div></div>