[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 weeks, 3 days
Decoding Consumer Minds: Fresh Ideas for Marketing Research Papers
by kefag22407@haotuwu.com
Marketing is no longer just about selling — it’s about understanding why people buy, share, and stay loyal. Research papers in marketing can dive into fascinating areas like consumer psychology, digital engagement, and emotional branding. Exploring topics such as the impact of social media influencers on brand perception, consumer trust in AI-driven recommendations, or sustainability as a driver of purchase intent can help uncover what really shapes modern consumer decisions.
Another promising angle is studying data and personalization in marketing. With companies relying heavily on analytics, there’s a growing need to explore how data-driven strategies influence consumer experience and brand loyalty. Researching ethical data usage, AI in customer segmentation, or neuromarketing trends can lead to insights that bridge creativity with strategy — essential for any marketer looking to make an impact in today’s competitive landscape. Have more info at: https://thedissertationhelp.co.uk/marketing-research-paper-topics/
3 weeks
Decoding Consumer Minds: Fresh Ideas for Marketing Research Papers
by kefag22407@haotuwu.com
Marketing is no longer just about selling — it’s about understanding why people buy, share, and stay loyal. Research papers in marketing can dive into fascinating areas like consumer psychology, digital engagement, and emotional branding. Exploring topics such as the impact of social media influencers on brand perception, consumer trust in AI-driven recommendations, or sustainability as a driver of purchase intent can help uncover what really shapes modern consumer decisions.
Another promising angle is studying data and personalization in marketing. With companies relying heavily on analytics, there’s a growing need to explore how data-driven strategies influence consumer experience and brand loyalty. Researching ethical data usage, AI in customer segmentation, or neuromarketing trends can lead to insights that bridge creativity with strategy — essential for any marketer looking to make an impact in today’s competitive landscape. Have more info at: https://thedissertationhelp.co.uk/marketing-research-paper-topics/
3 weeks
[PATCH v2] vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data' when unavailable in elf note
by Aditya Gupta
Few vmcores don't have vmcoreinfo elf note, such as those created using
virsh-dump.
On architectures such as PowerPC64, vmcoreinfo is mandatory to fetch the
first_vmalloc_address, for vmcores of upstream linux, since crash-utility commit:
commit 5b24e363a898 ("get vmalloc start address from vmcoreinfo")
Try reading from the 'vmcoreinfo_data' symbol instead, if the vmcoreinfo
crash tries to read in case of diskdump/netdump is empty/missing.
The approach to read 'vmcoreinfo_data' was used for a live kernel, which can be
reused in the case of missing vmcoreinfo note also, as the
'vmcoreinfo_data' symbol is available with vmcore too
Note though, till GDB interface is not initialised, reading from
vmcoreinfo_data symbol is not done, so behaviour is same as previously
with no vmcoreinfo (only till GDB interface is not initialised)
Hence rename 'vmcoreinfo_read_string' in kernel.c to
'vmcoreinfo_read_from_memory', and use it in netdump.c and diskdump.c
too.
Reported-by: Anushree Mathur <anushree.mathur(a)linux.ibm.com>
Tested-by: Anushree Mathur <anushree.mathur(a)linux.ibm.com>
Signed-off-by: Aditya Gupta <adityag(a)linux.ibm.com>
---
Changelog
=========
v2:
+ rename 'is_vmcoreinfo_empty' to netdump/diskdump variants in
netdump.c and diskdump.c respectively
---
---
defs.h | 1 +
diskdump.c | 18 ++++++++++++++++++
kernel.c | 17 ++++++++++++-----
netdump.c | 19 +++++++++++++++++++
4 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/defs.h b/defs.h
index 156ac0232906..d28484ec44f9 100644
--- a/defs.h
+++ b/defs.h
@@ -6218,6 +6218,7 @@ void dump_kernel_table(int);
void dump_bt_info(struct bt_info *, char *where);
void dump_log(int);
void parse_kernel_version(char *);
+char *vmcoreinfo_read_from_memory(const char *);
#define LOG_LEVEL(v) ((v) & 0x07)
#define SHOW_LOG_LEVEL (0x1)
diff --git a/diskdump.c b/diskdump.c
index ce3cbb7b12dd..de907551153d 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -1041,6 +1041,13 @@ pfn_to_pos(ulong pfn)
return desc_pos;
}
+/**
+ * Check if vmcoreinfo in vmcore is missing/empty
+ */
+static bool is_diskdump_vmcoreinfo_empty(void)
+{
+ return (dd->sub_header_kdump->size_vmcoreinfo == 0);
+}
/*
* Determine whether a file is a diskdump creation, and if TRUE,
@@ -1088,6 +1095,17 @@ is_diskdump(char *file)
pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ /*
+ * vmcoreinfo can be empty in case of dump collected via virsh-dump
+ *
+ * check if vmcoreinfo is not available in vmcore, and try to read
+ * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
+ */
+ if (is_diskdump_vmcoreinfo_empty()) {
+ error(WARNING, "vmcoreinfo is empty, will read from symbols\n");
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
+ }
+
if ((pc->flags2 & GET_LOG) && KDUMP_CMPRS_VALID()) {
pc->dfd = dd->dfd;
pc->readmem = read_diskdump;
diff --git a/kernel.c b/kernel.c
index e4213d7a663e..0e17874c503c 100644
--- a/kernel.c
+++ b/kernel.c
@@ -99,7 +99,6 @@ static ulong dump_audit_skb_queue(ulong);
static ulong __dump_audit(char *);
static void dump_audit(void);
static void dump_printk_safe_seq_buf(int);
-static char *vmcoreinfo_read_string(const char *);
static void check_vmcoreinfo(void);
static int is_pvops_xen(void);
static int get_linux_banner_from_vmlinux(char *, size_t);
@@ -11892,8 +11891,8 @@ dump_printk_safe_seq_buf(int msg_flags)
* Returns a string (that has to be freed by the caller) that contains the
* value for key or NULL if the key has not been found.
*/
-static char *
-vmcoreinfo_read_string(const char *key)
+char *
+vmcoreinfo_read_from_memory(const char *key)
{
char *buf, *value_string, *p1, *p2;
size_t value_length;
@@ -11903,6 +11902,14 @@ vmcoreinfo_read_string(const char *key)
buf = value_string = NULL;
+ if (!(pc->flags & GDB_INIT)) {
+ /*
+ * GDB interface hasn't been initialised yet, so can't
+ * access vmcoreinfo_data
+ */
+ return NULL;
+ }
+
switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
{
case TYPE_CODE_PTR:
@@ -11958,10 +11965,10 @@ check_vmcoreinfo(void)
switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
{
case TYPE_CODE_PTR:
- pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
break;
case TYPE_CODE_ARRAY:
- pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
break;
}
}
diff --git a/netdump.c b/netdump.c
index c7ff009e7f90..69100a92e067 100644
--- a/netdump.c
+++ b/netdump.c
@@ -111,6 +111,14 @@ map_cpus_to_prstatus(void)
FREEBUF(nt_ptr);
}
+/**
+ * Check if vmcoreinfo in vmcore is missing/empty
+ */
+static bool is_netdump_vmcoreinfo_empty(void)
+{
+ return (nd->size_vmcoreinfo == 0);
+}
+
/*
* Determine whether a file is a netdump/diskdump/kdump creation,
* and if TRUE, initialize the vmcore_data structure.
@@ -464,6 +472,17 @@ is_netdump(char *file, ulong source_query)
pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ /*
+ * vmcoreinfo can be empty in case of dump collected via virsh-dump
+ *
+ * check if vmcoreinfo is not available in vmcore, and try to read
+ * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
+ */
+ if (is_netdump_vmcoreinfo_empty()) {
+ error(WARNING, "vmcoreinfo is empty, will read from symbols\n");
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
+ }
+
if ((source_query == KDUMP_LOCAL) &&
(pc->flags2 & GET_OSRELEASE))
kdump_get_osrelease();
--
2.50.1
3 weeks
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
>
3 weeks
[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
3 weeks
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
>
3 weeks
[PATCH v3 1/3] s390x: Add non-zero vmalloc_start check to s390x_vr_IS_VMALLOC_ADDR()
by Mikhail Zaslonko
Update s390x_vr_IS_VMALLOC_ADDR() to include a non-zero vmalloc_start
check, making it consistent with s390x_generic_IS_VMALLOC_ADDR().
Fixes: d0164e7e480a ("s390x: uncouple physical and virtual memory spaces")
Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.ibm.com>
---
s390x.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/s390x.c b/s390x.c
index 0e8e2b3..1117bf0 100644
--- a/s390x.c
+++ b/s390x.c
@@ -724,13 +724,13 @@ static ulong s390x_vr_PTOV(ulong paddr)
{
return paddr + machdep->identity_map_base;
}
static int s390x_vr_IS_VMALLOC_ADDR(ulong vaddr)
{
- return (vaddr >= vt->vmalloc_start && vaddr < machdep->kvbase);
+ return (vt->vmalloc_start && vaddr >= vt->vmalloc_start && vaddr < machdep->kvbase);
}
ulong s390x_VTOP(ulong vaddr)
{
return machdep->machspec->virt_to_phys(vaddr);
}
--
2.49.0
3 weeks
[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
3 weeks, 2 days
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
>
3 weeks, 3 days