Hi, Aditya
Thank you for the patch.
On Mon, Sep 11, 2023 at 8:00 PM <crash-utility-request(a)redhat.com> wrote:
From: Aditya Gupta <adityag(a)linux.ibm.com
To: crash-utility(a)redhat.com
Cc: Hari Bathini <hbathini(a)linux.ibm.com>, Mahesh J Salgaonkar
<mahesh(a)linux.ibm.com>, Sourabh Jain <sourabhjain(a)linux.ibm.com>,
"Aneesh Kumar K.V" <aneesh.kumar(a)linux.ibm.com
Subject: [Crash-utility] [PATCH] ppc64: do page traversal if
vmemmap_list not populated
Message-ID: <20230911093032.419388-1-adityag(a)linux.ibm.com
Content-Type: text/plain; charset="US-ASCII";
x-default=true
Currently 'crash-tool' fails on vmcore collected on upstream kernel on
PowerPC64 with the error:
crash: invalid kernel virtual address: 0 type: "first list entry
Presently the address translation for vmemmap addresses is done using
the vmemmap_list. But with the below commit in Linux, vmemmap_list can
be empty, in case of Radix MMU on PowerPC64
368a0590d954: (powerpc/book3s64/vmemmap: switch radix to use a
different vmemmap handling function)
In case vmemmap_list is empty, then it's head is NULL, which crash tries
to access and fails due to accessing NULL.
Instead of depending on 'vmemmap_list' for address translation for
vmemmap addresses, do a kernel pagetable walk to get the physical
address associated with given virtual address
Reviewed-by: Hari Bathini <hbathini(a)linux.ibm.com
Signed-off-by: Aditya Gupta <adityag(a)linux.ibm.com
---
Testing
=======
Git tree with patch applied:
https://github.com/adi-g15-ibm/crash/tree/bugzilla-203296-list-v1
This can be tested with '/proc/vmcore' as the vmcore, since makedumpfile
Can you help to describe in detail how to reproduce this issue? Or does
this require any kernel configs to be enabled first? I did not reproduce
the current issue with '/proc/kcore' or vmcore(via cp).
Test kernel commit: ce9ecca0238b ("Linux 6.6-rc2")
# ./crash /home/linux/vmlinux
/var/crash/127.0.0.1-2023-09-18-06\:58\:57/vmcore
crash 8.0.3++
Copyright (C) 2002-2022 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011, 2020-2022 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Copyright (C) 2015, 2021 VMware, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.
GNU gdb (GDB) 10.2
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute
it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "powerpc64le-unknown-linux-gnu".
Type "show configuration" for configuration details.
Find the GDB manual and other documentation resources online at:
<
http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
KERNEL: /home/linux/vmlinux
DUMPFILE: /var/crash/127.0.0.1-2023-09-18-06:58:57/vmcore
CPUS: 8
DATE: Mon Sep 18 06:57:40 EDT 2023
UPTIME: 00:03:19
LOAD AVERAGE: 0.20, 0.31, 0.14
TASKS: 186
NODENAME:
ibm-p9z-16-lp10.khw3.lab.eng.bos.redhat.com
RELEASE: 6.6.0-rc2
VERSION: #2 SMP Mon Sep 18 06:11:14 EDT 2023
MACHINE: ppc64le (2800 Mhz)
MEMORY: 16 GB
PANIC: "Kernel panic - not syncing: sysrq triggered crash"
PID: 4337
COMMAND: "bash"
TASK: c000000052a49900 [THREAD_INFO: c000000052a49900]
CPU: 3
STATE: TASK_RUNNING (PANIC)
crash
Thanks
Lianbo
also fails in absence of 'vmemmap_list' in upstream linux
> The fix for makedumpfile will also been sent to upstream
> ---
> ---
> ppc64.c | 47 +++++++++++++++++++++++++++++++++--------------
> 1 file changed, 33 insertions(+), 14 deletions(-)
> diff --git a/ppc64.c b/ppc64.c
> index fc34006f4863..1e84c5f56773 100644
> --- a/ppc64.c
> +++ b/ppc64.c
> @@ -1280,8 +1280,30 @@ void ppc64_vmemmap_init(void)
> long backing_size, virt_addr_offset, phys_offset, list_offset;
> ulong *vmemmap_list;
> char *vmemmap_buf;
> - struct machine_specific *ms;
> -
> + struct machine_specific *ms = machdep->machspec;
> +
> + ld = &list_data;
> + BZERO(ld, sizeof(struct list_data));
> +
> + /*
> + * vmemmap_list is missing or set to 0 in the kernel would imply
> + * vmemmap region is mapped in the kernel pagetable. So, read
> vmemmap_list
> + * anyway and use the translation method accordingly.
> + */
> + readmem(symbol_value("vmemmap_list"), KVADDR, &ld->start,
> sizeof(void *),
> + "vmemmap_list", RETURN_ON_ERROR);
> + if (!ld->start) {
> + /*
> + * vmemmap_list is set to 0 or missing. Do kernel
> pagetable walk
> + * for vmemmamp address translation.
> + */
> + ms->vmemmap_list = NULL;
> + ms->vmemmap_cnt = 0;
> +
> + machdep->flags |= VMEMMAP_AWARE;
> + return;
> + }
> +
> if (!(kernel_symbol_exists("vmemmap_list")) ||
> !(kernel_symbol_exists("mmu_psize_defs")) ||
> !(kernel_symbol_exists("mmu_vmemmap_psize")) ||
> @@ -1293,8 +1315,6 @@ void ppc64_vmemmap_init(void)
> !MEMBER_EXISTS("vmemmap_backing", "list"))
> return;
> - ms = machdep->machspec;
> -
> backing_size = STRUCT_SIZE("vmemmap_backing");
> virt_addr_offset = MEMBER_OFFSET("vmemmap_backing",
"virt_addr");
> phys_offset = MEMBER_OFFSET("vmemmap_backing", "phys");
> @@ -1313,14 +1333,8 @@ void ppc64_vmemmap_init(void)
> ms->vmemmap_psize = 1 << shift;
> - ld = &list_data;
> - BZERO(ld, sizeof(struct list_data));
> - if (!readmem(symbol_value("vmemmap_list"),
> - KVADDR, &ld->start, sizeof(void *), "vmemmap_list",
> - RETURN_ON_ERROR))
> - return;
> - ld->end = symbol_value("vmemmap_list");
> - ld->list_head_offset = list_offset;
> + ld->end = symbol_value("vmemmap_list");
> + ld->list_head_offset = list_offset;
> hq_open();
> cnt = do_list(ld);
> @@ -1366,7 +1380,7 @@ ppc64_vmemmap_to_phys(ulong kvaddr, physaddr_t
> *paddr, int verbose)
> {
> int i;
> ulong offset;
> - struct machine_specific *ms;
> + struct machine_specific *ms = machdep->machspec;
> if (!(machdep->flags & VMEMMAP_AWARE)) {
> /*
> @@ -1386,7 +1400,12 @@ ppc64_vmemmap_to_phys(ulong kvaddr, physaddr_t
> *paddr, int verbose)
> return FALSE;
> }
> - ms = machdep->machspec;
> + /**
> + * When vmemmap_list is not populated, kernel does the mapping in
> init_mm
> + * page table, so do a pagetable walk in kernel page table
> + */
> + if (!ms->vmemmap_list)
> + return ppc64_vtop_level4(kvaddr, (ulong
> *)vt->kernel_pgd[0], paddr, verbose);
> for (i = 0; i < ms->vmemmap_cnt; i++) {
> if ((kvaddr >= ms->vmemmap_list[i].virt) &&
> --
> 2.41.0