[PATCH] memory: Handle crash failure in linux-next caused by struct kmem_cache changes
by Mikhail Zaslonko
Since kernel commit cf338283652f ("slab: remove struct kmem_cache_cpu")
in linux-next we have no more 'cpu_slab' member in struct kmem_cache.
Pick 'cpu_sheaves' as an alternative kmem_cache member for kernel-next to
identify the SLUB case.
Without the patch, crash fails to start on kernel-next with the error
message:
crash: invalid structure member offset: kmem_cache_s_num
FILE: memory.c LINE: 9988 FUNCTION: kmem_cache_init()
This fix allows the crash to start with no errors. But kmap -s is no
longer working for kernel-next since kmem_cache_cpu array is completely
missing.
Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.ibm.com>
---
memory.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/memory.c b/memory.c
index cbc8d2f..3373fdb 100644
--- a/memory.c
+++ b/memory.c
@@ -672,6 +672,7 @@ vm_init(void)
} else if (!VALID_STRUCT(kmem_slab_s) &&
!VALID_STRUCT(slab_s) &&
!MEMBER_EXISTS("kmem_cache", "cpu_slab") &&
+ !MEMBER_EXISTS("kmem_cache", "cpu_sheaves") &&
(VALID_STRUCT(slab) || (vt->flags & SLAB_OVERLOAD_PAGE))) {
vt->flags |= PERCPU_KMALLOC_V2;
@@ -816,7 +817,7 @@ vm_init(void)
if (INVALID_MEMBER(page_first_page))
ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page");
- } else if (MEMBER_EXISTS("kmem_cache", "cpu_slab") &&
+ } else if ((MEMBER_EXISTS("kmem_cache", "cpu_slab") || MEMBER_EXISTS("kmem_cache", "cpu_sheaves")) &&
STRUCT_EXISTS("kmem_cache_node")) {
vt->flags |= KMALLOC_SLUB;
--
2.52.0
12 hours, 56 minutes
Re: [PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output format
by lijiang
Hi, PengFei
Thank you for the patch.
I can not apply your patch in my local repo, it seems some encoding issue
at my mail client. Can you help check your patch and
make sure that it's text/plain?
Thanks
Lianbo
On Wed, Jan 28, 2026 at 9:54 AM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Mon, 26 Jan 2026 10:02:48 +0000
> From: 李鹏飞 <lipengfei28(a)xiaomi.com>
> Subject: [Crash-utility] [PATCH] arm64: Fix broken/incomplete gdb
> backtrace and unify output format
> To: "devel(a)lists.crash-utility.osci.io"
> <devel(a)lists.crash-utility.osci.io>
> Cc: "anderson(a)redhat.com" <anderson(a)redhat.com>
> Message-ID: <5db18509249d4a10a0b12a70b92a5a73(a)xiaomi.com>
> Content-Type: multipart/alternative;
> boundary="_000_5db18509249d4a10a0b12a70b92a5a73xiaomicom_"
>
> --_000_5db18509249d4a10a0b12a70b92a5a73xiaomicom_
> Content-Type: text/plain; charset="gb2312"
> Content-Transfer-Encoding: base64
>
>
> RnJvbSA0ZDgzMmEzM2ViZDgwYmQxMDljYzVhNDdmOThjNmIzNWZkY2JkOTU2IE1vbiBTZXAgMTcg
>
> MDA6MDA6MDAgMjAwMQ0KRnJvbTogbGlwZW5nZmVpMjggPGxpcGVuZ2ZlaTI4QHhpYW9taS5jb20+
>
> DQpEYXRlOiBGcmksIDIzIEphbiAyMDI2IDE2OjI0OjA3ICswODAwDQpTdWJqZWN0OiBbUEFUQ0hd
>
> ICBhcm02NDogRml4IGJyb2tlbi9pbmNvbXBsZXRlIGdkYiBiYWNrdHJhY2UgYW5kIHVuaWZ5IG91
>
> dHB1dA0KZm9ybWF0DQoNClRoaXMgcGF0Y2ggZml4ZXMgbXVsdGlwbGUgaXNzdWVzIHdpdGggJ2dk
>
> YiBidCcgb24gQVJNNjQsIHdoZXJlIHRoZSBiYWNrdHJhY2UNCndvdWxkIGJlIGludGVycnVwdGVk
>
> LCBjb250YWluIGdhcmJhZ2UgdGhyZWFkcywgb3IgZGlzcGxheSBmcmFnbWVudGVkIG91dHB1dC4N
>
> Cg0KMS4gRml4IE91dC1vZi1Cb3VuZHMgUmVhZCBpbiBFeGNlcHRpb24gRnJhbWUgSGFuZGxpbmc6
>
> DQogICAgSW4gYGFybTY0X3ByaW50X2V4Y2VwdGlvbl9mcmFtZWAsIHRoZSBjb2RlIHByZXZpb3Vz
>
> bHkgdXNlZCBgbWVtY3B5YCB0byBjb3B5DQogICAgYHNpemVvZihzdHJ1Y3QgYXJtNjRfcHRfcmVn
>
> cylgIGJ5dGVzIGZyb20gYSBgc3RydWN0IGFybTY0X3N0YWNrZnJhbWUgKmAgc291cmNlLg0KICAg
>
> IFNpbmNlIGBzdGFja2ZyYW1lYCBpcyBzaWduaWZpY2FudGx5IHNtYWxsZXIgdGhhbiBgcHRfcmVn
>
> c2AsIHRoaXMgY2F1c2VkIGFuDQogICAgb3V0LW9mLWJvdW5kcyByZWFkLCBwb3B1bGF0aW5nIHRo
> ...
1 week, 5 days
[PATCH] Reapply "vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data' when unavailable in elf note"
by Shivang Upadhyay
Commit 7636c13 ("vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data'
when unavailable in elf note") moved the vmcoreinfo reading to always
read from memory instead of relying on diskdump/netdump's local
handlers. This was later reverted to fix regression in X86_64 kslar
images.
Reintroduce the `vmcoreinfo_read_from_memory` as fallback to
diskdump/netdump vmcores.
This reverts commit 72e2776caf1ca41dffcc8aba11c55c636565725b.
Cc: Aditya Gupta <adityag(a)linux.ibm.com>
Cc: Tao Liu <ltao(a)redhat.com>
Signed-off-by: Shivang Upadhyay <shivangu(a)linux.ibm.com>
---
defs.h | 1 +
diskdump.c | 3 +++
kernel.c | 17 ++++++++++++-----
netdump.c | 2 ++
4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/defs.h b/defs.h
index ceed3a9..e5d38c2 100644
--- a/defs.h
+++ b/defs.h
@@ -6235,6 +6235,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 0ff8782..c16e7b9 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -2434,6 +2434,9 @@ err:
if (buf)
free(buf);
+ if (value_string == NULL)
+ return vmcoreinfo_read_from_memory(key);
+
return value_string;
}
diff --git a/kernel.c b/kernel.c
index bb148d0..ec287bb 100644
--- a/kernel.c
+++ b/kernel.c
@@ -100,7 +100,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);
@@ -11960,8 +11959,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;
@@ -11971,6 +11970,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:
@@ -12026,10 +12033,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 ba1c6c4..fd0d545 100644
--- a/netdump.c
+++ b/netdump.c
@@ -2020,6 +2020,8 @@ vmcoreinfo_read_string(const char *key)
}
}
+ if (value == NULL)
+ return vmcoreinfo_read_from_memory(key);
return value;
}
--
2.52.0
2 weeks, 1 day
[PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output format
by lipengfei28@xiaomi.com
From 4d832a33ebd80bd109cc5a47f98c6b35fdcbd956 Mon Sep 17 00:00:00 2001
From: lipengfei28 <lipengfei28(a)xiaomi.com>
Date: Fri, 23 Jan 2026 16:24:07 +0800
Subject: [PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output
format
This patch fixes multiple issues with 'gdb bt' on ARM64, where the backtrace
would be interrupted, contain garbage threads, or display fragmented output.
1. Fix Out-of-Bounds Read in Exception Frame Handling:
In `arm64_print_exception_frame`, the code previously used `memcpy` to copy
`sizeof(struct arm64_pt_regs)` bytes from a `struct arm64_stackframe *` source.
Since `stackframe` is significantly smaller than `pt_regs`, this caused an
out-of-bounds read, populating the GDB thread registers with stack garbage
(often resulting in invalid addresses like -3/0xff...fd).
This is fixed by manually copying only the valid registers (PC, SP, FP, etc.)
and properly initializing the bitmap.
2. Bridge the Gap Between IRQ and Process Stacks:
Previously, GDB unwinding would stop at `call_on_irq_stack` because it could
not automatically unwind through the assembly trampoline back to the process
stack.
Modified `arm64_switch_stack` (and the overflow variant) to "peek" one frame
ahead (reading the saved FP/PC of the caller) before registering the new
GDB substack. This effectively bridges the discontinuity, allowing GDB to
show frames like `do_interrupt_handler` that were previously missing.
3. Unify and Format GDB Output:
Modified `gdb_interface.c` to:
- Strip "Thread <id>" headers to present a continuous backtrace similar to
the native `crash bt`.
- Renumber stack frames sequentially (e.g., #0 to #30) instead of resetting
at each stack switch.
- Add indentation/alignment for frames where GDB omits the address (e.g.,
inline functions) to improve readability.
4. Prevent Invalid Thread Creation:
Added checks to ensure a GDB substack is only created if the Program Counter
(PC) is non-zero, preventing the display of "corrupt" or empty threads.
Tested on: Android 6.x ARM64
Signed-off-by: lipengfei28 <lipengfei28(a)xiaomi.com>
---
arm64.c | 117 +++++++++++++++++++++++++++++++++++++------
gdb_interface.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 229 insertions(+), 18 deletions(-)
diff --git a/arm64.c b/arm64.c
index c125655..f842739 100644
--- a/arm64.c
+++ b/arm64.c
@@ -3026,6 +3026,9 @@ static char *arm64_exception_functions[] = {
"do_el0_irq_bp_hardening",
"do_sp_pc_abort",
"handle_bad_stack",
+ "el1h_64_sync",
+ "el1h_64_irq",
+ "el1h_64_error",
NULL
};
@@ -3123,6 +3126,11 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr
fprintf(ofp, "\n");
+ if (STREQ(name, "el1h_64_irq") || STREQ(name, "el1h_64_sync"))
+ if (arm64_is_kernel_exception_frame(bt, frame->sp)) {
+ arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ }
+
if (bt->flags & BT_LINE_NUMBERS) {
get_line_number(branch_pc, buf, FALSE);
if (strlen(buf))
@@ -3775,11 +3783,12 @@ arm64_back_trace_cmd(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (!bt->machdep ||
(extra_stacks_regs[extra_stacks_idx]->ur.sp !=
((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
extra_stacks_regs[extra_stacks_idx]->ur.pc !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -3925,11 +3934,12 @@ arm64_back_trace_cmd_v2(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (!bt->machdep ||
(extra_stacks_regs[extra_stacks_idx]->ur.sp !=
((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
extra_stacks_regs[extra_stacks_idx]->ur.pc !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -4263,8 +4273,40 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ if (!extra_stacks_regs[extra_stacks_idx]) {
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+ malloc(sizeof(struct user_regs_bitmap_struct));
+ }
+ memset(extra_stacks_regs[extra_stacks_idx], 0, sizeof(struct user_regs_bitmap_struct));
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ ulong next_fp = GET_STACK_ULONG(frame->fp);
+ ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+ ulong next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
+ }
return KERNEL_MODE;
}
@@ -4300,8 +4342,40 @@ arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *fr
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ if (!extra_stacks_regs[extra_stacks_idx]) {
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+ malloc(sizeof(struct user_regs_bitmap_struct));
+ }
+ memset(extra_stacks_regs[extra_stacks_idx], 0, sizeof(struct user_regs_bitmap_struct));
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ ulong next_fp = GET_STACK_ULONG(frame->fp);
+ ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+ ulong next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
+ }
return KERNEL_MODE;
}
@@ -4556,16 +4630,27 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o
}
memset(extra_stacks_regs[extra_stacks_idx], 0,
sizeof(struct user_regs_bitmap_struct));
- memcpy(&extra_stacks_regs[extra_stacks_idx]->ur, regs,
- sizeof(struct arm64_pt_regs));
- for (int i = 0; i < sizeof(struct arm64_pt_regs)/sizeof(long); i++)
- SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i);
- if (!bt->machdep ||
- (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
- extra_stacks_regs[extra_stacks_idx]->ur.pc !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
- gdb_add_substack (extra_stacks_idx++);
+ {
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+ int i;
+
+ ur_ptr->ur.pc = regs->pc;
+ ur_ptr->ur.sp = regs->sp;
+ ur_ptr->ur.pstate = regs->pstate;
+ for (i = 0; i < 31; i++)
+ ur_ptr->ur.regs[i] = regs->regs[i];
+
+ for (i = 0; i < 34; i++)
+ SET_BIT(ur_ptr->bitmap, i);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
}
}
}
diff --git a/gdb_interface.c b/gdb_interface.c
index 9f76f85..d14144e 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -16,6 +16,7 @@
*/
#include "defs.h"
+#include <ctype.h>
#if !defined(GDB_10_2) && !defined(GDB_16_2)
static void exit_after_gdb_info(void);
@@ -779,22 +780,53 @@ strip_redirection(char *buf)
/*
* Command for passing strings directly to gdb.
*/
+static void format_and_print_gdb_bt(FILE *input_fp);
+
void
cmd_gdb(void)
{
char buf[BUFSIZE];
char **argv;
+ int i;
argv = STREQ(args[0], "gdb") ? &args[1] : &args[0];
if (*argv == NULL)
cmd_usage(pc->curcmd, SYNOPSIS);
+ if (STREQ(*argv, "bt")) {
+ FILE *tmp_fp;
+
+ if ((tmp_fp = tmpfile()) == NULL) {
+ error(FATAL, "cannot create temporary file for GDB output\n");
+ }
+
+ strcpy(buf, "thread apply all bt");
+ /* Append any arguments that were passed to 'bt' */
+ /* args[0] is "gdb", args[1] is "bt", so options start at index 2 */
+ for (i = 2; i < argcnt; i++) {
+ strcat(buf, " ");
+ strcat(buf, args[i]);
+ }
+
+ if (!gdb_pass_through(buf, tmp_fp, GNU_RETURN_ON_ERROR)) {
+ fclose(tmp_fp);
+ error(INFO, "gdb request failed: %s\n", buf);
+ return;
+ }
+
+ rewind(tmp_fp);
+ format_and_print_gdb_bt(tmp_fp);
+
+ fclose(tmp_fp);
+ return;
+ }
+
if (STREQ(*argv, "set") && argv[1]) {
/*
* Intercept set commands in case something has to be done
- * here or elsewhere.
- */
+ * here or elsewhere.
+ */
if (STREQ(argv[1], "gdb")) {
cmd_set();
return;
@@ -821,6 +853,100 @@ cmd_gdb(void)
}
}
+#define MAX_BT_LINES 1024
+#define MAX_THREAD_BLOCKS 64
+
+/*
+ * Helper function to parse 'thread apply all bt' output, reverse the
+ * thread blocks, and print the result.
+ */
+static void format_and_print_gdb_bt(FILE *input_fp)
+{
+ char *lines[MAX_BT_LINES];
+ int line_count = 0;
+ int thread_starts[MAX_THREAD_BLOCKS];
+ int thread_count = 0;
+ char line_buffer[BUFSIZE];
+ int i, j;
+ int global_frame_cnt = 0;
+
+ // Read all lines into memory
+ while (fgets(line_buffer, BUFSIZE, input_fp) && line_count < MAX_BT_LINES) {
+ if (strstr(line_buffer, "Thread ") == line_buffer) {
+ if (thread_count < MAX_THREAD_BLOCKS) {
+ thread_starts[thread_count++] = line_count;
+ }
+ }
+ lines[line_count] = strdup(line_buffer);
+ if (!lines[line_count]) {
+ error(FATAL, "strdup failed while reading gdb output\n");
+ }
+ line_count++;
+ }
+
+ if (thread_count == 0) { // If no threads, just print everything as is.
+ for (i = 0; i < line_count; i++) {
+ fputs(lines[i], fp);
+ }
+ } else {
+ // Iterate threads in reverse order to fix the display order
+ for (i = thread_count - 1; i >= 0; i--) {
+ int start_line = thread_starts[i];
+ int end_line = (i == thread_count - 1) ? line_count : thread_starts[i+1];
+
+ // Print thread frames, stripping header and renumbering
+ for (j = start_line; j < end_line; j++) {
+ char *line = lines[j];
+ // Skip "Thread " line
+ if (strncmp(line, "Thread ", 7) == 0) continue;
+ // Skip "Backtrace stopped" or similar noise if desired,
+ // but usually GDB prints "Backtrace stopped" at the very end.
+ // We'll keep it for info unless it's in the middle of our merge.
+ // Actually, duplicate frames or stops might appear.
+ // For now, simple renumbering.
+
+ char *ptr = line;
+ while (*ptr == ' ' || *ptr == '\t') ptr++;
+
+ if (*ptr == '#') {
+ // Frame line: #0 0x...
+ char *rest = ptr + 1;
+ while (isdigit(*rest)) rest++; // Skip old number
+
+ // Parse content to check for address
+ char *p = rest;
+ while (*p == ' ' || *p == '\t') p++;
+
+ int has_addr = (strncmp(p, "0x", 2) == 0);
+
+ // Print number
+ fprintf(fp, "#%-3d", global_frame_cnt++);
+
+ // Align if address is missing
+ if (!has_addr) {
+ // Align function name with frames that have addresses
+ // 64-bit: 0x... (18 chars) + " in " (4 chars) = 22 chars
+ // 32-bit: 0x... (10 chars) + " in " (4 chars) = 14 chars
+ int width = (machdep->bits == 64) ? 22 : 14;
+ for (int k = 0; k < width; k++) fputc(' ', fp);
+ }
+
+ fputs(rest, fp);
+ } else {
+ // Other lines (e.g. variable info, code)
+ fputs(line, fp);
+ }
+ }
+ }
+ }
+
+ // Cleanup
+ for (i = 0; i < line_count; i++) {
+ free(lines[i]);
+ }
+}
+
+
/*
* The gdb target_xfer_memory() has a hook installed to re-route
* all memory accesses back here; reads of 1 or 4 bytes come primarily
--
2.34.1
2 weeks, 2 days
[PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output format
by 李鹏飞
From 4d832a33ebd80bd109cc5a47f98c6b35fdcbd956 Mon Sep 17 00:00:00 2001
From: lipengfei28 <lipengfei28(a)xiaomi.com>
Date: Fri, 23 Jan 2026 16:24:07 +0800
Subject: [PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output
format
This patch fixes multiple issues with 'gdb bt' on ARM64, where the backtrace
would be interrupted, contain garbage threads, or display fragmented output.
1. Fix Out-of-Bounds Read in Exception Frame Handling:
In `arm64_print_exception_frame`, the code previously used `memcpy` to copy
`sizeof(struct arm64_pt_regs)` bytes from a `struct arm64_stackframe *` source.
Since `stackframe` is significantly smaller than `pt_regs`, this caused an
out-of-bounds read, populating the GDB thread registers with stack garbage
(often resulting in invalid addresses like -3/0xff...fd).
This is fixed by manually copying only the valid registers (PC, SP, FP, etc.)
and properly initializing the bitmap.
2. Bridge the Gap Between IRQ and Process Stacks:
Previously, GDB unwinding would stop at `call_on_irq_stack` because it could
not automatically unwind through the assembly trampoline back to the process
stack.
Modified `arm64_switch_stack` (and the overflow variant) to "peek" one frame
ahead (reading the saved FP/PC of the caller) before registering the new
GDB substack. This effectively bridges the discontinuity, allowing GDB to
show frames like `do_interrupt_handler` that were previously missing.
3. Unify and Format GDB Output:
Modified `gdb_interface.c` to:
- Strip "Thread <id>" headers to present a continuous backtrace similar to
the native `crash bt`.
- Renumber stack frames sequentially (e.g., #0 to #30) instead of resetting
at each stack switch.
- Add indentation/alignment for frames where GDB omits the address (e.g.,
inline functions) to improve readability.
4. Prevent Invalid Thread Creation:
Added checks to ensure a GDB substack is only created if the Program Counter
(PC) is non-zero, preventing the display of "corrupt" or empty threads.
Tested on: Android 6.x ARM64
Signed-off-by: lipengfei28 <lipengfei28(a)xiaomi.com>
---
arm64.c | 117 +++++++++++++++++++++++++++++++++++++------
gdb_interface.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 229 insertions(+), 18 deletions(-)
diff --git a/arm64.c b/arm64.c
index c125655..f842739 100644
--- a/arm64.c
+++ b/arm64.c
@@ -3026,6 +3026,9 @@ static char *arm64_exception_functions[] = {
"do_el0_irq_bp_hardening",
"do_sp_pc_abort",
"handle_bad_stack",
+ "el1h_64_sync",
+ "el1h_64_irq",
+ "el1h_64_error",
NULL
};
@@ -3123,6 +3126,11 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr
fprintf(ofp, "\n");
+ if (STREQ(name, "el1h_64_irq") || STREQ(name, "el1h_64_sync"))
+ if (arm64_is_kernel_exception_frame(bt, frame->sp)) {
+ arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ }
+
if (bt->flags & BT_LINE_NUMBERS) {
get_line_number(branch_pc, buf, FALSE);
if (strlen(buf))
@@ -3775,11 +3783,12 @@ arm64_back_trace_cmd(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (!bt->machdep ||
(extra_stacks_regs[extra_stacks_idx]->ur.sp !=
((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
extra_stacks_regs[extra_stacks_idx]->ur.pc !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -3925,11 +3934,12 @@ arm64_back_trace_cmd_v2(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (!bt->machdep ||
(extra_stacks_regs[extra_stacks_idx]->ur.sp !=
((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
extra_stacks_regs[extra_stacks_idx]->ur.pc !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -4263,8 +4273,40 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ if (!extra_stacks_regs[extra_stacks_idx]) {
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+ malloc(sizeof(struct user_regs_bitmap_struct));
+ }
+ memset(extra_stacks_regs[extra_stacks_idx], 0, sizeof(struct user_regs_bitmap_struct));
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ ulong next_fp = GET_STACK_ULONG(frame->fp);
+ ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+ ulong next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
+ }
return KERNEL_MODE;
}
@@ -4300,8 +4342,40 @@ arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *fr
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ if (!extra_stacks_regs[extra_stacks_idx]) {
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+ malloc(sizeof(struct user_regs_bitmap_struct));
+ }
+ memset(extra_stacks_regs[extra_stacks_idx], 0, sizeof(struct user_regs_bitmap_struct));
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ ulong next_fp = GET_STACK_ULONG(frame->fp);
+ ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+ ulong next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
+ }
return KERNEL_MODE;
}
@@ -4556,16 +4630,27 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o
}
memset(extra_stacks_regs[extra_stacks_idx], 0,
sizeof(struct user_regs_bitmap_struct));
- memcpy(&extra_stacks_regs[extra_stacks_idx]->ur, regs,
- sizeof(struct arm64_pt_regs));
- for (int i = 0; i < sizeof(struct arm64_pt_regs)/sizeof(long); i++)
- SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i);
- if (!bt->machdep ||
- (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
- extra_stacks_regs[extra_stacks_idx]->ur.pc !=
- ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
- gdb_add_substack (extra_stacks_idx++);
+ {
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+ int i;
+
+ ur_ptr->ur.pc = regs->pc;
+ ur_ptr->ur.sp = regs->sp;
+ ur_ptr->ur.pstate = regs->pstate;
+ for (i = 0; i < 31; i++)
+ ur_ptr->ur.regs[i] = regs->regs[i];
+
+ for (i = 0; i < 34; i++)
+ SET_BIT(ur_ptr->bitmap, i);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
}
}
}
diff --git a/gdb_interface.c b/gdb_interface.c
index 9f76f85..d14144e 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -16,6 +16,7 @@
*/
#include "defs.h"
+#include <ctype.h>
#if !defined(GDB_10_2) && !defined(GDB_16_2)
static void exit_after_gdb_info(void);
@@ -779,22 +780,53 @@ strip_redirection(char *buf)
/*
* Command for passing strings directly to gdb.
*/
+static void format_and_print_gdb_bt(FILE *input_fp);
+
void
cmd_gdb(void)
{
char buf[BUFSIZE];
char **argv;
+ int i;
argv = STREQ(args[0], "gdb") ? &args[1] : &args[0];
if (*argv == NULL)
cmd_usage(pc->curcmd, SYNOPSIS);
+ if (STREQ(*argv, "bt")) {
+ FILE *tmp_fp;
+
+ if ((tmp_fp = tmpfile()) == NULL) {
+ error(FATAL, "cannot create temporary file for GDB output\n");
+ }
+
+ strcpy(buf, "thread apply all bt");
+ /* Append any arguments that were passed to 'bt' */
+ /* args[0] is "gdb", args[1] is "bt", so options start at index 2 */
+ for (i = 2; i < argcnt; i++) {
+ strcat(buf, " ");
+ strcat(buf, args[i]);
+ }
+
+ if (!gdb_pass_through(buf, tmp_fp, GNU_RETURN_ON_ERROR)) {
+ fclose(tmp_fp);
+ error(INFO, "gdb request failed: %s\n", buf);
+ return;
+ }
+
+ rewind(tmp_fp);
+ format_and_print_gdb_bt(tmp_fp);
+
+ fclose(tmp_fp);
+ return;
+ }
+
if (STREQ(*argv, "set") && argv[1]) {
/*
* Intercept set commands in case something has to be done
- * here or elsewhere.
- */
+ * here or elsewhere.
+ */
if (STREQ(argv[1], "gdb")) {
cmd_set();
return;
@@ -821,6 +853,100 @@ cmd_gdb(void)
}
}
+#define MAX_BT_LINES 1024
+#define MAX_THREAD_BLOCKS 64
+
+/*
+ * Helper function to parse 'thread apply all bt' output, reverse the
+ * thread blocks, and print the result.
+ */
+static void format_and_print_gdb_bt(FILE *input_fp)
+{
+ char *lines[MAX_BT_LINES];
+ int line_count = 0;
+ int thread_starts[MAX_THREAD_BLOCKS];
+ int thread_count = 0;
+ char line_buffer[BUFSIZE];
+ int i, j;
+ int global_frame_cnt = 0;
+
+ // Read all lines into memory
+ while (fgets(line_buffer, BUFSIZE, input_fp) && line_count < MAX_BT_LINES) {
+ if (strstr(line_buffer, "Thread ") == line_buffer) {
+ if (thread_count < MAX_THREAD_BLOCKS) {
+ thread_starts[thread_count++] = line_count;
+ }
+ }
+ lines[line_count] = strdup(line_buffer);
+ if (!lines[line_count]) {
+ error(FATAL, "strdup failed while reading gdb output\n");
+ }
+ line_count++;
+ }
+
+ if (thread_count == 0) { // If no threads, just print everything as is.
+ for (i = 0; i < line_count; i++) {
+ fputs(lines[i], fp);
+ }
+ } else {
+ // Iterate threads in reverse order to fix the display order
+ for (i = thread_count - 1; i >= 0; i--) {
+ int start_line = thread_starts[i];
+ int end_line = (i == thread_count - 1) ? line_count : thread_starts[i+1];
+
+ // Print thread frames, stripping header and renumbering
+ for (j = start_line; j < end_line; j++) {
+ char *line = lines[j];
+ // Skip "Thread " line
+ if (strncmp(line, "Thread ", 7) == 0) continue;
+ // Skip "Backtrace stopped" or similar noise if desired,
+ // but usually GDB prints "Backtrace stopped" at the very end.
+ // We'll keep it for info unless it's in the middle of our merge.
+ // Actually, duplicate frames or stops might appear.
+ // For now, simple renumbering.
+
+ char *ptr = line;
+ while (*ptr == ' ' || *ptr == '\t') ptr++;
+
+ if (*ptr == '#') {
+ // Frame line: #0 0x...
+ char *rest = ptr + 1;
+ while (isdigit(*rest)) rest++; // Skip old number
+
+ // Parse content to check for address
+ char *p = rest;
+ while (*p == ' ' || *p == '\t') p++;
+
+ int has_addr = (strncmp(p, "0x", 2) == 0);
+
+ // Print number
+ fprintf(fp, "#%-3d", global_frame_cnt++);
+
+ // Align if address is missing
+ if (!has_addr) {
+ // Align function name with frames that have addresses
+ // 64-bit: 0x... (18 chars) + " in " (4 chars) = 22 chars
+ // 32-bit: 0x... (10 chars) + " in " (4 chars) = 14 chars
+ int width = (machdep->bits == 64) ? 22 : 14;
+ for (int k = 0; k < width; k++) fputc(' ', fp);
+ }
+
+ fputs(rest, fp);
+ } else {
+ // Other lines (e.g. variable info, code)
+ fputs(line, fp);
+ }
+ }
+ }
+ }
+
+ // Cleanup
+ for (i = 0; i < line_count; i++) {
+ free(lines[i]);
+ }
+}
+
+
/*
* The gdb target_xfer_memory() has a hook installed to re-route
* all memory accesses back here; reads of 1 or 4 bytes come primarily
--
2.34.1
#/******本邮件及其附件含有小米公司的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件! This e-mail and its attachments contain confidential information from XIAOMI, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!******/#
2 weeks, 2 days
Re: [PATCH 1/2] RISCV64: fix wrong information of, PUD, PMD and PTE - SA48(4K page)
by Lianbo Jiang
Hi, Austin
Thank you for the patch.
For the time being, I have no the RISCV64 environment for testing, just
did the build, and the changes are good to me. So: Ack for the [PATCH
1/2] and [PATCH 2/2].
Lianbo
On 1/15/26 4:27 PM, devel-request(a)lists.crash-utility.osci.io wrote:
> Date: Tue, 13 Jan 2026 10:54:01 +0900
> From: Austin Kim<austindh.kim(a)gmail.com>
> Subject: [Crash-utility] [PATCH 1/2] RISCV64: fix wrong information of
> PUD, PMD and PTE - SA48(4K page)
> To:devel@lists.crash-utility.osci.io
> Cc:austindh.kim@gmail.com
> Message-ID: <aWWluWUXmh9JuGQx@adminpc-PowerEdge-R7525>
> Content-Type: text/plain; charset=us-ascii
>
> As for SA48(4K page) in RISC-V based vmcore, 'vtop address' command
> produces the misleading information, including PUD, PMD, PTE.
>
> This commit is based on the following previous commit:
>
> commit 536a0d78f1fa ("RISCV64: fix wrong information of PMD and PTE - SA39(4K page)")
>
> Signed-off-by: Austin Kim<austindh.kim(a)gmail.com>
> ---
> riscv64.c | 37 ++++++++++++++++++-------------------
> 1 file changed, 18 insertions(+), 19 deletions(-)
>
> diff --git a/riscv64.c b/riscv64.c
> index 6b89f0b..4400d5c 100644
> --- a/riscv64.c
> +++ b/riscv64.c
> @@ -1210,10 +1210,9 @@ static int
> riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
> {
> ulong *pgd_ptr, pgd_val;
> - ulong pud_val;
> - ulong pmd_val;
> - ulong pte_val, pte_pfn;
> - ulong pt_phys;
> + ulong pud_base, pud_addr, pud_val;
> + 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);
> @@ -1227,36 +1226,36 @@ riscv64_vtop_4level_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();
> + pud_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>
> /* PUD */
> - FILL_PUD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
> - pud_val = ULONG(machdep->pud + PAGEOFFSET(sizeof(pud_t) *
> - pud_index_l4_4k(vaddr)));
> + FILL_PUD(PAGEBASE(pud_base), PHYSADDR, PAGESIZE());
> + pud_addr = pud_base + sizeof(pud_t) * pud_index_l4_4k(vaddr);
> + pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_addr));
> if (verbose)
> - fprintf(fp, " PUD: %016lx => %016lx\n", pt_phys, pud_val);
> + fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
> if (!pud_val)
> goto no_page;
> pud_val &= PTE_PFN_PROT_MASK;
> - pt_phys = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
> + pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
>
> /* PMD */
> - FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
> - pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) *
> - pmd_index_l4_4k(vaddr)));
> + FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
> + pmd_addr = pmd_base + sizeof(pmd_t) + pmd_index_l4_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_l4_4k(vaddr)));
> + FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
> + pte_addr = pte_base + sizeof(pte_t) * pte_index_l4_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] Fix for "mod -S" causes symbols to be incorrect
by Lianbo Jiang
Currently, the "mod -S" command may cause that the "bt/sym" commands
incorrectly translate the kernel module virtual address to symbol names,
if a kernel module contains a per-cpu section, this was reported on
PPC64 kernel.
Without the patch:
crash> mod -S ../usr/lib/debug/lib/modules/5.14.0-xxx.ppc64le
...
crash> bt
PID: 35705 TASK: c0000000b0365680 CPU: 16 COMMAND: "lsof"
...
[NIP : __key.7+32443920]
[LR : __key.7+32446288]
#4 [c0000000394df9c0] __key.7 at c00800001ce82040 [overlay] (unreliable)
#5 [c0000000394dfa00] walk_component at c0000000005c914c
...
crash> sym c00800001ce82040
c00800001ce82040 (b) __key.7+32443920 [bnx2i] /usr/src/debug/kernel-5.14.0-xxx/linux-5.14.0-xxx.ppc64le/fs/overlayfs/super.c: 122
With the patch:
crash> mod -S ../usr/lib/debug/lib/modules/5.14.0-xxx.ppc64le
...
crash> bt
PID: 35705 TASK: c0000000b0365680 CPU: 16 COMMAND: "lsof"
...
[NIP : ovl_revalidate_real+40]
[LR : ovl_dentry_revalidate_common+136]
#4 [c0000000394df9c0] ovl_revalidate_real at c00800001ce82040 [overlay]
#5 [c0000000394dfa00] walk_component at c0000000005c914c
...
crash> sym c00800001ce82040
c00800001ce82040 (t) ovl_revalidate_real+40 [overlay] /usr/src/debug/kernel-5.14.0-xxx/linux-5.14.0-xxx.ppc64le/fs/overlayfs/super.c: 122
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
symbols.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/symbols.c b/symbols.c
index c446beb43a76..e6865cabef74 100644
--- a/symbols.c
+++ b/symbols.c
@@ -5679,7 +5679,7 @@ value_search_module_6_4(ulong value, ulong *offset)
splast = NULL;
for ( ; sp <= sp_end; sp++) {
- if (machine_type("ARM64") &&
+ if ((machine_type("ARM64") || machine_type("PPC64")) &&
IN_MODULE_PERCPU(sp->value, lm) &&
!IN_MODULE_PERCPU(value, lm))
continue;
@@ -5769,10 +5769,10 @@ retry:
*/
splast = NULL;
for ( ; sp <= sp_end; sp++) {
- if (machine_type("ARM64") &&
+ if ((machine_type("ARM64") || machine_type("PPC64")) &&
IN_MODULE_PERCPU(sp->value, lm) &&
- !IN_MODULE_PERCPU(value, lm))
- continue;
+ !IN_MODULE_PERCPU(value, lm))
+ continue;
if (value == sp->value) {
if (MODULE_END(sp) || MODULE_INIT_END(sp))
--
2.51.1
3 weeks
[PATCH] maple_tree: add support for maple_tree.c output to respect the global radix and per-command -x/d flags
by stalexan@redhat.com
The commands that generate maple tree output do not currently respect the
global radix setting, nor do they respect the -x output flag. This
patch aims to fix this inconsistency, so that the output commands
respect both the global radix setting as well as the per-command -x/d
flags.
Signed-off-by: Sterling Alexander <stalexan(a)redhat.com>
---
maple_tree.c | 93 ++++++++++++++++++++++++++++++++++------------------
1 file changed, 61 insertions(+), 32 deletions(-)
diff --git a/maple_tree.c b/maple_tree.c
index 8c804d0..3b11ddd 100644
--- a/maple_tree.c
+++ b/maple_tree.c
@@ -67,12 +67,15 @@ struct req_entry *fill_member_offsets(char *);
void dump_struct_members_fast(struct req_entry *, int, ulong);
void dump_struct_members_for_tree(struct tree_data *, int, ulong);
-static void mt_dump_range(ulong min, ulong max, uint depth)
+static void mt_dump_range(ulong min, ulong max, uint depth, int radix)
{
- if (min == max)
- fprintf(fp, "%.*s%lu: ", depth * 2, spaces, min);
- else
- fprintf(fp, "%.*s%lu-%lu: ", depth * 2, spaces, min, max);
+ if (min == max) {
+ fprintf(fp, (radix == 16) ? "%.*s%lx: " : "%.*s%lu: ",
+ depth * 2, spaces, min);
+ } else {
+ fprintf(fp, (radix == 16) ? "%.*s%lx-%lx: " : "%.*s%lu-%lu: ",
+ depth * 2, spaces, min, max);
+ }
}
static inline bool mt_is_reserved(ulong entry)
@@ -92,13 +95,28 @@ static uint mt_height(char *mt_buf)
>> MT_FLAGS_HEIGHT_OFFSET;
}
-static void dump_mt_range64(char *mr64_buf)
+/*
+ * Determine the output radix for maple tree display.
+ * Priority: 1) -x/-d flags, 2) global pc->output_radix
+ */
+static inline int mt_output_radix(struct tree_data *td)
+{
+ if (td) {
+ if (td->flags & TREE_STRUCT_RADIX_10)
+ return 10;
+ else if (td->flags & TREE_STRUCT_RADIX_16)
+ return 16;
+ }
+ return pc->output_radix;
+}
+
+static void dump_mt_range64(char *mr64_buf, int radix)
{
int i;
fprintf(fp, " contents: ");
for (i = 0; i < mt_slots[maple_range_64] - 1; i++)
- fprintf(fp, "%p %lu ",
+ fprintf(fp, (radix == 16) ? "%p %lx " : "%p %lu ",
VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot)
+ sizeof(void *) * i),
ULONG(mr64_buf + OFFSET(maple_range_64_pivot)
@@ -107,14 +125,15 @@ static void dump_mt_range64(char *mr64_buf)
+ sizeof(void *) * i));
}
-static void dump_mt_arange64(char *ma64_buf)
+static void dump_mt_arange64(char *ma64_buf, int radix)
{
int i;
fprintf(fp, " contents: ");
for (i = 0; i < mt_slots[maple_arange_64]; i++)
- fprintf(fp, "%lu ", ULONG(ma64_buf + OFFSET(maple_arange_64_gap)
- + sizeof(ulong) * i));
+ fprintf(fp, (radix == 16) ? "%lx " : "%lu ",
+ ULONG(ma64_buf + OFFSET(maple_arange_64_gap)
+ + sizeof(ulong) * i));
fprintf(fp, "| %02X %02X| ",
UCHAR(ma64_buf + OFFSET(maple_arange_64_meta) +
@@ -123,7 +142,7 @@ static void dump_mt_arange64(char *ma64_buf)
OFFSET(maple_metadata_gap)));
for (i = 0; i < mt_slots[maple_arange_64] - 1; i++)
- fprintf(fp, "%p %lu ",
+ fprintf(fp, (radix == 16) ? "%p %lx " : "%p %lu ",
VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) +
sizeof(void *) * i),
ULONG(ma64_buf + OFFSET(maple_arange_64_pivot) +
@@ -132,25 +151,27 @@ static void dump_mt_arange64(char *ma64_buf)
sizeof(void *) * i));
}
-static void dump_mt_entry(ulong entry, ulong min, ulong max, uint depth)
+static void dump_mt_entry(ulong entry, ulong min, ulong max, uint depth, int radix)
{
- mt_dump_range(min, max, depth);
+ mt_dump_range(min, max, depth, radix);
- if (xa_is_value(entry))
- fprintf(fp, "value %ld (0x%lx) [0x%lx]\n", xa_to_value(entry),
+ if (xa_is_value(entry)) {
+ fprintf(fp, (radix == 16) ? "value 0x%lx [0x%lx]\n" : "value %ld [0x%lx]\n",
xa_to_value(entry), entry);
- else if (xa_is_zero(entry))
- fprintf(fp, "zero (%ld)\n", xa_to_internal(entry));
- else if (mt_is_reserved(entry))
+ } else if (xa_is_zero(entry)) {
+ fprintf(fp, (radix == 16) ? "zero (0x%lx)\n" : "zero (%ld)\n",
+ xa_to_internal(entry));
+ } else if (mt_is_reserved(entry)) {
fprintf(fp, "UNKNOWN ENTRY (0x%lx)\n", entry);
- else
- fprintf(fp, "0x%lx\n", entry);
+ } else {
+ fprintf(fp, (radix == 16) ? "0x%lx\n" : "%lu\n", entry);
+ }
}
static void dump_mt_node(ulong maple_node, char *node_data, uint type,
- ulong min, ulong max, uint depth)
+ ulong min, ulong max, uint depth, int radix)
{
- mt_dump_range(min, max, depth);
+ mt_dump_range(min, max, depth, radix);
fprintf(fp, "node 0x%lx depth %d type %d parent %p",
maple_node, depth, type,
@@ -169,6 +190,7 @@ static void do_mt_range64(ulong entry, ulong min, ulong max,
int i;
int len = strlen(path);
struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL;
+ int radix = mt_output_radix(td);
char *mr64_buf;
if (SIZE(maple_node) > MAPLE_BUFSIZE)
@@ -180,7 +202,7 @@ static void do_mt_range64(ulong entry, ulong min, ulong max,
mr64_buf = node_buf + OFFSET(maple_node_mr64);
if (td && td->flags & TREE_STRUCT_VERBOSE) {
- dump_mt_range64(mr64_buf);
+ dump_mt_range64(mr64_buf, radix);
}
for (i = 0; i < mt_slots[maple_range_64]; i++) {
@@ -230,6 +252,7 @@ static void do_mt_arange64(ulong entry, ulong min, ulong max,
int i;
int len = strlen(path);
struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL;
+ int radix = mt_output_radix(td);
char *ma64_buf;
if (SIZE(maple_node) > MAPLE_BUFSIZE)
@@ -241,7 +264,7 @@ static void do_mt_arange64(ulong entry, ulong min, ulong max,
ma64_buf = node_buf + OFFSET(maple_node_ma64);
if (td && td->flags & TREE_STRUCT_VERBOSE) {
- dump_mt_arange64(ma64_buf);
+ dump_mt_arange64(ma64_buf, radix);
}
for (i = 0; i < mt_slots[maple_arange_64]; i++) {
@@ -286,6 +309,7 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth,
int print_radix = 0, i;
static struct req_entry **e = NULL;
struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL;
+ int output_radix = mt_output_radix(td);
if (ops->entry && entry)
ops->entry(entry, entry, path, max, ops->private);
@@ -306,12 +330,15 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth,
td->count++;
if (td->flags & TREE_STRUCT_VERBOSE) {
- dump_mt_entry(entry, min, max, depth);
- } else if (td->flags & VERBOSE && entry)
- fprintf(fp, "%lx\n", entry);
- if (td->flags & TREE_POSITION_DISPLAY && entry)
- fprintf(fp, " index: %ld position: %s/%u\n",
+ dump_mt_entry(entry, min, max, depth, output_radix);
+ } else if (td->flags & VERBOSE && entry) {
+ fprintf(fp, (output_radix == 16) ? "%lx\n" : "%lu\n", entry);
+ }
+ if (td->flags & TREE_POSITION_DISPLAY && entry) {
+ fprintf(fp, (output_radix == 16) ? " index: %lx position: %s/%u\n" :
+ " index: %ld position: %s/%u\n",
++(*global_index), path, index);
+ }
if (td->structname && entry) {
if (td->flags & TREE_STRUCT_RADIX_10)
@@ -319,7 +346,7 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth,
else if (td->flags & TREE_STRUCT_RADIX_16)
print_radix = 16;
else
- print_radix = 0;
+ print_radix = output_radix;
for (i = 0; i < td->structname_args; i++) {
switch (count_chars(td->structname[i], '.')) {
@@ -348,6 +375,7 @@ static void do_mt_node(ulong entry, ulong min, ulong max,
uint i;
char node_buf[MAPLE_BUFSIZE];
struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL;
+ int radix = mt_output_radix(td);
if (SIZE(maple_node) > MAPLE_BUFSIZE)
error(FATAL, "MAPLE_BUFSIZE should be larger than maple_node struct");
@@ -356,7 +384,7 @@ static void do_mt_node(ulong entry, ulong min, ulong max,
"mt_dump_node read maple_node", FAULT_ON_ERROR);
if (td && td->flags & TREE_STRUCT_VERBOSE) {
- dump_mt_node(maple_node, node_buf, type, min, max, depth);
+ dump_mt_node(maple_node, node_buf, type, min, max, depth, radix);
}
switch (type) {
@@ -457,7 +485,8 @@ static void do_maple_tree_dump(ulong node, ulong slot, const char *path,
ulong index, void *private)
{
struct do_maple_tree_info *info = private;
- fprintf(fp, "[%lu] %lx\n", index, slot);
+ fprintf(fp, (pc->output_radix == 16) ? "[%lx] %lx\n" : "[%lu] %lx\n",
+ index, slot);
info->count++;
}
--
2.52.0
3 weeks
[PATCH 2/2] RISCV64: fix wrong information of P4D, PUD, PMD and PTE - SA57(4K page)
by Austin Kim
As for SA57(4K page) in RISC-V based vmcore, 'vtop address' command
produces the misleading information, including P4D, PUD, PMD, PTE.
This commit is based on the following previous commit:
commit 536a0d78f1fa ("RISCV64: fix wrong information of PMD and PTE - SA39(4K page)")
Signed-off-by: Austin Kim <austindh.kim(a)gmail.com>
---
riscv64.c | 49 ++++++++++++++++++++++++-------------------------
1 file changed, 24 insertions(+), 25 deletions(-)
diff --git a/riscv64.c b/riscv64.c
index 4400d5c..eceae70 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -1287,11 +1287,10 @@ static int
riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
{
ulong *pgd_ptr, pgd_val;
- ulong p4d_val;
- ulong pud_val;
- ulong pmd_val;
- ulong pte_val, pte_pfn;
- ulong pt_phys;
+ ulong p4d_base, p4d_addr, p4d_val;
+ ulong pud_base, pud_addr, pud_val;
+ 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);
@@ -1305,47 +1304,47 @@ riscv64_vtop_5level_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();
+ p4d_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
/* P4D */
- FILL_P4D(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
- p4d_val = ULONG(machdep->machspec->p4d + PAGEOFFSET(sizeof(p4d_t) *
- p4d_index_l5_4k(vaddr)));
+ FILL_P4D(PAGEBASE(p4d_base), PHYSADDR, PAGESIZE());
+ p4d_addr = p4d_base + sizeof(p4d_t) * p4d_index_l5_4k(vaddr);
+ p4d_val = ULONG(machdep->machspec->p4d + PAGEOFFSET(p4d_addr));
if (verbose)
- fprintf(fp, " P4D: %016lx => %016lx\n", pt_phys, p4d_val);
+ fprintf(fp, " P4D: %016lx => %016lx\n", p4d_addr, p4d_val);
if (!p4d_val)
goto no_page;
p4d_val &= PTE_PFN_PROT_MASK;
- pt_phys = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
+ pud_base = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
/* PUD */
- FILL_PUD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
- pud_val = ULONG(machdep->pud + PAGEOFFSET(sizeof(pud_t) *
- pud_index_l5_4k(vaddr)));
+ FILL_PUD(PAGEBASE(pud_base), PHYSADDR, PAGESIZE());
+ pud_addr = pud_base + sizeof(pud_t) * pud_index_l5_4k(vaddr);
+ pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_addr));
if (verbose)
- fprintf(fp, " PUD: %016lx => %016lx\n", pt_phys, pud_val);
+ fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
if (!pud_val)
goto no_page;
pud_val &= PTE_PFN_PROT_MASK;
- pt_phys = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
+ pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
/* PMD */
- FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) *
- pmd_index_l4_4k(vaddr)));
+ FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
+ pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l5_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_l4_4k(vaddr)));
+ FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
+ pte_addr = pte_base + sizeof(pte_t) * pte_index_l5_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_base, pte_val);
if (!pte_val)
goto no_page;
pte_val &= PTE_PFN_PROT_MASK;
--
2.34.1
4 weeks, 1 day
[PATCH 1/2] RISCV64: fix wrong information of PUD, PMD and PTE - SA48(4K page)
by Austin Kim
As for SA48(4K page) in RISC-V based vmcore, 'vtop address' command
produces the misleading information, including PUD, PMD, PTE.
This commit is based on the following previous commit:
commit 536a0d78f1fa ("RISCV64: fix wrong information of PMD and PTE - SA39(4K page)")
Signed-off-by: Austin Kim <austindh.kim(a)gmail.com>
---
riscv64.c | 37 ++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 19 deletions(-)
diff --git a/riscv64.c b/riscv64.c
index 6b89f0b..4400d5c 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -1210,10 +1210,9 @@ static int
riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
{
ulong *pgd_ptr, pgd_val;
- ulong pud_val;
- ulong pmd_val;
- ulong pte_val, pte_pfn;
- ulong pt_phys;
+ ulong pud_base, pud_addr, pud_val;
+ 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);
@@ -1227,36 +1226,36 @@ riscv64_vtop_4level_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();
+ pud_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
/* PUD */
- FILL_PUD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
- pud_val = ULONG(machdep->pud + PAGEOFFSET(sizeof(pud_t) *
- pud_index_l4_4k(vaddr)));
+ FILL_PUD(PAGEBASE(pud_base), PHYSADDR, PAGESIZE());
+ pud_addr = pud_base + sizeof(pud_t) * pud_index_l4_4k(vaddr);
+ pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_addr));
if (verbose)
- fprintf(fp, " PUD: %016lx => %016lx\n", pt_phys, pud_val);
+ fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
if (!pud_val)
goto no_page;
pud_val &= PTE_PFN_PROT_MASK;
- pt_phys = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
+ pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
/* PMD */
- FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE());
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) *
- pmd_index_l4_4k(vaddr)));
+ FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
+ pmd_addr = pmd_base + sizeof(pmd_t) + pmd_index_l4_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_l4_4k(vaddr)));
+ FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
+ pte_addr = pte_base + sizeof(pte_t) * pte_index_l4_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
4 weeks, 1 day