Re: [PATCH] RISCV64: fix wrong information of PMD and PTE - SA39(4K page) support
by lijiang
Hi, Austin
Thank you for the patch.
On Wed, Oct 22, 2025 at 6:00 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Wed, 22 Oct 2025 11:46:19 +0900
> From: Austin Kim <austindh.kim(a)gmail.com>
> Subject: [Crash-utility] [PATCH] RISCV64: fix wrong information of PMD
> and PTE - SA39(4K page) support
> To: devel(a)lists.crash-utility.osci.io
> Cc: austindh.kim(a)gmail.com
> Message-ID: <aPhFe2nFOb1qlY8h@adminpc-PowerEdge-R7525>
> Content-Type: text/plain; charset=us-ascii
>
> When running 'vtop address' command in RISC-V based vmcore, the base
> address
> without applying offset for PMD and PTE is displayed. This is not correct
> address for PMD and PTE.
>
>
This change looks good to me. So: Ack.
BTW: I haven't seen any similar changes on 4level_4k and 5level_4k, isn't
it necessary? Or can you also take a look?
Thanks
Lianbo
> With this patch, the actual address for PMD and PTE with the valid offset
> is printed:
>
> <Before>
> crash> vtop 0xffffffff81c4f000
> VIRTUAL PHYSICAL
> ffffffff81c4f000 41e4f000
>
> PAGE DIRECTORY: ffffffff81c4f000
> PGD: ffffffff81c4fff0 => 4fffe801
> PMD: 000000013fffa000 => 00000000107800e7
> PTE: 41e00000 => ffffffff8166fea0
>
> PTE PAGE: 0000000000000000 not present
>
> <After>
> crash> vtop 0xffffffff81c4f000
> VIRTUAL PHYSICAL
> ffffffff81c4f000 41e4f000
>
> PAGE DIRECTORY: ffffffff81c4f000
> PGD: ffffffff81c4fff0 => 4fffe801
> PMD: 000000013fffa070 => 00000000107800e7
> PTE: 41e00278 => ffffffff8166fea0
>
> PTE PAGE: 0000000000000000 not present
>
> Signed-off-by: Austin Kim <austindh.kim(a)gmail.com>
> ---
> riscv64.c | 25 ++++++++++++-------------
> 1 file changed, 12 insertions(+), 13 deletions(-)
>
> diff --git a/riscv64.c b/riscv64.c
> index ef5c41d..6b89f0b 100644
> --- a/riscv64.c
> +++ b/riscv64.c
> @@ -630,9 +630,8 @@ static int
> riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int
> verbose)
> {
> ulong *pgd_ptr, pgd_val;
> - ulong pmd_val;
> - ulong pte_val, pte_pfn;
> - ulong pt_phys;
> + ulong pmd_base, pmd_addr, pmd_val;
> + ulong pte_base, pte_addr, pte_val, pte_pfn;
>
> if (verbose)
> fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
> @@ -646,25 +645,25 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr,
> physaddr_t *paddr, int verbose)
> if (!pgd_val)
> goto no_page;
> pgd_val &= PTE_PFN_PROT_MASK;
> - pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
> + pmd_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>
> /* PMD */
> - FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
> - pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) *
> - pmd_index_l3_4k(vaddr)));
> + FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
> + pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l3_4k(vaddr);
> + pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
> if (verbose)
> - fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val);
> + fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr,
> pmd_val);
> if (!pmd_val)
> goto no_page;
> pmd_val &= PTE_PFN_PROT_MASK;
> - pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
> + pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>
> /* PTE */
> - FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
> - pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) *
> - pte_index_l3_4k(vaddr)));
> + FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
> + pte_addr = pte_base + sizeof(pmd_t) * pte_index_l3_4k(vaddr);
> + pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
> if (verbose)
> - fprintf(fp, " PTE: %lx => %lx\n", pt_phys, pte_val);
> + fprintf(fp, " PTE: %lx => %lx\n", pte_addr, pte_val);
> if (!pte_val)
> goto no_page;
> pte_val &= PTE_PFN_PROT_MASK;
> --
> 2.34.1
>
9 hours, 22 minutes
[PATCH v3 0/2] extension: Several improvements on eppic extension
by Tao Liu
Eppic works as a crash extension for a long time, and it is a very convenient
tool to extend crash's function:
1) People don't need to write an actual crash extension, which requires
knowledge of crash APIs, such as readmem(), gdb_interface() etc.
Implementing such an crash extension is hard for normal users.
2) Eppic programs are C-syntax-like scripting, no compile needed, so friendly
to kernel developers who are already familiar with C. It's a good alternative
for people who are unfamiliar with python (comparing to drgn/pykdump).
3) Writing eppic programs is similar to do kernel programming, people can use
kernel data structures/global variables directly, again, friendly to kernel
developers.
Personally I think eppic is a good tool and would like to push it forward to
make it used more widely, improved consistently. However I hardly heard anyone
who are using it, I guess it is due to it's extension position and unknown to
others.
In this patchset, I will make several improvements on eppic, although it is
still a crash extension, but I think it is made more easily for
compile/run/scripting.
To-do:
Some crash functions should be exposed to eppic, such as maple_tree/rbtree etc,
so people can iterate these kernel structures with the existing crash functions,
otherwise people need to reimplement those in eppic.
A more aggresive improvement of eppic can be found in [1], which people
can use call_crash_func() to call any crash's function within eppic
script, please refer to code example in [2]. Not sure if people like
this, so any feedback/comments are welcomed.
v2 -> v1:
Removed v1's No.2 & 3 & 5 patch, these 3 are used for compile/preload/alias
eppic by default, these are a little aggressive and left to [1] instead.
[1]: https://github.com/liutgnu/crash-dev/tree/eppic
[2]: https://github.com/liutgnu/crash-dev/blob/eppic/extensions/eppic.patch#L298
v3 -> v2:
Removed goto for get_extensions_directory().
Removed pushd/popd in eppic.mk.
Tao Liu (2):
extensions: Search all possible paths
eppic.patch: Add customized functions to eppic
extensions.c | 59 ++++++------
extensions/eppic.mk | 9 +-
extensions/eppic.patch | 210 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 250 insertions(+), 28 deletions(-)
create mode 100644 extensions/eppic.patch
--
2.47.0
9 hours, 54 minutes
Re: [PATCH v3 1/2] extensions: Search all possible paths
by lijiang
Hi, Tao
Thank you for the update.
On Tue, Oct 28, 2025 at 6:59 AM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Tue, 28 Oct 2025 11:40:03 +1300
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH v3 1/2] extensions: Search all
> possible paths
> To: devel(a)lists.crash-utility.osci.io
> Cc: lijiang(a)redhat.com
> Message-ID: <20251027224004.13784-2-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> Search all possible paths for extensions. Previously if one path, e.g.
> "/usr/lib64/crash/extensions" exists, but no extensions found within,
> crash will not search any later paths, e.g. "./extensions". This patch
> will let crash continue to search any later paths.
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> extensions.c | 59 ++++++++++++++++++++++++++++------------------------
> 1 file changed, 32 insertions(+), 27 deletions(-)
>
> diff --git a/extensions.c b/extensions.c
> index d23b1e3..099af3b 100644
> --- a/extensions.c
> +++ b/extensions.c
> @@ -19,7 +19,7 @@
> #include <dlfcn.h>
>
> static int in_extensions_library(char *, char *);
> -static char *get_extensions_directory(char *);
> +static char *get_extensions_directory(char *, bool *);
> static void show_all_extensions(void);
> static void show_extensions(char *);
>
> @@ -395,32 +395,29 @@ in_extensions_library(char *lib, char *buf)
> * Look for an extensions directory using the proper order.
> */
> static char *
> -get_extensions_directory(char *dirbuf)
> +get_extensions_directory(char *dirbuf, bool *end)
> {
> - char *env;
> + static int index = 0;
>
> + char *dirs[] = {
> + getenv("CRASH_EXTENSIONS"),
> + BITS64() ? "/usr/lib64/crash/extensions" : NULL,
> + "/usr/lib/crash/extensions",
> + "./extensions",
> + };
> + char *dir;
>
> - if ((env = getenv("CRASH_EXTENSIONS"))) {
> - if (is_directory(env)) {
> - strcpy(dirbuf, env);
> - return dirbuf;
> - }
> + if (index >= sizeof(dirs) / sizeof(char *)) {
> + *end = true;
> + return NULL;
> }
> -
> - if (BITS64()) {
> - sprintf(dirbuf, "/usr/lib64/crash/extensions");
> - if (is_directory(dirbuf))
> - return dirbuf;
> + *end = false;
> + dir = dirs[index++];
> + if (is_directory(dir)) {
> + snprintf(dirbuf, BUFSIZE - 1, "%s", dir);
>
The snprintf() won't write more than BUFSIZE - 1 characters and will always
null-terminate the buffer(including the terminating null byte ('\0')),
so using the BUFSIZE should be safe and correct.
Other changes are fine to me. Otherwise: Ack.
Thanks
Lianbo
+ return dir;
> + } else {
> + return NULL;
> }
> -
> - sprintf(dirbuf, "/usr/lib/crash/extensions");
> - if (is_directory(dirbuf))
> - return dirbuf;
> -
> - sprintf(dirbuf, "./extensions");
> - if (is_directory(dirbuf))
> - return dirbuf;
> -
> - return NULL;
> }
>
>
> @@ -432,14 +429,20 @@ preload_extensions(void)
> char dirbuf[BUFSIZE];
> char filename[BUFSIZE*2];
> int found;
> + bool end;
>
> - if (!get_extensions_directory(dirbuf))
> - return;
> +next_dir:
> + if (!get_extensions_directory(dirbuf, &end)) {
> + if (end)
> + return;
> + else
> + goto next_dir;
> + }
>
> dirp = opendir(dirbuf);
> if (!dirp) {
> error(INFO, "%s: %s\n", dirbuf, strerror(errno));
> - return;
> + goto next_dir;
> }
>
> pc->curcmd = pc->program_name;
> @@ -461,10 +464,12 @@ preload_extensions(void)
>
> if (found)
> fprintf(fp, "\n");
> - else
> + else {
> error(NOTE,
> "%s: no extension modules found in directory\n\n",
> dirbuf);
> + goto next_dir;
> + }
> }
>
> /*
> --
> 2.47.0
>
9 hours, 59 minutes
[PATCH] RISCV64: fix wrong information of PMD and PTE - SA39(4K page) support
by Austin Kim
When running 'vtop address' command in RISC-V based vmcore, the base address
without applying offset for PMD and PTE is displayed. This is not correct
address for PMD and PTE.
With this patch, the actual address for PMD and PTE with the valid offset
is printed:
<Before>
crash> vtop 0xffffffff81c4f000
VIRTUAL PHYSICAL
ffffffff81c4f000 41e4f000
PAGE DIRECTORY: ffffffff81c4f000
PGD: ffffffff81c4fff0 => 4fffe801
PMD: 000000013fffa000 => 00000000107800e7
PTE: 41e00000 => ffffffff8166fea0
PTE PAGE: 0000000000000000 not present
<After>
crash> vtop 0xffffffff81c4f000
VIRTUAL PHYSICAL
ffffffff81c4f000 41e4f000
PAGE DIRECTORY: ffffffff81c4f000
PGD: ffffffff81c4fff0 => 4fffe801
PMD: 000000013fffa070 => 00000000107800e7
PTE: 41e00278 => ffffffff8166fea0
PTE PAGE: 0000000000000000 not present
Signed-off-by: Austin Kim <austindh.kim(a)gmail.com>
---
riscv64.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/riscv64.c b/riscv64.c
index ef5c41d..6b89f0b 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -630,9 +630,8 @@ static int
riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
{
ulong *pgd_ptr, pgd_val;
- ulong pmd_val;
- ulong pte_val, pte_pfn;
- ulong pt_phys;
+ ulong pmd_base, pmd_addr, pmd_val;
+ ulong pte_base, pte_addr, pte_val, pte_pfn;
if (verbose)
fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
@@ -646,25 +645,25 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
if (!pgd_val)
goto no_page;
pgd_val &= PTE_PFN_PROT_MASK;
- pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
+ pmd_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
/* PMD */
- FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) *
- pmd_index_l3_4k(vaddr)));
+ FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
+ pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l3_4k(vaddr);
+ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
if (verbose)
- fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val);
+ fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
if (!pmd_val)
goto no_page;
pmd_val &= PTE_PFN_PROT_MASK;
- pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
+ pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
/* PTE */
- FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
- pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) *
- pte_index_l3_4k(vaddr)));
+ FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
+ pte_addr = pte_base + sizeof(pmd_t) * pte_index_l3_4k(vaddr);
+ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
if (verbose)
- fprintf(fp, " PTE: %lx => %lx\n", pt_phys, pte_val);
+ fprintf(fp, " PTE: %lx => %lx\n", pte_addr, pte_val);
if (!pte_val)
goto no_page;
pte_val &= PTE_PFN_PROT_MASK;
--
2.34.1
1 day, 15 hours
[PATCH] Fix for "set" command failure
by Lianbo Jiang
Recently we have observed some failures as below:
crash> set 2276866
set: invalid kernel virtual address: 0 type: "stack contents"
set: read of stack at 0 failed
crash> ps 2276866
PID PPID CPU TASK ST %MEM VSZ RSS COMM
2276866 2276750 47 ff3a19fbd3c80000 ZO 0.0 0 0 sh
This is a regression issue that introduced by adding gdb stack unwind
support. When attempting to read from the stack, firstly, need to check
if the stack exists, otherwise it may fail in some corner cases. E.g:
there are some zombie processes(ZO) and the stack does not exist.
Furthermore this may also break the switching thread in gdb.
With the patch:
crash> set 2276866
PID: 2276866
COMMAND: "sh"
TASK: ff3a19fbd3c80000 [THREAD_INFO: ff3a19fbd3c80000]
CPU: 47
STATE: EXIT_DEAD|EXIT_ZOMBIE
Reported-by: Buland Kumar Singh <bsingh(a)redhat.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
arm64.c | 2 ++
ppc64.c | 2 ++
x86_64.c | 2 ++
3 files changed, 6 insertions(+)
diff --git a/arm64.c b/arm64.c
index 354d17ab6a19..17235950bb60 100644
--- a/arm64.c
+++ b/arm64.c
@@ -234,6 +234,8 @@ arm64_get_current_task_reg(int regno, const char *name,
BZERO(&bt_setup, sizeof(struct bt_info));
clone_bt_info(&bt_setup, &bt_info, tc);
+ if (bt_info.stackbase == 0)
+ return FALSE;
fill_stackbuf(&bt_info);
get_dumpfile_regs(&bt_info, &sp, &ip);
diff --git a/ppc64.c b/ppc64.c
index d1a506773c93..9c5c0a460c7a 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -2606,6 +2606,8 @@ ppc64_get_current_task_reg(int regno, const char *name, int size,
BZERO(&bt_setup, sizeof(struct bt_info));
clone_bt_info(&bt_setup, &bt_info, tc);
+ if (bt_info.stackbase == 0)
+ return FALSE;
fill_stackbuf(&bt_info);
// reusing the get_dumpfile_regs function to get pt regs structure
diff --git a/x86_64.c b/x86_64.c
index d7da536d20d8..b2cddbf8ba3d 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -9383,6 +9383,8 @@ x86_64_get_current_task_reg(int regno, const char *name,
BZERO(&bt_setup, sizeof(struct bt_info));
clone_bt_info(&bt_setup, &bt_info, tc);
+ if (bt_info.stackbase == 0)
+ return FALSE;
fill_stackbuf(&bt_info);
// reusing the get_dumpfile_regs function to get pt regs structure
--
2.50.1
2 days, 9 hours
Re: [PATCH] bpf: Implement ringbuf_map memory usage calculation
by lijiang
On Mon, Sep 15, 2025 at 1:16 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Thu, 11 Sep 2025 15:20:23 +1200
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] bpf: Implement ringbuf_map memory
> usage calculation
> To: devel(a)lists.crash-utility.osci.io
> Cc: Tao Liu <ltao(a)redhat.com>
> Message-ID: <20250911032023.16833-1-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> This patch replicates the kernel code for bpf ringbuf_map mm usage
> calculation.
>
> $ bpftool map create /sys/fs/bpf/rb0 type ringbuf key 0 value 0 entries
> $((1<<24)) name rb0
>
> Before:
> crash> bpf -m 12
> ID BPF_MAP BPF_MAP_TYPE MAP_FLAGS
> 12 ffff8dc4d7c0ed00 RINGBUF 00000000
> KEY_SIZE: 0 VALUE_SIZE: 0 MAX_ENTRIES: 16777216 MEMLOCK:
> (unknown)
> NAME: "rb0" UID: (unused)
>
> After:
> crash> bpf -m 12
> ID BPF_MAP BPF_MAP_TYPE MAP_FLAGS
> 12 ffff8dc4d7c0ed00 RINGBUF 00000000
> KEY_SIZE: 0 VALUE_SIZE: 0 MAX_ENTRIES: 16777216 MEMLOCK: 16855320
> NAME: "rb0" UID: (unused)
>
> Thus, the output will be the same as bpftool:
>
> $ bpftool map show id 12
> 12: ringbuf name rb0 flags 0x0
> key 0B value 0B max_entries 16777216 memlock 16855320B
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> bpf.c | 30 +++++++++++++++++++++++++++++-
> defs.h | 5 +++++
> symbols.c | 5 +++++
> 3 files changed, 39 insertions(+), 1 deletion(-)
>
> diff --git a/bpf.c b/bpf.c
> index 466b244..43e4ff5 100644
> --- a/bpf.c
> +++ b/bpf.c
> @@ -121,6 +121,26 @@ static ulong bpf_map_memory_size(int map_type, uint
> value_size,
> return roundup((max_entries * size), PAGESIZE());
> }
>
> +/*
> + * Code replicated from kernel/bpf/ringbuf.c:ringbuf_map_mem_usage()
> +*/
> +static ulong ringbuf_map_mem_usage(struct bpf_info *bpf, int i)
> +{
> + ulong nr_pages;
> + ulong usage = SIZE(bpf_ringbuf_map);
> + ulong rb = (ulong)(bpf->maplist[i].value) -
> OFFSET(bpf_ringbuf_map_map)
> + + OFFSET(bpf_ringbuf_map_rb);
> + readmem(rb, KVADDR, &rb, sizeof(ulong), "bpf_ringbuf *",
> RETURN_ON_ERROR);
>
It should be good to use the "FAULT_ON_ERROR" in readmem(), or you can
check the returned error(if any) here. Both are fine to me.
+ readmem(rb + OFFSET(bpf_ringbuf_nr_pages), KVADDR, &nr_pages,
> + sizeof(ulong), "bpf_ringbuf.nr_pages", RETURN_ON_ERROR);
>
Ditto.
Other changes are good for me.
Thanks
Lianbo
+ usage += (nr_pages << PAGESHIFT());
> + ulong nr_meta_pages = (OFFSET(bpf_ringbuf_consumer_pos) >>
> PAGESHIFT()) + 2;
> + ulong nr_data_pages = UINT(bpf->bpf_map_buf +
> OFFSET(bpf_map_max_entries)) >> PAGESHIFT();
> + usage += (nr_meta_pages + 2 * nr_data_pages) * sizeof(void *);
> +
> + return usage;
> +}
> +
> void
> cmd_bpf(void)
> {
> @@ -217,6 +237,7 @@ bpf_init(struct bpf_info *bpf)
> STRUCT_SIZE_INIT(bpf_prog_aux, "bpf_prog_aux");
> STRUCT_SIZE_INIT(bpf_map, "bpf_map");
> STRUCT_SIZE_INIT(bpf_insn, "bpf_insn");
> + STRUCT_SIZE_INIT(bpf_ringbuf_map, "bpf_ringbuf_map");
> MEMBER_OFFSET_INIT(bpf_prog_aux, "bpf_prog", "aux");
> MEMBER_OFFSET_INIT(bpf_prog_type, "bpf_prog", "type");
> MEMBER_OFFSET_INIT(bpf_prog_tag, "bpf_prog", "tag");
> @@ -228,6 +249,10 @@ bpf_init(struct bpf_info *bpf)
> MEMBER_OFFSET_INIT(bpf_map_map_flags, "bpf_map",
> "map_flags");
> MEMBER_OFFSET_INIT(bpf_prog_aux_used_maps, "bpf_prog_aux",
> "used_maps");
> MEMBER_OFFSET_INIT(bpf_prog_aux_used_map_cnt,
> "bpf_prog_aux", "used_map_cnt");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_map_map, "bpf_ringbuf_map",
> "map");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_map_rb, "bpf_ringbuf_map",
> "rb");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_consumer_pos,
> "bpf_ringbuf", "consumer_pos");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_nr_pages, "bpf_ringbuf",
> "nr_pages");
> if (!VALID_STRUCT(bpf_prog) ||
> !VALID_STRUCT(bpf_prog_aux) ||
> !VALID_STRUCT(bpf_map) ||
> @@ -664,7 +689,10 @@ do_map_only:
> fprintf(fp, "%d\n", map_pages *
> PAGESIZE());
> } else if ((msize = bpf_map_memory_size(type,
> value_size, key_size, max_entries)))
> fprintf(fp, "%ld\n", msize);
> - else
> +#define BPF_MAP_TYPE_RINGBUF (0x1BUL)
> + else if (type == BPF_MAP_TYPE_RINGBUF) {
> + fprintf(fp, "%ld\n",
> ringbuf_map_mem_usage(bpf, i));
> + } else
> fprintf(fp, "(unknown)");
>
> fprintf(fp, " NAME: ");
> diff --git a/defs.h b/defs.h
> index 4fecb83..498c262 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2274,6 +2274,10 @@ struct offset_table { /* stash
> of commonly-used offsets */
> long request_queue_tag_set;
> long blk_mq_tag_set_flags;
> long blk_mq_tag_set_shared_tags;
> + long bpf_ringbuf_map_map;
> + long bpf_ringbuf_map_rb;
> + long bpf_ringbuf_consumer_pos;
> + long bpf_ringbuf_nr_pages;
> };
>
> struct size_table { /* stash of commonly-used sizes */
> @@ -2452,6 +2456,7 @@ struct size_table { /* stash of
> commonly-used sizes */
> long vmap_node;
> long cpumask_t;
> long task_struct_exit_state;
> + long bpf_ringbuf_map;
> };
>
> struct array_table {
> diff --git a/symbols.c b/symbols.c
> index ce0b441..19e1316 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -11868,6 +11868,10 @@ dump_offset_table(char *spec, ulong makestruct)
> fprintf(fp, " thread_struct_gsbase: %ld\n",
> OFFSET(thread_struct_gsbase));
> fprintf(fp, " thread_struct_fs: %ld\n",
> OFFSET(thread_struct_fs));
> fprintf(fp, " thread_struct_gs: %ld\n",
> OFFSET(thread_struct_gs));
> + fprintf(fp, " bpf_ringbuf_map_map: %ld\n",
> OFFSET(bpf_ringbuf_map_map));
> + fprintf(fp, " bpf_ringbuf_map_rb: %ld\n",
> OFFSET(bpf_ringbuf_map_rb));
> + fprintf(fp, " bpf_ringbuf_consumer_pos: %ld\n",
> OFFSET(bpf_ringbuf_consumer_pos));
> + fprintf(fp, " bpf_ringbuf_nr_pages: %ld\n",
> OFFSET(bpf_ringbuf_nr_pages));
>
> fprintf(fp, "\n size_table:\n");
> fprintf(fp, " page: %ld\n", SIZE(page));
> @@ -12148,6 +12152,7 @@ dump_offset_table(char *spec, ulong makestruct)
>
> fprintf(fp, " percpu_counter: %ld\n",
> SIZE(percpu_counter));
> fprintf(fp, " cpumask_t: %ld\n",
> SIZE(cpumask_t));
> + fprintf(fp, " bpf_ringbuf_map: %ld\n",
> SIZE(bpf_ringbuf_map));
>
> fprintf(fp, "\n array_table:\n");
> /*
> --
> 2.47.0
>
2 days, 18 hours
Re: [PATCH] Fix the misleading uncompress error message
by lijiang
On Tue, Oct 7, 2025 at 7:37 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Tue, 7 Oct 2025 16:52:40 +1300
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] Fix the misleading uncompress error
> message
> To: devel(a)lists.crash-utility.osci.io
> Cc: Tao Liu <ltao(a)redhat.com>
> Message-ID: <20251007035240.28260-1-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> The "unxz" is missing for uncompressing fail message. Fix [1].
>
> [1]: https://github.com/crash-utility/crash/issues/220
Can you add the Resolves tag before Sob, E.g:
Resolves: https://github.com/crash-utility/crash/issues/220
Signed-off-by: Tao Liu <ltao(a)redhat.com>
And this looks good to me: Ack.
Thanks
Lianbo
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> symbols.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/symbols.c b/symbols.c
> index ee3cba1..e6af38b 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -4481,8 +4481,9 @@ is_compressed_kernel(char *file, char **tmp)
> }
> if (system(command) < 0) {
> please_wait_done();
> - error(INFO, "%s of %s failed\n",
> - type == GZIP ? "gunzip" : "bunzip2", file);
> + error(INFO, "%s of %s failed\n",
> + type == GZIP ? "gunzip" :
> + (type == BZIP2 ? "bunzip2" : "unxz"),
> file);
> free(tempname);
> return FALSE;
> }
> --
> 2.47.0
>
2 days, 18 hours
[PATCH v4] Add "log -R" to display human readable Rust symbol name
by Lianbo Jiang
Currently, the log command will display human readable Rust
symbol name by default if any, but, sometimes still want to
print the original messages from the log buffer(do not demangle).
In addition, if the log buffer has lines like "_R ... +" which
are not Rust symbols unexpectedly, probably the output will be
missed, that is unexpected.
To fix above cases, add "log -R" to display human readable Rust
symbol name, otherwise still print the original messages.
With the patch:
crash> log -R
...
[ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016
[ 2174.308966] Call Trace:
[ 2174.311693] <TASK>
[ 2174.314033] dump_stack_lvl+0x5d/0x80
[ 2174.318125] panic+0x156/0x32a
[ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]
[ 2174.329700] ? console_unlock+0x9c/0x140
[ 2174.334080] ? irq_work_queue+0x2d/0x50
[ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]
[ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]
[ 2174.353698] ? _printk+0x6b/0x90
[ 2174.357303] init_module+0x57/0xff0 [rust_panic]
[ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]
...
Link: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01652.html
Suggested-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
defs.h | 1 +
help.c | 24 ++++++++++++++++-
kernel.c | 5 +++-
printk.c | 79 ++++++++++++++++++++++++++++++++++++--------------------
4 files changed, 79 insertions(+), 30 deletions(-)
diff --git a/defs.h b/defs.h
index 3fd7d897c781..c434a5cae702 100644
--- a/defs.h
+++ b/defs.h
@@ -6229,6 +6229,7 @@ void parse_kernel_version(char *);
#define SHOW_LOG_CTIME (0x10)
#define SHOW_LOG_SAFE (0x20)
#define SHOW_LOG_CALLER (0x40)
+#define SHOW_LOG_RUST (0x80)
void set_cpu(int);
void clear_machdep_cache(void);
struct stack_hook *gather_text_list(struct bt_info *);
diff --git a/help.c b/help.c
index 4f071e0bd0a0..78d7a5c70e30 100644
--- a/help.c
+++ b/help.c
@@ -4026,7 +4026,7 @@ NULL
char *help_log[] = {
"log",
"dump system message buffer",
-"[-Ttdmasc]",
+"[-TtdmascR]",
" This command dumps the kernel log_buf contents in chronological order. The",
" command supports the older log_buf formats, which may or may not contain a",
" timestamp inserted prior to each message, as well as the newer variable-length",
@@ -4053,6 +4053,8 @@ char *help_log[] = {
" the CPU id (if in CPU context) that called printk(), if available.",
" Generally available on Linux 5.1 to 5.9 kernels configured with",
" CONFIG_PRINTK_CALLER or Linux 5.10 and later kernels.",
+" -R Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.",
" ",
"\nEXAMPLES",
" Dump the kernel message buffer:\n",
@@ -4231,6 +4233,26 @@ char *help_log[] = {
" [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
" [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3",
" ...",
+" ",
+" Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.\n",
+" %s> log -R",
+" ...",
+" [ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE",
+" [ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016",
+" [ 2174.308966] Call Trace:",
+" [ 2174.311693] <TASK>",
+" [ 2174.314033] dump_stack_lvl+0x5d/0x80",
+" [ 2174.318125] panic+0x156/0x32a",
+" [ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]",
+" [ 2174.329700] ? console_unlock+0x9c/0x140",
+" [ 2174.334080] ? irq_work_queue+0x2d/0x50",
+" [ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" [ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]",
+" [ 2174.353698] ? _printk+0x6b/0x90",
+" [ 2174.357303] init_module+0x57/0xff0 [rust_panic]",
+" [ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" ...",
NULL
};
diff --git a/kernel.c b/kernel.c
index e4213d7a663e..e077275d7ed6 100644
--- a/kernel.c
+++ b/kernel.c
@@ -5136,7 +5136,7 @@ cmd_log(void)
msg_flags = 0;
- while ((c = getopt(argcnt, args, "Ttdmasc")) != EOF) {
+ while ((c = getopt(argcnt, args, "TtdmascR")) != EOF) {
switch(c)
{
case 'T':
@@ -5160,6 +5160,9 @@ cmd_log(void)
case 'c':
msg_flags |= SHOW_LOG_CALLER;
break;
+ case 'R':
+ msg_flags |= SHOW_LOG_RUST;
+ break;
default:
argerrs++;
break;
diff --git a/printk.c b/printk.c
index 51b618e2a434..50cc2449dd69 100644
--- a/printk.c
+++ b/printk.c
@@ -116,7 +116,7 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
uint64_t ts_nsec;
ulonglong nanos;
ulonglong seq;
- int ilen = 0, i;
+ int ilen = 0, i, nlines;
char *desc, *info, *text, *p;
ulong rem;
@@ -202,44 +202,67 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
text = m->text_data + begin;
- if (text_len > BUFSIZE) {
+ if ((msg_flags & SHOW_LOG_RUST) && (text_len > BUFSIZE)) {
error(WARNING, "\nThe messages could be truncated!\n");
text_len = BUFSIZE;
}
- for (i = 0, p = text; i < text_len; i++, p++) {
- if (*p == '\n')
+ for (i = 0, nlines = 0, p = text; i < text_len; i++, p++) {
+ if (*p == '\n') {
+ /*
+ * When printing disassembly code blocks in the log, saw number
+ * of empty lines printed and some disassembly code was missed.
+ * So far I haven't got better solution to handle the current
+ * case(when the input data contains several lines, those '\n'
+ * are written one by one), here try to check if there are multiple
+ * line breaks to decide what to do next.
+ */
+ if ((msg_flags & SHOW_LOG_RUST) && (i != text_len - 1)) {
+ nlines++;
+ if (strlen(buf)) {
+ fprintf(fp, "%s", buf);
+ memset(buf, 0, strlen(buf));
+ }
+ }
fprintf(fp, "\n%s", space(ilen));
- else if (isprint(*p) || isspace(*p))
- sprintf(&buf[i], "%c", *p);
+ } else if ((msg_flags & SHOW_LOG_RUST) && (isprint(*p) || isspace(*p))) {
+ if (nlines >= 1)
+ fputc(*p, fp);
+ else
+ sprintf(&buf[i], "%c", *p);
+ } else if (isprint(*p) || isspace(*p))
+ fputc(*p, fp);
else
fputc('.', fp);
}
/*
* Try to demangle a mangled Rust symbol(calltrace) from log buffer
*/
- char *p1 = strstr(buf, "_R");
- if (!p1)
- p1 = strstr(buf, "_ZN");
- char *p2 = strrchr(buf, '+');
- if (p1 && p2) {
- char mangled[BUFSIZE] = {0};
- char demangled[BUFSIZE] = {0};
- char *res;
- size_t slen = p1 - buf;
-
- if (slen)
- memcpy(demangled, buf, slen);
-
- memcpy(mangled, p1, p2-p1);
- res = rust_demangle(mangled, DMGL_RUST);
- if (res) {
- snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
- fprintf(fp, "%s",demangled);
- free(res);
- }
- } else
- fprintf(fp, "%s", buf);
+ if (msg_flags & SHOW_LOG_RUST) {
+ char *p1 = strstr(buf, "_R");
+ if (!p1)
+ p1 = strstr(buf, "_ZN");
+ char *p2 = strrchr(buf, '+');
+ if (p1 && p2) {
+ char mangled[BUFSIZE] = {0};
+ char demangled[BUFSIZE] = {0};
+ char *res;
+ size_t slen = p1 - buf;
+
+ if (slen)
+ memcpy(demangled, buf, slen);
+
+ memcpy(mangled, p1, p2-p1);
+ res = rust_demangle(mangled, DMGL_RUST);
+ if (res) {
+ snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
+ fprintf(fp, "%s",demangled);
+ free(res);
+ } else
+ fprintf(fp, "%s", buf);
+ } else
+ fprintf(fp, "%s", buf);
+ }
if (msg_flags & SHOW_LOG_DICT) {
text = info + OFFSET(printk_info_dev_info) +
--
2.50.1
2 days, 19 hours
Re: [PATCH v3 3/3] s390x: Always perform kernel address translation in vtop verbose mode.
by Tao Liu
Hi Alexander & Mikhail,
Thanks for the improvements, LGTM, for the series, ack.
Thanks,
Tao Liu
On Tue, Oct 28, 2025 at 6:11 AM Alexander Gordeev
<agordeev(a)linux.ibm.com> wrote:
>
> On Mon, Oct 27, 2025 at 06:04:56PM +0100, Mikhail Zaslonko wrote:
> > In s390x_kvtop() early return may take place despite the verbose
> > flag. Thus we can miss page-table walk information in the vtop output
> > for kernel virtual addresses.
> > Make sure that s390x_vtop() is always called for kernel virtual addresses
> > when the verbose flag is passed to s390x_kvtop() by do_vtop().
> >
> > Suggested-by: Heiko Carstens <hca(a)linux.ibm.com>
> > Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.ibm.com>
> > ---
> > s390x.c | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/s390x.c b/s390x.c
> > index 25dca5e..77d9082 100644
> > --- a/s390x.c
> > +++ b/s390x.c
> > @@ -943,15 +943,15 @@ s390x_kvtop(struct task_context *tc, ulong vaddr, physaddr_t *paddr, int verbose
> >
> > if (!IS_KVADDR(vaddr)){
> > *paddr = 0;
> > return FALSE;
> > }
> >
> > - if (!IS_VMALLOC_ADDR(vaddr)) {
> > - *paddr = VTOP(vaddr);
> > - return TRUE;
> > + if (!verbose && !IS_VMALLOC_ADDR(vaddr)) {
> > + *paddr = VTOP(vaddr);
> > + return TRUE;
> > }
> >
> > pgd_base = (unsigned long)vt->kernel_pgd[0];
> > return s390x_vtop(pgd_base, vaddr, paddr, verbose);
> > }
>
> Acked-by: Alexander Gordeev <agordeev(a)linux.ibm.com>
>
2 days, 20 hours
[PATCH v2] vtop: Translate IEP flag for s390 region, segment and page entries
by Mikhail Zaslonko
Translate and print the IEP (Instruction Execution Protection) flag for
Region-Third-Table entries and Segment-Table entries of Format
Control 1 and also for Page-Table entries. Display the flags in s390x 'vtop'
command output like shown below:
STE: 0000000033be8ac0 => 0000000015803503 (flags = 03503)
flags in binary : AV=0; ACC=0011; F=0; FC=1; P=0; IEP=1; I=0; CS=0; TT=0
or
PTE: 00000000031c6fd8 => 000000000842e13d (flags = 13d)
flags in binary : I=0; P=0; IEP=1
Suggested-by: Heiko Carstens <hca(a)linux.ibm.com>
Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.ibm.com>
Reviewed-by: Heiko Carstens <hca(a)linux.ibm.com>
---
s390x.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/s390x.c b/s390x.c
index 0e8e2b3..8c0bba4 100644
--- a/s390x.c
+++ b/s390x.c
@@ -29,6 +29,7 @@
#define S390X_PTE_FLAG_BITS 0xfffULL /* Page table entry flag bits */
#define S390X_PAGE_PRESENT 0x001ULL /* set: loaded in physical memory
* clear: not loaded in physical mem */
+#define S390X_PAGE_IEP 0x100ULL /* Instruction-execution protection */
#define S390X_PAGE_RO 0x200ULL /* HW read-only */
#define S390X_PAGE_INVALID 0x400ULL /* HW invalid */
#define S390X_PAGE_INVALID_MASK 0x601ULL /* for linux 2.6 */
@@ -65,6 +66,7 @@
#define S390X_RTE_TF 0xc0ULL
#define S390X_RTE_TF_10 0x80ULL
#define S390X_RTE_TF_01 0x40ULL
+#define S390X_RTE_IEP 0x100ULL
#define S390X_RTE_P 0x200ULL
#define S390X_RTE_FC 0x400ULL
#define S390X_RTE_F 0x800ULL
@@ -82,6 +84,7 @@
#define S390X_STE_TT_01 0x4ULL
#define S390X_STE_CS 0x10ULL
#define S390X_STE_I 0x20ULL
+#define S390X_STE_IEP 0x100ULL
#define S390X_STE_P 0x200ULL
#define S390X_STE_FC 0x400ULL
#define S390X_STE_F 0x800ULL
@@ -979,7 +982,7 @@ static inline int s390x_pte_present(unsigned long x){
/* Print flags of Segment-Table entry with format control = 1 */
static void print_segment_entry_fc1(ulong val)
{
- fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; I=%u; CS=%u; TT=%u%u\n",
+ fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; IEP=%u; I=%u; CS=%u; TT=%u%u\n",
!!(val & S390X_STE_AV),
!!(val & S390X_STE_ACC_1000),
!!(val & S390X_STE_ACC_0100),
@@ -988,6 +991,7 @@ static void print_segment_entry_fc1(ulong val)
!!(val & S390X_STE_F),
!!(val & S390X_STE_FC),
!!(val & S390X_STE_P),
+ !!(val & S390X_STE_IEP),
!!(val & S390X_STE_I),
!!(val & S390X_STE_CS),
!!(val & S390X_STE_TT_10),
@@ -1009,7 +1013,7 @@ static void print_segment_entry_fc0(ulong val)
/* Print flags of Region-Third-Table entry with format control = 1 */
static void print_region_third_entry_fc1(ulong val)
{
- fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; I=%u; CR=%u; TT=%u%u\n",
+ fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; IEP=%u; I=%u; CR=%u; TT=%u%u\n",
!!(val & S390X_RTE_AV),
!!(val & S390X_RTE_ACC_1000),
!!(val & S390X_RTE_ACC_0100),
@@ -1018,6 +1022,7 @@ static void print_region_third_entry_fc1(ulong val)
!!(val & S390X_RTE_F),
!!(val & S390X_RTE_FC),
!!(val & S390X_RTE_P),
+ !!(val & S390X_RTE_IEP),
!!(val & S390X_RTE_I),
!!(val & S390X_RTE_CR),
!!(val & S390X_RTE_TT_10),
@@ -1151,8 +1156,10 @@ static ulong _kl_pg_table_deref_s390x(ulong vaddr, ulong table, int verbose)
if (verbose) {
fprintf(fp, "%5s: %016lx => %016lx (flags = %03llx)\n",
"PTE", addr, entry, entry & S390X_PTE_FLAG_BITS);
- fprintf(fp, " flags in binary : I=%u; P=%u\n",
- !!(entry & S390X_PAGE_INVALID), !!(entry & S390X_PAGE_RO));
+ fprintf(fp, " flags in binary : I=%u; P=%u; IEP=%u\n",
+ !!(entry & S390X_PAGE_INVALID),
+ !!(entry & S390X_PAGE_RO),
+ !!(entry & S390X_PAGE_IEP));
fprintf(fp, "%5s: %016llx\n", "PAGE", entry & ~S390X_PTE_FLAG_BITS);
}
/*
--
2.49.0
2 days, 21 hours