<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>