[PATCH] crash_target: Support for GDB debugging of all tasks
by Alexey Makhalov
Support for GDB debugging of all tasks active and inactive.
Before this commit only active tasks were listed by "info threads"
with "CPU #" as a Target Id.
"info threads" will now show all tasks, similar to "ps", example:
crash> info threads
Id Target Id Frame
* 1 0 swapper/0 0xffffffffadba19d4 in default_idle () at arch/x86/kernel/process.c:731
2 0 swapper/1 0xffffffffadba19d4 in default_idle () at arch/x86/kernel/process.c:731
3 0 swapper/2 0xffffffffadba19d4 in default_idle () at arch/x86/kernel/process.c:731
4 0 swapper/3 0xffffffffadba19d4 in default_idle () at arch/x86/kernel/process.c:731
5 0 swapper/4 0xffffffffadb97292 in context_switch (rf=0xffffbaf0000f3e88, next=0xffff9ecb04908000, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
...
730 970325 taskset 0xffffffffadb97292 in context_switch (rf=0xffffbaf006a0fd18, next=0xffff9ecb0aec0000, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
731 975217 sleep 0xffffffffadb97292 in context_switch (rf=0xffffbaf005743c20, next=0xffff9ecac0692880, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
732 975228 sleep 0xffffffffadb97292 in context_switch (rf=0xffffbaf00696fb58, next=0xffff9ecac0690000, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
...
876 976084 docker 0xffffffffadb97292 in context_switch (rf=0xffffbaf0153dbd10, next=0xffff9ecac0645100, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
877 976085 systemd-userwor 0xffffffffadb97292 in context_switch (rf=0xffffbaf0153cbc58, next=0xffff9ecac0645100, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
878 976086 systemd-userwor 0xffffffffadb97292 in context_switch (rf=0xffffbaf0153e3c58, next=0xffffffffaec15a40 <init_task>, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
879 976087 systemd-userwor 0xffffffffadb97292 in context_switch (rf=0xffffbaf0153ebc58, next=0xffffffffaec15a40 <init_task>, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
Where "Target ID" contains "PID COMM" of the task
Example of "731 975217 sleep" debugging, real case, trying to
figure out why sleep was stuck in uninterruptable sleep.
Backtrace using crash:
crash> ps | grep 975217
975217 969797 3 ffff9ecb3956a880 UN 0.0 0 0 sleep
crash> bt 975217
PID: 975217 TASK: ffff9ecb3956a880 CPU: 3 COMMAND: "sleep"
#0 [ffffbaf005743ba0] __schedule at ffffffffadb97292
#1 [ffffbaf005743c60] schedule at ffffffffadb982b8
#2 [ffffbaf005743c80] rwbase_write_lock at ffffffffadb9aed7
#3 [ffffbaf005743cc0] down_write at ffffffffadb9b133
#4 [ffffbaf005743cd0] unlink_file_vma at ffffffffad2b0e2e
#5 [ffffbaf005743cf8] free_pgtables at ffffffffad2a47b0
#6 [ffffbaf005743d88] exit_mmap at ffffffffad2b3b8d
#7 [ffffbaf005743e80] mmput at ffffffffad08c81f
#8 [ffffbaf005743e98] do_exit at ffffffffad09636c
#9 [ffffbaf005743ef8] do_group_exit at ffffffffad096c78
RIP: 00007f111c70ddf9 RSP: 00007fff451817e8 RFLAGS: 00000246
RAX: ffffffffffffffda RBX: 00007f111c8089e0 RCX: 00007f111c70ddf9
RDX: 000000000000003c RSI: 00000000000000e7 RDI: 0000000000000000
RBP: 0000000000000000 R8: ffffffffffffff80 R9: 0000000000000000
R10: 00007fff451817b0 R11: 0000000000000246 R12: 00007f111c8089e0
R13: 00007f111c80e2e0 R14: 0000000000000002 R15: 00007f111c80e2c8
ORIG_RAX: 00000000000000e7 CS: 0033 SS: 002b
Backtrace using gdb (pay attention, task must be selected by thread Id):
crash> thread 731
[Switching to thread 731 ( 975217 sleep)]
5372 switch_to(prev, next, prev);
crash> gdb bt
#0 0xffffffffadb97292 in context_switch (rf=0xffffbaf005743c20, next=0xffff9ecac0692880, prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
#1 __schedule (sched_mode=sched_mode@entry=0) at kernel/sched/core.c:6696
#2 0xffffffffadb982b8 in schedule () at kernel/sched/core.c:6772
#3 0xffffffffadb9aed7 in rwbase_write_lock (rwb=rwb@entry=0xffff9ecaf1831430, state=state@entry=2) at kernel/locking/rwbase_rt.c:259
#4 0xffffffffadb9b133 in __down_write (sem=sem@entry=0xffff9ecaf1831430) at kernel/locking/rwsem.c:1474
#5 down_write (sem=sem@entry=0xffff9ecaf1831430) at kernel/locking/rwsem.c:1574
#6 0xffffffffad2b0e2e in i_mmap_lock_write (mapping=<optimized out>) at ./include/linux/fs.h:466
#7 unlink_file_vma (vma=vma@entry=0xffff9ecadd566090) at mm/mmap.c:127
#8 0xffffffffad2a47b0 in free_pgtables (tlb=tlb@entry=0xffffbaf005743dd0, mt=mt@entry=0xffff9ecb28e3b180, vma=0xffff9ecadd566090, vma@entry=0xffff9ecadd566000, floor=floor@entry=0, ceiling=ceiling@entry=0) at mm/memory.c:431
#9 0xffffffffad2b3b8d in exit_mmap (mm=mm@entry=0xffff9ecb28e3b180) at mm/mmap.c:3237
#10 0xffffffffad08c81f in __mmput (mm=0xffff9ecb28e3b180) at kernel/fork.c:1204
#11 mmput (mm=mm@entry=0xffff9ecb28e3b180) at kernel/fork.c:1226
#12 0xffffffffad09636c in exit_mm () at kernel/exit.c:563
#13 do_exit (code=code@entry=0) at kernel/exit.c:856
#14 0xffffffffad096c78 in do_group_exit (exit_code=0) at kernel/exit.c:1019
#15 0xffffffffad096cf8 in __do_sys_exit_group (error_code=<optimized out>) at kernel/exit.c:1030
#16 __se_sys_exit_group (error_code=<optimized out>) at kernel/exit.c:1028
#17 __x64_sys_exit_group (regs=<optimized out>) at kernel/exit.c:1028
#18 0xffffffffadb8a327 in do_syscall_x64 (nr=<optimized out>, regs=0xffffbaf005743f58) at arch/x86/entry/common.c:51
#19 do_syscall_64 (regs=0xffffbaf005743f58, nr=<optimized out>) at arch/x86/entry/common.c:81
#20 0xffffffffadc000dc in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:120
#21 0x00007f111c80e2c8 in ?? ()
#22 0x0000000000000002 in ?? ()
#23 0x00007f111c80e2e0 in ?? ()
#24 0x00007f111c8089e0 in ?? ()
#25 0x0000000000000000 in ?? ()
crash> f 3
259 rwbase_schedule();
crash> p *rwb
$1 = {
readers = {
counter = 1
},
rtmutex = {
wait_lock = {
raw_lock = {
{
val = {
counter = 0
},
{
locked = 0 '\000',
pending = 0 '\000'
},
{
locked_pending = 0,
tail = 0
}
}
}
},
waiters = {
rb_root = {
rb_node = 0xffffbaf006977be0
},
rb_leftmost = 0xffffbaf00696fbe0
},
owner = 0xffff9ecb3956a881
}
}
Additional changes:
1. Allow gdb "frame" command.
2. Blacklist useless gdb "gcore" command. Use gcore plugin instead.
3. Move crash_target_init() to later time as crash target requires a list of
tasks to be initialized.
Known issues and TBD items:
1. "info threads" may bail out first time throwing errors trying to access
userspace address during unwind process. Following "info threads"
invokations run without issues.
2. To unwind a stack of inactive task, only modern Linux versions, which use
inactive_task_frame, are supported and only x86_64 architecture.
3. gdb bt unwinder does not stop properly and may show invalid frames (21-25
on example above). Not a regression, existed before.
4. gdb bt unwinder does not work on active tasks in userspace. Not a regression,
existed before.
5. Only x86_64 architecture supported. machdep->get_task_reg() must be
implemented for others. Not a regression, existed before.
6. Active tasks registers fetching imlemented only for VMware dumps, see
x86_64_get_task_reg() for more details. Not a regression, existed before.
Signed-off-by: Alexey Makhalov <alexey.makhalov(a)broadcom.com>
---
crash_target.c | 39 ++++++++++++++++++++---------
defs.h | 10 ++++++--
gdb-10.2.patch | 7 ++----
gdb_interface.c | 63 ++++++++++++++++++++++++++++++----------------
help.c | 1 +
main.c | 1 +
task.c | 1 +
x86_64.c | 66 +++++++++++++++++++++++++++++++++++++++++++------
8 files changed, 140 insertions(+), 48 deletions(-)
diff --git a/crash_target.c b/crash_target.c
index 4554806..2fdf203 100644
--- a/crash_target.c
+++ b/crash_target.c
@@ -2,6 +2,8 @@
* crash_target.c
*
* Copyright (c) 2021 VMware, Inc.
+ * Copyright (c) 2024 Broadcom. All Rights Reserved. The term "Broadcom"
+ * refers to Broadcom Inc. and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,7 +15,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * Author: Alexey Makhalov <amakhalov(a)vmware.com>
+ * Author: Alexey Makhalov <alexey.makhalov(a)broadcom.com>
*/
#include <defs.h>
@@ -23,11 +25,11 @@
#include "regcache.h"
#include "gdbarch.h"
-void crash_target_init (void);
-
+extern "C" void crash_target_init (void);
extern "C" int gdb_readmem_callback(unsigned long, void *, int, int);
-extern "C" int crash_get_nr_cpus(void);
-extern "C" int crash_get_cpu_reg (int cpu, int regno, const char *regname,
+extern "C" int crash_get_nr_tasks(void);
+extern "C" void crash_get_task_info(int task_nr, unsigned long *pid, char **comm);
+extern "C" int crash_get_task_reg (int task_nr, int regno, const char *regname,
int regsize, void *val);
@@ -60,7 +62,13 @@ public:
bool has_registers () override { return true; }
bool thread_alive (ptid_t ptid) override { return true; }
std::string pid_to_str (ptid_t ptid) override
- { return string_printf ("CPU %ld", ptid.tid ()); }
+ {
+ unsigned long pid;
+ char *comm;
+
+ crash_get_task_info(ptid.tid(), &pid, &comm);
+ return string_printf ("%7ld %s", pid, comm);
+ }
};
@@ -68,18 +76,25 @@ public:
void
crash_target::fetch_registers (struct regcache *regcache, int regno)
{
+ int r;
gdb_byte regval[16];
- int cpu = inferior_ptid.tid();
+ int task_nr = inferior_ptid.tid();
struct gdbarch *arch = regcache->arch ();
- for (int r = 0; r < gdbarch_num_regs (arch); r++)
+ if (regno >= 0) {
+ r = regno;
+ goto onetime;
+ }
+
+ for (r = 0; regno == -1 && r < gdbarch_num_regs (arch); r++)
{
+onetime:
const char *regname = gdbarch_register_name(arch, r);
int regsize = register_size (arch, r);
if (regsize > sizeof (regval))
error (_("fatal error: buffer size is not enough to fit register value"));
- if (crash_get_cpu_reg (cpu, r, regname, regsize, (void *)®val))
+ if (crash_get_task_reg (task_nr, r, regname, regsize, (void *)®val))
regcache->raw_supply (r, regval);
else
regcache->raw_supply (r, NULL);
@@ -107,10 +122,10 @@ crash_target::xfer_partial (enum target_object object, const char *annex,
#define CRASH_INFERIOR_PID 1
-void
+extern "C" void
crash_target_init (void)
{
- int nr_cpus = crash_get_nr_cpus();
+ int nr_tasks = crash_get_nr_tasks();
crash_target *target = new crash_target ();
/* Own the target until it is successfully pushed. */
@@ -119,7 +134,7 @@ crash_target_init (void)
push_target (std::move (target_holder));
inferior_appeared (current_inferior (), CRASH_INFERIOR_PID);
- for (int i = 0; i < nr_cpus; i++)
+ for (int i = 0; i < nr_tasks; i++)
{
thread_info *thread = add_thread_silent (target,
ptid_t(CRASH_INFERIOR_PID, 0, i));
diff --git a/defs.h b/defs.h
index 98650e8..2b3f247 100644
--- a/defs.h
+++ b/defs.h
@@ -1080,7 +1080,7 @@ struct machdep_table {
void (*get_irq_affinity)(int);
void (*show_interrupts)(int, ulong *);
int (*is_page_ptr)(ulong, physaddr_t *);
- int (*get_cpu_reg)(int, int, const char *, int, void *);
+ int (*get_task_reg)(struct task_context *, int, const char *, int, void *);
int (*is_cpu_prstatus_valid)(int cpu);
};
@@ -2263,6 +2263,7 @@ struct size_table { /* stash of commonly-used sizes */
long pt_regs;
long task_struct;
long thread_info;
+ long inactive_task_frame;
long softirq_state;
long desc_struct;
long umode_t;
@@ -8001,9 +8002,14 @@ extern int have_full_symbols(void);
#define XEN_HYPERVISOR_ARCH
#endif
+/*
+ * crash_target.c
+ */
+extern void crash_target_init (void);
+
/*
* Register numbers must be in sync with gdb/features/i386/64bit-core.c
- * to make crash_target->fetch_registers() ---> machdep->get_cpu_reg()
+ * to make crash_target->fetch_registers() ---> machdep->get_task_reg()
* working properly.
*/
enum x86_64_regnum {
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
index a7018a2..ecf673d 100644
--- a/gdb-10.2.patch
+++ b/gdb-10.2.patch
@@ -221,7 +221,7 @@ exit 0
warning (_("\
--- gdb-10.2/gdb/main.c.orig
+++ gdb-10.2/gdb/main.c
-@@ -392,6 +392,14 @@ start_event_loop ()
+@@ -392,6 +392,13 @@ start_event_loop ()
return;
}
@@ -230,7 +230,6 @@ exit 0
+extern "C" void main_loop(void);
+extern "C" unsigned long crash_get_kaslr_offset(void);
+extern "C" int console(const char *, ...);
-+void crash_target_init (void);
+#endif
+
/* Call command_loop. */
@@ -316,7 +315,7 @@ exit 0
}
}
-@@ -1242,6 +1274,16 @@ captured_main (void *data)
+@@ -1242,6 +1274,14 @@ captured_main (void *data)
captured_main_1 (context);
@@ -324,8 +323,6 @@ exit 0
+ /* Relocate the vmlinux. */
+ objfile_rebase (symfile_objfile, crash_get_kaslr_offset());
+
-+ crash_target_init();
-+
+ /* Back to crash. */
+ main_loop();
+#endif
diff --git a/gdb_interface.c b/gdb_interface.c
index b14319c..03178f5 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -3,6 +3,8 @@
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
* Copyright (C) 2002-2015,2018-2019 David Anderson
* Copyright (C) 2002-2015,2018-2019 Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2024 Broadcom. All Rights Reserved. The term "Broadcom"
+ * refers to Broadcom Inc. and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -711,7 +713,7 @@ static char *prohibited_list[] = {
"watch", "rwatch", "awatch", "attach", "continue", "c", "fg", "detach",
"finish", "handle", "interrupt", "jump", "kill", "next", "nexti",
"signal", "step", "s", "stepi", "target", "until", "delete",
- "clear", "disable", "enable", "condition", "ignore", "frame", "catch",
+ "clear", "disable", "enable", "condition", "ignore", "gcore", "catch",
"tcatch", "return", "file", "exec-file", "core-file", "symbol-file",
"load", "si", "ni", "shell", "sy",
NULL /* must be last */
@@ -877,6 +879,7 @@ gdb_readmem_callback(ulong addr, void *buf, int len, int write)
switch (len)
{
case SIZEOF_8BIT:
+ fprintf(fp, "%s\n", pc->curcmd);
if (STREQ(pc->curcmd, "bt")) {
if (readmem(addr, memtype, buf, SIZEOF_8BIT,
"gdb_readmem_callback", readflags))
@@ -1063,34 +1066,52 @@ get_frame_offset(ulong pc)
unsigned long crash_get_kaslr_offset(void);
unsigned long crash_get_kaslr_offset(void)
{
- return kt->relocate * -1;
+ return kt->relocate * -1;
}
/* Callbacks for crash_target */
-int crash_get_nr_cpus(void);
-int crash_get_cpu_reg (int cpu, int regno, const char *regname,
+int crash_get_nr_tasks(void);
+void crash_get_task_info(int task_nr, unsigned long *pid, char **comm);
+int crash_get_task_reg (int task_nr, int regno, const char *regname,
int regsize, void *val);
-int crash_get_nr_cpus(void)
+int crash_get_nr_tasks(void)
{
- if (SADUMP_DUMPFILE())
- return sadump_get_nr_cpus();
- else if (DISKDUMP_DUMPFILE())
- return diskdump_get_nr_cpus();
- else if (KDUMP_DUMPFILE())
- return kdump_get_nr_cpus();
- else if (VMSS_DUMPFILE())
- return vmware_vmss_get_nr_cpus();
-
- /* Just CPU #0 */
- return 1;
+ return RUNNING_TASKS();
}
-int crash_get_cpu_reg (int cpu, int regno, const char *regname,
- int regsize, void *value)
+/* Get task information by its index number in TT */
+void crash_get_task_info(int task_nr, unsigned long *pid, char **comm)
{
- if (!machdep->get_cpu_reg)
- return FALSE;
- return machdep->get_cpu_reg(cpu, regno, regname, regsize, value);
+ int i;
+ struct task_context *tc;
+
+ tc = FIRST_CONTEXT();
+ for (i = 0; i < RUNNING_TASKS(); i++, tc++)
+ if (i == task_nr) {
+ *pid = tc->pid;
+ *comm = tc->comm;
+ return;
+ }
+ *pid = 0;
+ *comm = NULL;
+ return;
+}
+
+int crash_get_task_reg (int task_nr, int regno, const char *regname,
+ int regsize, void *value)
+{
+ int i;
+ struct task_context *tc;
+
+ if (!machdep->get_task_reg)
+ return FALSE;
+
+ tc = FIRST_CONTEXT();
+ for (i = 0; i < RUNNING_TASKS(); i++, tc++)
+ if (i == task_nr) {
+ return machdep->get_task_reg(tc, regno, regname, regsize, value);
+ }
+ return FALSE;
}
diff --git a/help.c b/help.c
index a9c4d30..85dbda5 100644
--- a/help.c
+++ b/help.c
@@ -8520,6 +8520,7 @@ char *version_info[] = {
"Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.",
"Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.",
"Copyright (C) 2015, 2021 VMware, Inc.",
+"Copyright (C) 2024 Broadcom, Inc.",
"This program is free software, covered by the GNU General Public License,",
"and you are welcome to change it and/or distribute copies of it under",
"certain conditions. Enter \"help copying\" to see the conditions.",
diff --git a/main.c b/main.c
index 0b6b927..13acd2d 100644
--- a/main.c
+++ b/main.c
@@ -794,6 +794,7 @@ main_loop(void)
} else
SIGACTION(SIGINT, restart, &pc->sigaction, NULL);
+ crash_target_init();
/*
* Display system statistics and current context.
*/
diff --git a/task.c b/task.c
index ebdb5be..5d26c52 100644
--- a/task.c
+++ b/task.c
@@ -298,6 +298,7 @@ task_init(void)
tt->flags |= THREAD_INFO;
}
+ STRUCT_SIZE_INIT(inactive_task_frame, "inactive_task_frame");
MEMBER_OFFSET_INIT(task_struct_state, "task_struct", "state");
MEMBER_SIZE_INIT(task_struct_state, "task_struct", "state");
if (INVALID_MEMBER(task_struct_state)) {
diff --git a/x86_64.c b/x86_64.c
index 502817d..b6e36a5 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -126,7 +126,7 @@ static int x86_64_get_framesize(struct bt_info *, ulong, ulong, char *);
static void x86_64_framesize_debug(struct bt_info *);
static void x86_64_get_active_set(void);
static int x86_64_get_kvaddr_ranges(struct vaddr_range *);
-static int x86_64_get_cpu_reg(int, int, const char *, int, void *);
+static int x86_64_get_task_reg(struct task_context *, int, const char *, int, void *);
static int x86_64_verify_paddr(uint64_t);
static void GART_init(void);
static void x86_64_exception_stacks_init(void);
@@ -195,7 +195,7 @@ x86_64_init(int when)
machdep->machspec->irq_eframe_link = UNINITIALIZED;
machdep->machspec->irq_stack_gap = UNINITIALIZED;
machdep->get_kvaddr_ranges = x86_64_get_kvaddr_ranges;
- machdep->get_cpu_reg = x86_64_get_cpu_reg;
+ machdep->get_task_reg = x86_64_get_task_reg;
if (machdep->cmdline_args[0])
parse_cmdline_args();
if ((string = pc->read_vmcoreinfo("relocate"))) {
@@ -891,7 +891,7 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, " is_page_ptr: x86_64_is_page_ptr()\n");
fprintf(fp, " verify_paddr: x86_64_verify_paddr()\n");
fprintf(fp, " get_kvaddr_ranges: x86_64_get_kvaddr_ranges()\n");
- fprintf(fp, " get_cpu_reg: x86_64_get_cpu_reg()\n");
+ fprintf(fp, " get_task_reg: x86_64_get_task_reg()\n");
fprintf(fp, " init_kernel_pgd: x86_64_init_kernel_pgd()\n");
fprintf(fp, "clear_machdep_cache: x86_64_clear_machdep_cache()\n");
fprintf(fp, " xendump_p2m_create: %s\n", PVOPS_XEN() ?
@@ -6398,6 +6398,9 @@ x86_64_ORC_init(void)
};
struct ORC_data *orc;
+ MEMBER_OFFSET_INIT(inactive_task_frame_bp, "inactive_task_frame", "bp");
+ MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr, "inactive_task_frame", "ret_addr");
+
if (machdep->flags & FRAMEPOINTER)
return;
@@ -6455,9 +6458,6 @@ x86_64_ORC_init(void)
orc->__stop_orc_unwind = symbol_value("__stop_orc_unwind");
orc->orc_lookup = symbol_value("orc_lookup");
- MEMBER_OFFSET_INIT(inactive_task_frame_bp, "inactive_task_frame", "bp");
- MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr, "inactive_task_frame", "ret_addr");
-
orc->has_signal = MEMBER_EXISTS("orc_entry", "signal"); /* added at 6.3 */
orc->has_end = MEMBER_EXISTS("orc_entry", "end"); /* removed at 6.4 */
@@ -9070,14 +9070,64 @@ x86_64_get_kvaddr_ranges(struct vaddr_range *vrp)
}
static int
-x86_64_get_cpu_reg(int cpu, int regno, const char *name,
+x86_64_get_task_reg(struct task_context *tc, int regno, const char *name,
int size, void *value)
{
if (regno >= LAST_REGNUM)
return FALSE;
+ /*
+ * For inactive task, grab rip, rbp, rbx, r12, r13, r14 and r15 from
+ * inactive_task_frame (see __switch_to_asm). Other regs saved on
+ * regular frame.
+ */
+ if (!is_task_active(tc->task)) {
+ int frame_size = STRUCT_SIZE("inactive_task_frame");
+
+ /* Only modern kernels supported. */
+ if (tt->flags & THREAD_INFO && frame_size == 7 * 8) {
+ ulong rsp;
+ int offset = 0;
+ switch (regno) {
+ case RSP_REGNUM:
+ readmem(tc->task + OFFSET(task_struct_thread) +
+ OFFSET(thread_struct_rsp), KVADDR,
+ &rsp, sizeof(void *),
+ "thread_struct rsp", FAULT_ON_ERROR);
+ rsp += frame_size;
+ memcpy(value, &rsp, size);
+ return TRUE;
+ case RIP_REGNUM:
+ offset += 8;
+ case RBP_REGNUM:
+ offset += 8;
+ case RBX_REGNUM:
+ offset += 8;
+ case R12_REGNUM:
+ offset += 8;
+ case R13_REGNUM:
+ offset += 8;
+ case R14_REGNUM:
+ offset += 8;
+ case R15_REGNUM:
+ readmem(tc->task + OFFSET(task_struct_thread) +
+ OFFSET(thread_struct_rsp), KVADDR,
+ &rsp, sizeof(void *),
+ "thread_struct rsp", FAULT_ON_ERROR);
+ readmem(rsp + offset, KVADDR, value, sizeof(void *),
+ "inactive_thread_frame saved regs", FAULT_ON_ERROR);
+ return TRUE;
+ }
+ }
+ /* TBD: older kernels support. */
+ return FALSE;
+ }
+
+ /*
+ * Task is active, grab CPU's registers
+ */
if (VMSS_DUMPFILE())
- return vmware_vmss_get_cpu_reg(cpu, regno, name, size, value);
+ return vmware_vmss_get_cpu_reg(tc->processor, regno, name, size, value);
return FALSE;
}
--
2.39.0
7 months
Re: [PATCH] gdb: fix the "p" command incorrectly print the value of a global variable
by lijiang
On Wed, Mar 6, 2024 at 6:30 PM Daisuke Hatayama (Fujitsu) <
d.hatayama(a)fujitsu.com> wrote:
> Lianbo,
>
> Thank you for your work.
>
> > Some objects format may potentially support copy relocations, but
> > currently the maybe_copied is always initialized to 0 in the symbol().
> > And the type is 'mst_file_bss', not always the 'mst_bss' or 'mst_data'
> > in the lookup_minimal_symbol_linkage(). For example:
> >
> > (gdb) p *msymbol
> > $42 = {<general_symbol_info> = {m_name = 0x349812f "test_no_static",
> value = {ivalue = 8, block = 0x8,
> > bytes = 0x8 <error: Cannot access memory at address 0x8>, address
> = 8, common_block = 0x8, chain = 0x8}, language_specific = {
> > obstack = 0x0, demangled_name = 0x0}, m_language = language_auto,
> ada_mangled = 0, section = 20}, size = 4,
> > filename = 0x6db3440 "test_sanity.c", type = mst_file_bss,
> created_by_gdb = 0, target_flag_1 = 0, target_flag_2 = 0, has_size = 1,
> > maybe_copied = 0, name_set = 1, hash_next = 0x0, demangled_hash_next =
> 0x0}
>
> The current description lacks explanation of when this issue
> occurs. Please write that the issue occurs when the corresponding
> kernel is built with CONFIG_CALL_DEPTH_TRACKING=y.
>
>
Thank you for the comment, Hatayama.
I should describe more background on this issue in the patch log. The
current issue can be easily reproduced with the following kernel commit:
commit 80e4c1cd42fff110bfdae8fce7ac4f22465f9664 (HEAD)
Author: Thomas Gleixner <tglx(a)linutronix.de>
Date: Thu Sep 15 13:11:19 2022 +0200
x86/retbleed: Add X86_FEATURE_CALL_DEPTH
Intel SKL CPUs fall back to other predictors when the RSB underflows.
The
only microcode mitigation is IBRS which is insanely expensive. It comes
with performance drops of up to 30% depending on the workload.
A way less expensive, but nevertheless horrible mitigation is to track
the
call depth in software and overeagerly fill the RSB when returns
underflow
the software counter.
Provide a configuration symbol and a CPU misfeature bit.
Signed-off-by: Thomas Gleixner <tglx(a)linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz(a)infradead.org>
Link: https://lore.kernel.org/r/20220915111147.056176424@infradead.org
After reverting the above commit, the current issue may disappear. And
originally I tried to find the clue how this kernel commit changes affected
the gdb, I have not found the clue for the time being. But later I noticed
that the gdb gets the correct offset address of a global variable
'test_no_static', which is an expected behavior from the gdb perspective
because of copy relocations, probably some object files potentially support
the copy relocations, just like this.
It would also be good to describe the fact that the issue occurs at
> least on RHEL9 kernel.
>
This is an upstream issue, I have reproduced it on the upstream kernel with
the above kernel commit changes.
>
> > This causes a problem that the 'p' command can not work well as
> > expected, and always gets an error:
> >
> > crash> mod -s test_sanity /home/test_sanity.ko
> > MODULE NAME BASE SIZE
> OBJECT FILE
> > ffffffffc1084040 test_sanity ffffffffc1082000 16384
> /home/test_sanity.ko
> > crash> p test_no_static
> > p: gdb request failed: p test_no_static
> > crash>
> >
> > With the patch:
> > crash> mod -s test_sanity /home/test_sanity.ko
> > MODULE NAME BASE SIZE
> OBJECT FILE
> > ffffffffc1084040 test_sanity ffffffffc1082000 16384
> /home/test_sanity.ko
> > crash> p test_no_static
> > test_no_static = $1 = 5
> > crash>
>
> It's correct that p command doesn't work as expected, but it doesn't
> always result in some error. This issue is failure of calculating
> relocated address of static symbols. If the calculated address happens
> to be the address where read can be successfull, it doesn't result in
> read error but outputs some bogus value.
>
It's true, but the bogus value is not an expected result because of an
incorrect address.
That is why the maybe_copied flag is initialized to 1, as I mentioned
above, some objfile may potentially support the copy relocations.
Thanks.
Lianbo
>
> To make this clear, I think it's better to set debug level 4 and to
> have p command output calculated virtual address as debug messages.
>
> For example:
>
> crash> sym -M | grep -E " test_no"
> ffffffffc0da7580 (B) test_no
> ffffffffc0da7584 (b) test_no_static
> crash> set debug 4
> debug: 4
> crash> p test_no
> p: per_cpu_symbol_search(test_no): NULL
> test_no = <readmem: ffffffffc0da7580, KVADDR, "gdb_readmem callback",
> 4, (ROE), 560d2d483400>
> <read_diskdump: addr: ffffffffc0da7580 paddr: 10b263580 cnt: 4>
> $3 = 5
> crash> p test_no_static
> p: per_cpu_symbol_search(test_no_static): NULL
> test_no_static = <readmem: ffffffffc0d9f004, KVADDR, "gdb_readmem
> callback", 4, (ROE), 560d2dc9b100>
> <read_diskdump: addr: ffffffffc0d9f004 paddr: 108bfc004 cnt: 4>
> $4 = -1869574000
>
>
>
7 months
[PATCH] gdb: fix the "p" command incorrectly print the value of a global variable
by Lianbo Jiang
Some objects format may potentially support copy relocations, but
currently the maybe_copied is always initialized to 0 in the symbol().
And the type is 'mst_file_bss', not always the 'mst_bss' or 'mst_data'
in the lookup_minimal_symbol_linkage(). For example:
(gdb) p *msymbol
$42 = {<general_symbol_info> = {m_name = 0x349812f "test_no_static", value = {ivalue = 8, block = 0x8,
bytes = 0x8 <error: Cannot access memory at address 0x8>, address = 8, common_block = 0x8, chain = 0x8}, language_specific = {
obstack = 0x0, demangled_name = 0x0}, m_language = language_auto, ada_mangled = 0, section = 20}, size = 4,
filename = 0x6db3440 "test_sanity.c", type = mst_file_bss, created_by_gdb = 0, target_flag_1 = 0, target_flag_2 = 0, has_size = 1,
maybe_copied = 0, name_set = 1, hash_next = 0x0, demangled_hash_next = 0x0}
This causes a problem that the 'p' command can not work well as
expected, and always gets an error:
crash> mod -s test_sanity /home/test_sanity.ko
MODULE NAME BASE SIZE OBJECT FILE
ffffffffc1084040 test_sanity ffffffffc1082000 16384 /home/test_sanity.ko
crash> p test_no_static
p: gdb request failed: p test_no_static
crash>
With the patch:
crash> mod -s test_sanity /home/test_sanity.ko
MODULE NAME BASE SIZE OBJECT FILE
ffffffffc1084040 test_sanity ffffffffc1082000 16384 /home/test_sanity.ko
crash> p test_no_static
test_no_static = $1 = 5
crash>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
Here is the test case:
#include <linux/kernel.h>
#include <linux/module.h>
int test_no = 0;
static int test_no_static = 0;
static int test_init(void)
{
test_no += 5;
test_no_static += 5;
printk(KERN_INFO "%d static=%d\n", test_no, test_no_static);
return 0;
}
static void test_exit(void)
{
test_no += 7;
test_no_static += 7;
printk(KERN_INFO "%d static=%d\n", test_no, test_no_static);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
gdb-10.2.patch | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
index a7018a249118..35388ba03e25 100644
--- a/gdb-10.2.patch
+++ b/gdb-10.2.patch
@@ -16057,3 +16057,27 @@ exit 0
m10200-dis.c
m10200-opc.c
m10300-dis.c
+--- gdb-10.2/gdb/minsyms.c.orig
++++ gdb-10.2/gdb/minsyms.c
+@@ -535,7 +535,9 @@ lookup_minimal_symbol_linkage (const char *name, struct objfile *objf)
+ {
+ if (strcmp (msymbol->linkage_name (), name) == 0
+ && (MSYMBOL_TYPE (msymbol) == mst_data
+- || MSYMBOL_TYPE (msymbol) == mst_bss))
++ || MSYMBOL_TYPE (msymbol) == mst_bss
++ || MSYMBOL_TYPE (msymbol) == mst_file_bss
++ || MSYMBOL_TYPE (msymbol) == mst_file_data))
+ return {msymbol, objfile};
+ }
+ }
+--- gdb-10.2/gdb/symtab.h.orig
++++ gdb-10.2/gdb/symtab.h
+@@ -1110,7 +1110,7 @@ struct symbol : public general_symbol_info, public allocate_on_obstack
+ is_objfile_owned (1),
+ is_argument (0),
+ is_inlined (0),
+- maybe_copied (0),
++ maybe_copied (1),/* The objfile potentially supports copy relocations. */
+ subclass (SYMBOL_NONE)
+ {
+ /* We can't use an initializer list for members of a base class, and
--
2.41.0
7 months, 1 week
[RFC PATCH 0/9] Add feature to validate page descriptor table in kdump-compressed format
by HATAYAMA Daisuke
I've made a RFC patch set to make sanity check of page descriptor
table in kdump compressed format strict.
This work has arose from the past issue that a produced crash dump
file was broken not only in data segment but also in headers including
page descriptor table. I've ever explained a bit this on crash-devel
in the following thread:
https://listman.redhat.com/archives/crash-utility/2023-September/010957.html
In this past issue, I couldn't find out its root cause after all
because when I began investigating the issue, problematic system where
the issue was reproduced was already unavailable.
This patch set is aimed at allowing us to figure out this kind of
issue more quickly and in more detail using crash utility. The code is
based on the tool I made to analyze the broken crash dump in the past
issue.
This is still incomplete, for example, the sanity check has not yet
supported split dump files in the kdump-compressed format and old
header version up to 5. It would be appreciated if I can get comments
for this RFC version.
HATAYAMA Daisuke (9):
diskdump: Add stat object in diskdump_data
diskdump: Add function sanity_check_page_desc() that sanity checks an
entry of page descriptor table
diskdump: Add function check_kdump_headers() that validates page
descriptor table
defs.h: Introduce flag VALIDATE_KDUMP_HEADERS
diskdump, main: Add --validate_kdump_headers command-line option
diskdump: Make sanity check in cache_page() strict
help: Add description of --validate_kdump_headers command-line option
man: Add description of --validate_kdump_headers command-line option
diskdump, debug: Print elapsed time consumed in validation of page
descriptor table
crash.8 | 4 +++
defs.h | 1 +
diskdump.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
help.c | 4 +++
main.c | 5 ++++
5 files changed, 87 insertions(+), 1 deletion(-)
--
2.43.1
7 months, 3 weeks
Re: [RFC PATCH 2/9] diskdump: Add function,sanity_check_page_desc() that sanity checks an entry of page, descriptor table
by Lianbo Jiang
On 2/15/24 18:04, devel-request(a)lists.crash-utility.osci.io wrote:
> Date: Thu, 15 Feb 2024 19:02:38 +0900
> From: HATAYAMA Daisuke<d.hatayama(a)fujitsu.com>
> Subject: [Crash-utility] [RFC PATCH 2/9] diskdump: Add function
> sanity_check_page_desc() that sanity checks an entry of page
> descriptor table
> To:devel@lists.crash-utility.osci.io
> Message-ID:<20240215100246.437-3-d.hatayama(a)fujitsu.com>
>
> Add function sanity_check_page_desc(). This sanity checks an given
> entry of page descriptor table based on the conditions that are
> expected to hold in each filed, i.e.:
>
> - offset must be smaller than a file size of dump file.
> - size must not be 0 and equal to or smaller than a block size.
> - If size is equal to a block size, it means the page is not
> compressed and so flags must be 0.
> - If size is smaller than a block size, it means the page is
> compressed and so flags must hold any of compression flags.
> - page_flags must constantly be 0 because this field is unused.
>
> This will be later used to validate a single entry of page descriptor
> table when it is read in cache_page() and to validate a whole part of
> page descriptor table when --validate_kdump_headers command-line
> option is specified.
> ---
> diskdump.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/diskdump.c b/diskdump.c
> index a495120..2d2cf97 100644
> --- a/diskdump.c
> +++ b/diskdump.c
> @@ -92,6 +92,7 @@ static void dump_note_offsets(FILE *);
> static char *vmcoreinfo_read_string(const char *);
> static void diskdump_get_osrelease(void);
> static int valid_note_address(unsigned char *);
> +static int sanity_check_page_desc(page_desc_t *);
>
> /* For split dumpfile */
> static struct diskdump_data **dd_list = NULL;
> @@ -3134,3 +3135,13 @@ out:
> FREEBUF(zram_buf);
> return len;
> }
> +
> +static int sanity_check_page_desc(page_desc_t *pd)
> +{
> + return pd->offset < dd->stat.st_size &&
I do not remember if there might be a hole in the kcore or dump core, if
yes, could the above checking break something in such cases? Not sure,
just impression.
Thanks
Lianbo
> + pd->size &&
> + pd->size <= dd->block_size &&
> + ((pd->size == dd->block_size && pd->flags == 0) ||
> + (pd->size < dd->block_size && pd->flags & (DUMP_DH_COMPRESSED_ZLIB|DUMP_DH_COMPRESSED_LZO|DUMP_DH_COMPRESSED_SNAPPY|DUMP_DH_COMPRESSED_ZSTD))) &&
> + pd->page_flags == 0;
> +}
> -- 2.43.1
8 months
Re: [RFC PATCH 0/9] Add feature to validate page, descriptor table in kdump-compressed format
by Lianbo Jiang
Hi, HATAYAMA
Thanks for your trying this.
On 2/15/24 18:04, devel-request(a)lists.crash-utility.osci.io wrote:
> Date: Thu, 15 Feb 2024 19:02:36 +0900
> From: HATAYAMA Daisuke<d.hatayama(a)fujitsu.com>
> Subject: [Crash-utility] [RFC PATCH 0/9] Add feature to validate page
> descriptor table in kdump-compressed format
> To:devel@lists.crash-utility.osci.io
> Message-ID:<20240215100246.437-1-d.hatayama(a)fujitsu.com>
>
> I've made a RFC patch set to make sanity check of page descriptor
> table in kdump compressed format strict.
>
> This work has arose from the past issue that a produced crash dump
> file was broken not only in data segment but also in headers including
> page descriptor table. I've ever explained a bit this on crash-devel
> in the following thread:
>
> https://listman.redhat.com/archives/crash-utility/2023-September/010957.html
For the patchset, the patch [2] and [6] should be able to fix the
current issue?
After the crash tool knows which pages are incomplete or invalid, how to
handle these pages in the next steps? Or crash-utility can not do
anything except for printing those bad pages. Could you please explain
it a little more? That can help me understand the other
patches[1/3/4/5/7/8].
Thanks
Lianbo
> In this past issue, I couldn't find out its root cause after all
> because when I began investigating the issue, problematic system where
> the issue was reproduced was already unavailable.
>
> This patch set is aimed at allowing us to figure out this kind of
> issue more quickly and in more detail using crash utility. The code is
> based on the tool I made to analyze the broken crash dump in the past
> issue.
>
> This is still incomplete, for example, the sanity check has not yet
> supported split dump files in the kdump-compressed format and old
> header version up to 5. It would be appreciated if I can get comments
> for this RFC version.
>
> HATAYAMA Daisuke (9):
> diskdump: Add stat object in diskdump_data
> diskdump: Add function sanity_check_page_desc() that sanity checks an
> entry of page descriptor table
> diskdump: Add function check_kdump_headers() that validates page
> descriptor table
> defs.h: Introduce flag VALIDATE_KDUMP_HEADERS
> diskdump, main: Add --validate_kdump_headers command-line option
> diskdump: Make sanity check in cache_page() strict
> help: Add description of --validate_kdump_headers command-line option
> man: Add description of --validate_kdump_headers command-line option
> diskdump, debug: Print elapsed time consumed in validation of page
> descriptor table
>
> crash.8 | 4 +++
> defs.h | 1 +
> diskdump.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> help.c | 4 +++
> main.c | 5 ++++
> 5 files changed, 87 insertions(+), 1 deletion(-)
>
> -- 2.43.1
8 months
Re: [PATCH v3 ] Adding the zram decompression algorithm "lzo-rle" to support kernel versions >= 5.1
by HAGIO KAZUHITO(萩尾 一仁)
On 2024/03/12 17:25, Yulong TANG 汤玉龙 wrote:
> In Linux 5.1, the ZRAM block driver has changed its default compressor
> from "lzo" to "lzo-rle" to enhance LZO compression support. However,
> crash does not support the improved LZO algorithm, resulting in failure
> when reading memory.
>
> change default compressor : ce82f19fd5809f0cf87ea9f753c5cc65ca0673d6
>
> The issue was discovered when using the extension 'gcore' to generate a
> process coredump, which was found to be incomplete and unable to be
> opened properly with gdb.
> This patch is for Crash-utility tool, it enables the Crash-utility to
> support decompression of the "lzo-rle" compression algorithm used in
> zram. The patch has been tested with vmcore files from kernel version
> 5.4, and successfully allows reading of memory compressed with the zram
> compression algorithm.
>
> Testing:
> ========
>
> before apply this patch :
> crash> gcore -v 0 1
> gcore: WARNING: only the lzo compressor is supported
> gcore: WARNING: only the lzo compressor is supported
> gcore: WARNING: only the lzo compressor is supported
> after:
> crash> gcore -v 0
> 1 Saved core.1.init
>
> Changelog:
> ==========
> v2: keep the "if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)"
> related code of the copied kernel code, but change the "if defined"
> macro into a runtime check .
> v3: set a default value of HAVE_EFFICIENT_UNALIGNED_ACCESS depending on
> architecture, for no ikconfig kernels.
Thanks for the update.
> + } else if (STREQ(name, "lzo-rle")) {
> +#ifdef LZO
why are this ifdef and lzo_init() etc. needed? I think we do not use
the lzo library for lzo-rle. maybe I'm missing something..
> + bool efficient_unaligned_access;
There is no need to check this every call, how about making this static?
for example:
static int efficient_unaligned_access = -1;
if (efficient_unaligned_access == -1) {
#if defined(ARM) || defined(ARM64) || defined(X86) || defined(X86_64) ||
defined(PPC) || defined(PPC64) || defined(S390)|| defined(S390X)
efficient_unaligned_access = TRUE;
#else
efficient_unaligned_access = FALSE;
#endif
if ((kt->ikconfig_flags & IKCONFIG_AVAIL) &&
(get_kernel_config("CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS", NULL)
== IKCONFIG_Y)
efficient_unaligned_access = TRUE;
}
Thanks,
Kazu
>
> Patch:
> ==========
>
> See attachment.
>
>
>
> Thanks and regards,
> Yulong
>
>
> --
> Crash-utility mailing list -- devel(a)lists.crash-utility.osci.io
> To unsubscribe send an email to devel-leave(a)lists.crash-utility.osci.io
> https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
> Contribution Guidelines: https://github.com/crash-utility/crash/wiki
8 months
[PATCH v4 ] Adding the zram decompression algorithm "lzo-rle" to support kernel versions >= 5.1
by Yulong TANG 汤玉龙
In Linux 5.1, the ZRAM block driver has changed its default compressor from "lzo" to "lzo-rle" to enhance LZO compression support. However, crash does not support the improved LZO algorithm, resulting in failure when reading memory.
change default compressor : ce82f19fd5809f0cf87ea9f753c5cc65ca0673d6
The issue was discovered when using the extension 'gcore' to generate a process coredump, which was found to be incomplete and unable to be opened properly with gdb.
This patch is for Crash-utility tool, it enables the Crash-utility to support decompression of the "lzo-rle" compression algorithm used in zram. The patch has been tested with vmcore files from kernel version 5.4, and successfully allows reading of memory compressed with the zram compression algorithm.
Testing:
========
before apply this patch :
crash> gcore -v 0 1
gcore: WARNING: only the lzo compressor is supported
gcore: WARNING: only the lzo compressor is supported
gcore: WARNING: only the lzo compressor is supported
after:
crash> gcore -v 0
1 Saved core.1.init
Changelog:
==========
v2: keep the "if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)" related code of the copied kernel code, but change the "if defined" macro into a runtime check .
v3: set a default value of HAVE_EFFICIENT_UNALIGNED_ACCESS depending on architecture, for no ikconfig kernels.
v4: avoid checking CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS every call;move "include lzorle_decompress.h" to diskdump.c from def.h
Patch:
==========
See attachment.
Thanks and regards,
Yulong
8 months
[PATCH] Fix arm64 vabits_actual value from arm64_get_vmcoreinfo
by Guanyou Chen
Hi Kazu, Lianbo
vmcoreinfo "tcr_el1_t1sz" should be a decimal number.
Before:
vmcoreinfo : vabits_actual: 27
After:
vmcoreinfo : vabits_actual: 39
Fixes: 28f0833037b2 ("Fix arm64: rewrite the arm64_get_vmcoreinfo_ul to
arm64_get_vmcoreinfo")
Signed-off-by: chenguanyou <chenguanyou(a)xiaomi.com>
---
arm64.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arm64.c b/arm64.c
index af0e0d7..e36c723 100644
--- a/arm64.c
+++ b/arm64.c
@@ -4656,8 +4656,8 @@ arm64_set_va_bits_by_tcr(void)
{
ulong value;
- if (arm64_get_vmcoreinfo(&value, "NUMBER(TCR_EL1_T1SZ)", NUM_HEX) ||
- arm64_get_vmcoreinfo(&value, "NUMBER(tcr_el1_t1sz)", NUM_HEX)) {
+ if (arm64_get_vmcoreinfo(&value, "NUMBER(TCR_EL1_T1SZ)", NUM_DEC) ||
+ arm64_get_vmcoreinfo(&value, "NUMBER(tcr_el1_t1sz)", NUM_DEC)) {
/* See ARMv8 ARM for the description of
* TCR_EL1.T1SZ and how it can be used
* to calculate the vabits_actual
--
2.39.0
Thanks,
Guanyou
8 months
[PATCH] Fix for "bt" command incorrectly printing "bogus exception frame" warning
by Lianbo Jiang
The "bogus exception frame" warning was observed again on a specific
vmcore, and the remaining frame was truncated on X86_64 machine, when
executing the "bt" command as below:
crash> bt 0 -c 8
PID: 0 TASK: ffff9948c08f5640 CPU: 8 COMMAND: "swapper/8"
#0 [fffffe1788788e58] crash_nmi_callback at ffffffff972672bb
#1 [fffffe1788788e68] nmi_handle at ffffffff9722eb8e
#2 [fffffe1788788eb0] default_do_nmi at ffffffff97e51cd0
#3 [fffffe1788788ed0] exc_nmi at ffffffff97e51ee1
#4 [fffffe1788788ef0] end_repeat_nmi at ffffffff980015f9
[exception RIP: __update_load_avg_se+13]
RIP: ffffffff9736b16d RSP: ffffbec3c08acc78 RFLAGS: 00000046
RAX: 0000000000000000 RBX: ffff994c2f2b1a40 RCX: ffffbec3c08acdc0
RDX: ffff9948e4fe1d80 RSI: ffff994c2f2b1a40 RDI: 0000001d7ad7d55d
RBP: ffffbec3c08acc88 R8: 0000001d921fca6f R9: ffff994c2f2b1328
R10: 00000000fffd0010 R11: ffffffff98e060c0 R12: 0000001d7ad7d55d
R13: 0000000000000005 R14: ffff994c2f2b19c0 R15: 0000000000000001
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
--- <NMI exception stack> ---
#5 [ffffbec3c08acc78] __update_load_avg_se at ffffffff9736b16d
#6 [ffffbec3c08acce0] enqueue_entity at ffffffff9735c9ab
#7 [ffffbec3c08acd28] enqueue_task_fair at ffffffff9735cef8
#8 [ffffbec3c08acd60] enqueue_task at ffffffff973481fa
#9 [ffffbec3c08acd88] ttwu_do_activate at ffffffff9734aeed
#10 [ffffbec3c08acdb0] try_to_wake_up at ffffffff9734c7d7
#11 [ffffbec3c08ace08] __queue_work at ffffffff9732a4d2
#12 [ffffbec3c08ace50] queue_work_on at ffffffff9732a6a4
#13 [ffffbec3c08ace60] iomap_dio_bio_end_io at ffffffff976a7b4c
#14 [ffffbec3c08ace90] clone_endio at ffffffffc090315f [dm_mod]
#15 [ffffbec3c08aced0] blk_update_request at ffffffff9779b49d
#16 [ffffbec3c08acf28] scsi_end_request at ffffffff97a3d5a7
#17 [ffffbec3c08acf58] scsi_io_completion at ffffffff97a3e606
#18 [ffffbec3c08acf90] blk_complete_reqs at ffffffff977978d0
#19 [ffffbec3c08acfa0] __do_softirq at ffffffff97e66f7a
#20 [ffffbec3c08acff0] do_softirq at ffffffff9730f6ef
--- <IRQ stack> ---
#21 [ffffbec3c022ff18] do_idle at ffffffff97368288
[exception RIP: unknown or invalid address]
RIP: 0000000000000000 RSP: 0000000000000000 RFLAGS: 00000000
RAX: 0000000000000000 RBX: 000000089726a2d0 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffffffff9726a3dd R8: 0000000000000000 R9: 0000000000000000
R10: ffffffff9720015a R11: e48885e126bc1600 R12: 0000000000000000
R13: ffffffff973684a9 R14: 0000000000000094 R15: 0000000040000000
ORIG_RAX: 0000000000000000 CS: 0000 SS: 0000
bt: WARNING: possibly bogus exception frame
crash>
Actually there is no exception frame, when called from do_softirq().
With the patch:
crash> bt 0 -c 8
PID: 0 TASK: ffff9948c08f5640 CPU: 8 COMMAND: "swapper/8"
#0 [fffffe1788788e58] crash_nmi_callback at ffffffff972672bb
#1 [fffffe1788788e68] nmi_handle at ffffffff9722eb8e
#2 [fffffe1788788eb0] default_do_nmi at ffffffff97e51cd0
#3 [fffffe1788788ed0] exc_nmi at ffffffff97e51ee1
#4 [fffffe1788788ef0] end_repeat_nmi at ffffffff980015f9
[exception RIP: __update_load_avg_se+13]
RIP: ffffffff9736b16d RSP: ffffbec3c08acc78 RFLAGS: 00000046
RAX: 0000000000000000 RBX: ffff994c2f2b1a40 RCX: ffffbec3c08acdc0
RDX: ffff9948e4fe1d80 RSI: ffff994c2f2b1a40 RDI: 0000001d7ad7d55d
RBP: ffffbec3c08acc88 R8: 0000001d921fca6f R9: ffff994c2f2b1328
R10: 00000000fffd0010 R11: ffffffff98e060c0 R12: 0000001d7ad7d55d
R13: 0000000000000005 R14: ffff994c2f2b19c0 R15: 0000000000000001
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
--- <NMI exception stack> ---
#5 [ffffbec3c08acc78] __update_load_avg_se at ffffffff9736b16d
#6 [ffffbec3c08acce0] enqueue_entity at ffffffff9735c9ab
#7 [ffffbec3c08acd28] enqueue_task_fair at ffffffff9735cef8
#8 [ffffbec3c08acd60] enqueue_task at ffffffff973481fa
#9 [ffffbec3c08acd88] ttwu_do_activate at ffffffff9734aeed
#10 [ffffbec3c08acdb0] try_to_wake_up at ffffffff9734c7d7
#11 [ffffbec3c08ace08] __queue_work at ffffffff9732a4d2
#12 [ffffbec3c08ace50] queue_work_on at ffffffff9732a6a4
#13 [ffffbec3c08ace60] iomap_dio_bio_end_io at ffffffff976a7b4c
#14 [ffffbec3c08ace90] clone_endio at ffffffffc090315f [dm_mod]
#15 [ffffbec3c08aced0] blk_update_request at ffffffff9779b49d
#16 [ffffbec3c08acf28] scsi_end_request at ffffffff97a3d5a7
#17 [ffffbec3c08acf58] scsi_io_completion at ffffffff97a3e606
#18 [ffffbec3c08acf90] blk_complete_reqs at ffffffff977978d0
#19 [ffffbec3c08acfa0] __do_softirq at ffffffff97e66f7a
#20 [ffffbec3c08acff0] do_softirq at ffffffff9730f6ef
--- <IRQ stack> ---
#21 [ffffbec3c022ff28] cpu_startup_entry at ffffffff973684a9
#22 [ffffbec3c022ff38] start_secondary at ffffffff9726a3dd
#23 [ffffbec3c022ff50] secondary_startup_64_no_verify at ffffffff9720015a
crash>
Reported-by: Jie Li <jieli(a)redhat.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
x86_64.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/x86_64.c b/x86_64.c
index 502817d3b2bd..c672a0c3e8fc 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -3841,11 +3841,12 @@ in_exception_stack:
up -= 1;
bt->instptr = *up;
/*
- * No exception frame when coming from do_softirq_own_stack
- * or call_softirq.
+ * No exception frame when coming from do_softirq_own_stack,
+ * call_softirq or do_softirq.
*/
if ((sp = value_search(bt->instptr, &offset)) &&
- (STREQ(sp->name, "do_softirq_own_stack") || STREQ(sp->name, "call_softirq")))
+ (STREQ(sp->name, "do_softirq_own_stack") || STREQ(sp->name, "call_softirq")
+ || STREQ(sp->name, "do_softirq")))
irq_eframe = 0;
bt->frameptr = 0;
done = FALSE;
--
2.41.0
8 months