Merge branch 'c9' into a9

This commit is contained in:
eabdullin 2022-11-15 10:27:31 +00:00 committed by Stepan Oksanichenko
commit 4cf0624999
38 changed files with 1691 additions and 1498 deletions

View File

@ -1,2 +1,2 @@
692a903aa3cae47cf2c5dbb7fe79ae6e774e3641 SOURCES/crash-8.0.0.tar.gz
c5511a10f2be0d44a74d7d832663a5567befad3f SOURCES/crash-8.0.1.tar.gz
6bf5ee7877a4740835745ed97ce525a00bb2232c SOURCES/gdb-10.2.tar.gz

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/crash-8.0.0.tar.gz
SOURCES/crash-8.0.1.tar.gz
SOURCES/gdb-10.2.tar.gz

View File

@ -1,59 +0,0 @@
From 70a27ae9f2b45d6dba56ee4240b6adf79c544ee1 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Thu, 6 Jan 2022 22:34:26 +0800
Subject: [PATCH 01/10] Fix for "timer -r" option to display all the per-CPU
clocks
Currently, the hrtimer_max_clock_bases is hard-coded to 3, which
makes that crash only prints three clocks, and the rest of clocks
are not displayed.
Without the patch:
crash> timer -r -C 11
CPU: 11 HRTIMER_CPU_BASE: ffff9a775f95ee00
CLOCK: 0 HRTIMER_CLOCK_BASE: ffff9a775f95ee80 [ktime_get]
(empty)
CLOCK: 1 HRTIMER_CLOCK_BASE: ffff9a775f95ef00 [ktime_get_real]
(empty)
CLOCK: 2 HRTIMER_CLOCK_BASE: ffff9a775f95ef80 [ktime_get_boottime]
(empty)
With the patch:
crash> timer -r -C 11
CPU: 11 HRTIMER_CPU_BASE: ffff9a775f95ee00
CLOCK: 0 HRTIMER_CLOCK_BASE: ffff9a775f95ee80 [ktime_get]
(empty)
CLOCK: 1 HRTIMER_CLOCK_BASE: ffff9a775f95ef00 [ktime_get_real]
(empty)
CLOCK: 2 HRTIMER_CLOCK_BASE: ffff9a775f95ef80 [ktime_get_boottime]
(empty)
...
CLOCK: 7 HRTIMER_CLOCK_BASE: ffff9a775f95f200 [ktime_get_clocktai]
(empty)
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
kernel.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel.c b/kernel.c
index 37b7af74ed2e..36c57ed501ad 100644
--- a/kernel.c
+++ b/kernel.c
@@ -7675,7 +7675,8 @@ dump_hrtimer_data(const ulong *cpus)
if (VALID_STRUCT(hrtimer_clock_base)) {
hrtimer_max_clock_bases = 2;
if (symbol_exists("ktime_get_boottime"))
- hrtimer_max_clock_bases = 3;
+ hrtimer_max_clock_bases = MEMBER_SIZE("hrtimer_cpu_base", "clock_base") /
+ SIZE(hrtimer_clock_base);
} else if (VALID_STRUCT(hrtimer_base)) {
max_hrtimer_bases = 2;
} else
--
2.20.1

View File

@ -1,69 +0,0 @@
From 7eba220e1a7d443cad6716dd83d4953ffd62d566 Mon Sep 17 00:00:00 2001
From: Qi Zheng <zhengqi.arch@bytedance.com>
Date: Tue, 21 Dec 2021 15:40:31 +0800
Subject: [PATCH 1/2] Fix pvops Xen detection for arm machine
Since the xen_start_info on the arm/arm64 platform points to a static
variable '_xen_start_info'(see its definition as below), which makes
that the address of xen_start_info will never be null.
arch/arm/xen/enlighten.c:40:static struct start_info _xen_start_info;
arch/arm/xen/enlighten.c:41:struct start_info *xen_start_info = &_xen_start_info;
arch/arm/xen/enlighten.c:42:EXPORT_SYMBOL(xen_start_info);
As a result, the is_pvops_xen() in commit 4badc6229c69 ("Fix pvops
Xen detection for kernels >= v4.20") always returns TRUE because it
can always read out the non-null address of xen_start_info, finally
the following error will be reported on arm/arm64 platform(non-Xen
environment) because p2m_mid_missing and xen_p2m_addr are not defined:
crash: cannot resolve "p2m_top"
For the arm/arm64 platform, fix it by using xen_vcpu_info instead of
xen_start_info to detect Xen dumps.
In addition, also explicitly narrow the scope of the xen_start_info
check to x86 with the machine_type(), there is no need to check it on
other architectures.
Fixes: 4badc6229c69 ("Fix pvops Xen detection for kernels >= v4.20")
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Acked-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
kernel.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/kernel.c b/kernel.c
index f4598ea217a3..37b7af74ed2e 100644
--- a/kernel.c
+++ b/kernel.c
@@ -10757,11 +10757,21 @@ is_pvops_xen(void)
STREQ(sym, "paravirt_patch_default")))
return TRUE;
- if (symbol_exists("xen_start_info") &&
- readmem(symbol_value("xen_start_info"), KVADDR, &addr,
- sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
- addr != 0)
- return TRUE;
+ if (machine_type("X86") || machine_type("X86_64")) {
+ if (symbol_exists("xen_start_info") &&
+ readmem(symbol_value("xen_start_info"), KVADDR, &addr,
+ sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
+ addr != 0)
+ return TRUE;
+ }
+
+ if (machine_type("ARM") || machine_type("ARM64")) {
+ if (symbol_exists("xen_vcpu_info") &&
+ readmem(symbol_value("xen_vcpu_info"), KVADDR, &addr,
+ sizeof(void *), "xen_vcpu_info", RETURN_ON_ERROR) &&
+ addr != 0)
+ return TRUE;
+ }
return FALSE;
}
--
2.20.1

View File

@ -1,379 +0,0 @@
From 995db8ab88916b6397676b67be98c0a4f82cca49 Mon Sep 17 00:00:00 2001
From: Hong YANG <hong.yang3@nio.com>
Date: Mon, 15 Nov 2021 15:41:01 +0800
Subject: [PATCH 1/3] arm64: Support overflow stack panic
Kernel commit <872d8327ce89> ("arm64: add VMAP_STACK overflow detection")
has supported the overflow stack exception handling. Without the patch, the
"bt" command will make crash generate a core dump because of segmentation
fault. With the patch, the "bt" command can display the overflow stack.
Before:
crash> bt
PID: 3607 TASK: ffffffcbf9a4da00 CPU: 2 COMMAND: "sh"
Segmentation fault (core dumped)
After:
crash> bt
PID: 3607 TASK: ffffffcbf9a4da00 CPU: 2 COMMAND: "sh"
#0 [ffffffccbfd85f50] __delay at ffffff8008ceded8
...
#5 [ffffffccbfd85fd0] emergency_restart at ffffff80080d49fc
#6 [ffffffccbfd86140] panic at ffffff80080af4c0
#7 [ffffffccbfd86150] nmi_panic at ffffff80080af150
#8 [ffffffccbfd86190] handle_bad_stack at ffffff800808b0b8
#9 [ffffffccbfd862d0] __bad_stack at ffffff800808285c
PC: ffffff8008082e80 [el1_sync]
LR: ffffff8000d6c214 [stack_overflow_demo+84]
SP: ffffff1a79930070 PSTATE: 204003c5
X29: ffffff8011b03d00 X28: ffffffcbf9a4da00 X27: ffffff8008e02000
X26: 0000000000000040 X25: 0000000000000124 X24: ffffffcbf9a4da00
X23: 0000007daec2e288 X22: ffffffcbfe03b800 X21: 0000007daec2e288
X20: 0000000000000002 X19: 0000000000000002 X18: 0000000000000002
X17: 00000000000003e7 X16: 0000000000000000 X15: 0000000000000000
X14: ffffffcc17facb00 X13: ffffffccb4c25c00 X12: 0000000000000000
X11: ffffffcc17fad660 X10: 0000000000000af0 X9: 0000000000000000
X8: ffffff1a799334f0 X7: 0000000000000000 X6: 000000000000003f
X5: 0000000000000040 X4: 0000000000000010 X3: 00000065981d07f0
X2: 00000065981d07f0 X1: 0000000000000000 X0: ffffff1a799334f0
Signed-off-by: Hong YANG <hong.yang3@nio.com>
---
arm64.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++------
defs.h | 6 ++
2 files changed, 159 insertions(+), 16 deletions(-)
diff --git a/arm64.c b/arm64.c
index 94681d1a37db..23c3d75d85aa 100644
--- a/arm64.c
+++ b/arm64.c
@@ -45,6 +45,7 @@ static int arm64_vtop_3level_4k(ulong, ulong, physaddr_t *, int);
static int arm64_vtop_4level_4k(ulong, ulong, physaddr_t *, int);
static ulong arm64_get_task_pgd(ulong);
static void arm64_irq_stack_init(void);
+static void arm64_overflow_stack_init(void);
static void arm64_stackframe_init(void);
static int arm64_eframe_search(struct bt_info *);
static int arm64_is_kernel_exception_frame(struct bt_info *, ulong);
@@ -63,6 +64,7 @@ static int arm64_get_dumpfile_stackframe(struct bt_info *, struct arm64_stackfra
static int arm64_in_kdump_text(struct bt_info *, struct arm64_stackframe *);
static int arm64_in_kdump_text_on_irq_stack(struct bt_info *);
static int arm64_switch_stack(struct bt_info *, struct arm64_stackframe *, FILE *);
+static int arm64_switch_stack_from_overflow(struct bt_info *, struct arm64_stackframe *, FILE *);
static int arm64_get_stackframe(struct bt_info *, struct arm64_stackframe *);
static void arm64_get_stack_frame(struct bt_info *, ulong *, ulong *);
static void arm64_gen_hidden_frame(struct bt_info *bt, ulong, struct arm64_stackframe *);
@@ -78,8 +80,11 @@ static int arm64_get_smp_cpus(void);
static void arm64_clear_machdep_cache(void);
static int arm64_on_process_stack(struct bt_info *, ulong);
static int arm64_in_alternate_stack(int, ulong);
+static int arm64_in_alternate_stackv(int cpu, ulong stkptr, ulong *stacks, ulong stack_size);
static int arm64_on_irq_stack(int, ulong);
+static int arm64_on_overflow_stack(int, ulong);
static void arm64_set_irq_stack(struct bt_info *);
+static void arm64_set_overflow_stack(struct bt_info *);
static void arm64_set_process_stack(struct bt_info *);
static int arm64_get_kvaddr_ranges(struct vaddr_range *);
static void arm64_get_crash_notes(void);
@@ -463,6 +468,7 @@ arm64_init(int when)
machdep->hz = 100;
arm64_irq_stack_init();
+ arm64_overflow_stack_init();
arm64_stackframe_init();
break;
@@ -1715,6 +1721,49 @@ arm64_irq_stack_init(void)
}
}
+/*
+ * Gather Overflow stack values.
+ *
+ * Overflow stack supported since 4.14, in commit 872d8327c
+ */
+static void
+arm64_overflow_stack_init(void)
+{
+ int i;
+ struct syment *sp;
+ struct gnu_request request, *req;
+ struct machine_specific *ms = machdep->machspec;
+ req = &request;
+
+ if (symbol_exists("overflow_stack") &&
+ (sp = per_cpu_symbol_search("overflow_stack")) &&
+ get_symbol_type("overflow_stack", NULL, req)) {
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "overflow_stack: \n");
+ fprintf(fp, " type: %x, %s\n",
+ (int)req->typecode,
+ (req->typecode == TYPE_CODE_ARRAY) ?
+ "TYPE_CODE_ARRAY" : "other");
+ fprintf(fp, " target_typecode: %x, %s\n",
+ (int)req->target_typecode,
+ req->target_typecode == TYPE_CODE_INT ?
+ "TYPE_CODE_INT" : "other");
+ fprintf(fp, " target_length: %ld\n",
+ req->target_length);
+ fprintf(fp, " length: %ld\n", req->length);
+ }
+
+ if (!(ms->overflow_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
+ error(FATAL, "cannot malloc overflow_stack addresses\n");
+
+ ms->overflow_stack_size = ARM64_OVERFLOW_STACK_SIZE;
+ machdep->flags |= OVERFLOW_STACKS;
+
+ for (i = 0; i < kt->cpus; i++)
+ ms->overflow_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
+ }
+}
+
/*
* Gather and verify all of the backtrace requirements.
*/
@@ -1960,6 +2009,7 @@ static char *arm64_exception_functions[] = {
"do_mem_abort",
"do_el0_irq_bp_hardening",
"do_sp_pc_abort",
+ "handle_bad_stack",
NULL
};
@@ -1978,7 +2028,10 @@ arm64_in_exception_text(ulong ptr)
if ((ptr >= ms->__exception_text_start) &&
(ptr < ms->__exception_text_end))
return TRUE;
- } else if ((name = closest_symbol(ptr))) { /* Linux 5.5 and later */
+ }
+
+ name = closest_symbol(ptr);
+ if (name != NULL) { /* Linux 5.5 and later */
for (func = &arm64_exception_functions[0]; *func; func++) {
if (STREQ(name, *func))
return TRUE;
@@ -2252,15 +2305,14 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
if ((frame->fp == 0) && (frame->pc == 0))
return FALSE;
- if (!(machdep->flags & IRQ_STACKS))
- return TRUE;
-
- if (!(machdep->flags & IRQ_STACKS))
+ if (!(machdep->flags & (IRQ_STACKS | OVERFLOW_STACKS)))
return TRUE;
if (machdep->flags & UNW_4_14) {
- if ((bt->flags & BT_IRQSTACK) &&
- !arm64_on_irq_stack(bt->tc->processor, frame->fp)) {
+ if (((bt->flags & BT_IRQSTACK) &&
+ !arm64_on_irq_stack(bt->tc->processor, frame->fp)) ||
+ ((bt->flags & BT_OVERFLOW_STACK) &&
+ !arm64_on_overflow_stack(bt->tc->processor, frame->fp))) {
if (arm64_on_process_stack(bt, frame->fp)) {
arm64_set_process_stack(bt);
@@ -2677,6 +2729,9 @@ arm64_back_trace_cmd(struct bt_info *bt)
if (arm64_on_irq_stack(bt->tc->processor, bt->frameptr)) {
arm64_set_irq_stack(bt);
bt->flags |= BT_IRQSTACK;
+ } else if (arm64_on_overflow_stack(bt->tc->processor, bt->frameptr)) {
+ arm64_set_overflow_stack(bt);
+ bt->flags |= BT_OVERFLOW_STACK;
}
stackframe.sp = bt->stkptr;
stackframe.pc = bt->instptr;
@@ -2731,7 +2786,9 @@ arm64_back_trace_cmd(struct bt_info *bt)
break;
if (arm64_in_exception_text(bt->instptr) && INSTACK(stackframe.fp, bt)) {
- if (!(bt->flags & BT_IRQSTACK) ||
+ if (bt->flags & BT_OVERFLOW_STACK) {
+ exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
+ } else if (!(bt->flags & BT_IRQSTACK) ||
((stackframe.sp + SIZE(pt_regs)) < bt->stacktop)) {
if (arm64_is_kernel_exception_frame(bt, stackframe.fp - KERN_EFRAME_OFFSET))
exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
@@ -2745,6 +2802,12 @@ arm64_back_trace_cmd(struct bt_info *bt)
break;
}
+ if ((bt->flags & BT_OVERFLOW_STACK) &&
+ !arm64_on_overflow_stack(bt->tc->processor, stackframe.fp)) {
+ bt->flags &= ~BT_OVERFLOW_STACK;
+ if (arm64_switch_stack_from_overflow(bt, &stackframe, ofp) == USER_MODE)
+ break;
+ }
level++;
}
@@ -3131,6 +3194,43 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
return KERNEL_MODE;
}
+static int
+arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp)
+{
+ int i;
+ ulong stacktop, words, addr;
+ ulong *stackbuf;
+ char buf[BUFSIZE];
+ struct machine_specific *ms = machdep->machspec;
+
+ if (bt->flags & BT_FULL) {
+ stacktop = ms->overflow_stacks[bt->tc->processor] + ms->overflow_stack_size;
+ words = (stacktop - bt->bptr) / sizeof(ulong);
+ stackbuf = (ulong *)GETBUF(words * sizeof(ulong));
+ readmem(bt->bptr, KVADDR, stackbuf, words * sizeof(long),
+ "top of overflow stack", FAULT_ON_ERROR);
+
+ addr = bt->bptr;
+ for (i = 0; i < words; i++) {
+ if (!(i & 1))
+ fprintf(ofp, "%s %lx: ", i ? "\n" : "", addr);
+ fprintf(ofp, "%s ", format_stack_entry(bt, buf, stackbuf[i], 0));
+ addr += sizeof(ulong);
+ }
+ fprintf(ofp, "\n");
+ FREEBUF(stackbuf);
+ }
+ fprintf(ofp, "--- <Overflow stack> ---\n");
+
+ if (frame->fp == 0)
+ return USER_MODE;
+
+ if (!(machdep->flags & UNW_4_14))
+ arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+
+ return KERNEL_MODE;
+}
+
static int
arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe *frame)
{
@@ -3682,6 +3782,16 @@ arm64_display_machine_stats(void)
machdep->machspec->irq_stacks[i]);
}
}
+ if (machdep->machspec->overflow_stack_size) {
+ fprintf(fp, "OVERFLOW STACK SIZE: %ld\n",
+ machdep->machspec->overflow_stack_size);
+ fprintf(fp, " OVERFLOW STACKS:\n");
+ for (i = 0; i < kt->cpus; i++) {
+ pad = (i < 10) ? 3 : (i < 100) ? 2 : (i < 1000) ? 1 : 0;
+ fprintf(fp, "%s CPU %d: %lx\n", space(pad), i,
+ machdep->machspec->overflow_stacks[i]);
+ }
+ }
}
static int
@@ -3875,24 +3985,41 @@ arm64_on_process_stack(struct bt_info *bt, ulong stkptr)
}
static int
-arm64_on_irq_stack(int cpu, ulong stkptr)
+arm64_in_alternate_stackv(int cpu, ulong stkptr, ulong *stacks, ulong stack_size)
{
- return arm64_in_alternate_stack(cpu, stkptr);
+ if ((cpu >= kt->cpus) || (stacks == NULL) || !stack_size)
+ return FALSE;
+
+ if ((stkptr >= stacks[cpu]) &&
+ (stkptr < (stacks[cpu] + stack_size)))
+ return TRUE;
+
+ return FALSE;
}
static int
arm64_in_alternate_stack(int cpu, ulong stkptr)
+{
+ return (arm64_on_irq_stack(cpu, stkptr) ||
+ arm64_on_overflow_stack(cpu, stkptr));
+}
+
+static int
+arm64_on_irq_stack(int cpu, ulong stkptr)
{
struct machine_specific *ms = machdep->machspec;
- if (!ms->irq_stack_size || (cpu >= kt->cpus))
- return FALSE;
+ return arm64_in_alternate_stackv(cpu, stkptr,
+ ms->irq_stacks, ms->irq_stack_size);
+}
- if ((stkptr >= ms->irq_stacks[cpu]) &&
- (stkptr < (ms->irq_stacks[cpu] + ms->irq_stack_size)))
- return TRUE;
+static int
+arm64_on_overflow_stack(int cpu, ulong stkptr)
+{
+ struct machine_specific *ms = machdep->machspec;
- return FALSE;
+ return arm64_in_alternate_stackv(cpu, stkptr,
+ ms->overflow_stacks, ms->overflow_stack_size);
}
static void
@@ -3905,6 +4032,16 @@ arm64_set_irq_stack(struct bt_info *bt)
alter_stackbuf(bt);
}
+static void
+arm64_set_overflow_stack(struct bt_info *bt)
+{
+ struct machine_specific *ms = machdep->machspec;
+
+ bt->stackbase = ms->overflow_stacks[bt->tc->processor];
+ bt->stacktop = bt->stackbase + ms->overflow_stack_size;
+ alter_stackbuf(bt);
+}
+
static void
arm64_set_process_stack(struct bt_info *bt)
{
diff --git a/defs.h b/defs.h
index a2f30853a4b1..7e2a16e34a59 100644
--- a/defs.h
+++ b/defs.h
@@ -3218,6 +3218,7 @@ typedef signed int s32;
#define UNW_4_14 (0x200)
#define FLIPPED_VM (0x400)
#define HAS_PHYSVIRT_OFFSET (0x800)
+#define OVERFLOW_STACKS (0x1000)
/*
* Get kimage_voffset from /dev/crash
@@ -3260,6 +3261,7 @@ typedef signed int s32;
#define ARM64_STACK_SIZE (16384)
#define ARM64_IRQ_STACK_SIZE ARM64_STACK_SIZE
+#define ARM64_OVERFLOW_STACK_SIZE (4096)
#define _SECTION_SIZE_BITS 30
#define _SECTION_SIZE_BITS_5_12 27
@@ -3332,6 +3334,9 @@ struct machine_specific {
char *irq_stackbuf;
ulong __irqentry_text_start;
ulong __irqentry_text_end;
+ ulong overflow_stack_size;
+ ulong *overflow_stacks;
+ char *overflow_stackbuf;
/* for exception vector code */
ulong exp_entry1_start;
ulong exp_entry1_end;
@@ -5770,6 +5775,7 @@ ulong cpu_map_addr(const char *type);
#define BT_CPUMASK (0x1000000000000ULL)
#define BT_SHOW_ALL_REGS (0x2000000000000ULL)
#define BT_REGS_NOT_FOUND (0x4000000000000ULL)
+#define BT_OVERFLOW_STACK (0x8000000000000ULL)
#define BT_SYMBOL_OFFSET (BT_SYMBOLIC_ARGS)
#define BT_REF_HEXVAL (0x1)
--
2.30.2

View File

@ -1,34 +0,0 @@
From 6ecb8a23ca294de5ef92726c782f4c92fcb39d92 Mon Sep 17 00:00:00 2001
From: Huang Shijie <shijie@os.amperecomputing.com>
Date: Fri, 11 Feb 2022 09:46:42 +0000
Subject: [PATCH] arm64: Use CONFIG_ARM64_VA_BITS to initialize VA_BITS_ACTUAL
We can get VA_BITS_ACTUAL from CONFIG_ARM64_VA_BITS by guess.
Without this patch, we may need to use "--machdep vabits_actual=48" to
set the VA_BITS_ACTUAL.
Signed-off-by: Huang Shijie <shijie@os.amperecomputing.com>
---
arm64.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arm64.c b/arm64.c
index 4f2c2b5..de1038a 100644
--- a/arm64.c
+++ b/arm64.c
@@ -4170,6 +4170,11 @@ arm64_calc_VA_BITS(void)
} else if (machdep->machspec->VA_BITS_ACTUAL) {
machdep->machspec->VA_BITS = machdep->machspec->VA_BITS_ACTUAL;
machdep->machspec->VA_START = _VA_START(machdep->machspec->VA_BITS_ACTUAL);
+ } else if (machdep->machspec->CONFIG_ARM64_VA_BITS) {
+ /* guess */
+ machdep->machspec->VA_BITS_ACTUAL = machdep->machspec->CONFIG_ARM64_VA_BITS;
+ machdep->machspec->VA_BITS = machdep->machspec->CONFIG_ARM64_VA_BITS;
+ machdep->machspec->VA_START = _VA_START(machdep->machspec->VA_BITS_ACTUAL);
} else
error(FATAL, "cannot determine VA_BITS_ACTUAL\n");
}
--
2.31.1

View File

@ -1,69 +0,0 @@
From e3bdc32aab5d8fe09b679cf394da8ba8826e207f Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Thu, 24 Feb 2022 11:52:12 +0800
Subject: [PATCH] arm64: deduce the start address of kernel code, based on
kernel version
After kernel commit e2a073dde921 ("arm64: omit [_text, _stext) from
permanent kernel mapping"), the range [_text, _stext] is reclaimed. But
the current crash code still assumes kernel starting from "_text".
This change only affects the vmalloced area on arm64 and may result a
false in arm64_IS_VMALLOC_ADDR().
Since vmcore has no extra information about this trival change, it can
only be deduced from kernel version, which means ms->kimage_text can not
be correctly initialized until kernel_init() finishes. Here on arm64, it
can be done at the point machdep_init(POST_GDB). This is fine
since there is no access to vmalloced area at this stage.
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
arm64.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arm64.c b/arm64.c
index de1038a..3ab8489 100644
--- a/arm64.c
+++ b/arm64.c
@@ -92,6 +92,20 @@ static void arm64_calc_VA_BITS(void);
static int arm64_is_uvaddr(ulong, struct task_context *);
static void arm64_calc_KERNELPACMASK(void);
+static void arm64_calc_kernel_start(void)
+{
+ struct machine_specific *ms = machdep->machspec;
+ struct syment *sp;
+
+ if (THIS_KERNEL_VERSION >= LINUX(5,11,0))
+ sp = kernel_symbol_search("_stext");
+ else
+ sp = kernel_symbol_search("_text");
+
+ ms->kimage_text = (sp ? sp->value : 0);
+ sp = kernel_symbol_search("_end");
+ ms->kimage_end = (sp ? sp->value : 0);
+}
/*
* Do all necessary machine-specific setup here. This is called several times
@@ -241,6 +255,7 @@ arm64_init(int when)
if (machdep->flags & NEW_VMEMMAP) {
struct syment *sp;
+ /* It is finally decided in arm64_calc_kernel_start() */
sp = kernel_symbol_search("_text");
ms->kimage_text = (sp ? sp->value : 0);
sp = kernel_symbol_search("_end");
@@ -387,6 +402,8 @@ arm64_init(int when)
break;
case POST_GDB:
+ /* Rely on kernel version to decide the kernel start address */
+ arm64_calc_kernel_start();
arm64_calc_virtual_memory_ranges();
arm64_get_section_size_bits();
--
2.31.1

View File

@ -0,0 +1,30 @@
From ae52398a13fa9a238279114ed671c7c514c154ee Mon Sep 17 00:00:00 2001
From: Sourabh Jain <sourabhjain@linux.ibm.com>
Date: Mon, 9 May 2022 12:49:56 +0530
Subject: [PATCH] ppc64: update the NR_CPUS to 8192
Since the kernel commit 2d8ae638bb86 ("powerpc: Make the NR_CPUS max 8192")
the NR_CPUS on Linux kernel ranges from 1-8192. So let's match NR_CPUS with
the max NR_CPUS count on the Linux kernel.
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/defs.h b/defs.h
index 1e8360d65a3b..a6735d07b32f 100644
--- a/defs.h
+++ b/defs.h
@@ -136,7 +136,7 @@
#define NR_CPUS (4096)
#endif
#ifdef PPC64
-#define NR_CPUS (2048)
+#define NR_CPUS (8192)
#endif
#ifdef S390
#define NR_CPUS (512)
--
2.30.2

View File

@ -0,0 +1,62 @@
From 364b2e413c69daf189d2bc0238e3ba9b0dcbd937 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:13 +0800
Subject: [PATCH 01/15] sbitmapq: remove struct and member validation in
sbitmapq_init()
Let's remove the struct and member validation from sbitmapq_init(), which
will help the crash to display the actual error when the sbitmapq fails.
Without the patch:
crash> sbitmapq ffff8e99d0dc8010
sbitmapq: command not supported or applicable on this architecture or kernel
With the patch:
crash> sbitmapq ffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_queue_alloc_hint
FILE: sbitmap.c LINE: 365 FUNCTION: sbitmap_queue_context_load()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
sbitmap.c | 24 ------------------------
1 file changed, 24 deletions(-)
diff --git a/sbitmap.c b/sbitmap.c
index 96a61e6c2c71..7693eef6cebd 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -525,30 +525,6 @@ void sbitmapq_init(void)
MEMBER_OFFSET_INIT(sbq_wait_state_wait_cnt, "sbq_wait_state", "wait_cnt");
MEMBER_OFFSET_INIT(sbq_wait_state_wait, "sbq_wait_state", "wait");
- if (!VALID_SIZE(sbitmap_word) ||
- !VALID_SIZE(sbitmap) ||
- !VALID_SIZE(sbitmap_queue) ||
- !VALID_SIZE(sbq_wait_state) ||
- INVALID_MEMBER(sbitmap_word_depth) ||
- INVALID_MEMBER(sbitmap_word_word) ||
- INVALID_MEMBER(sbitmap_word_cleared) ||
- INVALID_MEMBER(sbitmap_depth) ||
- INVALID_MEMBER(sbitmap_shift) ||
- INVALID_MEMBER(sbitmap_map_nr) ||
- INVALID_MEMBER(sbitmap_map) ||
- INVALID_MEMBER(sbitmap_queue_sb) ||
- INVALID_MEMBER(sbitmap_queue_alloc_hint) ||
- INVALID_MEMBER(sbitmap_queue_wake_batch) ||
- INVALID_MEMBER(sbitmap_queue_wake_index) ||
- INVALID_MEMBER(sbitmap_queue_ws) ||
- INVALID_MEMBER(sbitmap_queue_ws_active) ||
- INVALID_MEMBER(sbitmap_queue_round_robin) ||
- INVALID_MEMBER(sbitmap_queue_min_shallow_depth) ||
- INVALID_MEMBER(sbq_wait_state_wait_cnt) ||
- INVALID_MEMBER(sbq_wait_state_wait)) {
- command_not_supported();
- }
-
sb_flags |= SB_FLAG_INIT;
}
--
2.30.2

View File

@ -1,69 +0,0 @@
From 0d3d80b47d69c5d303b48c0463a026e60633cae2 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Thu, 6 Jan 2022 12:01:17 +0800
Subject: [PATCH 02/10] Fix for "bt -v" option to display the stack-end address
correctly
The "bt -v" command prints incorrect stack-end address when the
"CONFIG_THREAD_INFO_IN_TASK=y" is enabled in kernel, the "bt -v"
command output shows that the value stored at 0xffff8dee0312c198
is 0xffffffffc076400a, however, the value stored actually at
0xffff8dee0312c198 is NULL(0x0000000000000000), the stack-end
address is incorrect.
Without the patch:
crash> bt -v
PID: 28642 TASK: ffff8dee0312c180 CPU: 0 COMMAND: "insmod"
possible stack overflow: ffff8dee0312c198: ffffffffc076400a != STACK_END_MAGIC
^^^^^^^^^^^^^^^^
crash> rd 0xffff8dee0312c198
ffff8dee0312c198: 0000000000000000 ........
^^^^^^^^^^^^^^^^
With the patch:
crash> bt -v
PID: 28642 TASK: ffff8dee0312c180 CPU: 0 COMMAND: "insmod"
possible stack overflow: ffff991340bc0000: ffffffffc076400a != STACK_END_MAGIC
crash> rd 0xffff991340bc0000
ffff991340bc0000: ffffffffc076400a .@v.....
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
task.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/task.c b/task.c
index bb6a5da8ad33..b5ddc88e0acb 100644
--- a/task.c
+++ b/task.c
@@ -11202,7 +11202,7 @@ check_stack_overflow(void)
{
int i, overflow, cpu_size, cpu, total;
char buf[BUFSIZE];
- ulong magic, task, stackbase;
+ ulong magic, task, stackbase, location;
struct task_context *tc;
if (!tt->stack_end_magic &&
@@ -11286,9 +11286,15 @@ check_stack_end_magic:
if (magic != STACK_END_MAGIC) {
if (!overflow)
print_task_header(fp, tc, 0);
+
+ if (tt->flags & THREAD_INFO_IN_TASK)
+ location = task_to_stackbase(tc->task);
+ else
+ location = tc->thread_info + SIZE(thread_info);
+
fprintf(fp,
" possible stack overflow: %lx: %lx != STACK_END_MAGIC\n",
- tc->thread_info + SIZE(thread_info), magic);
+ location, magic);
overflow++, total++;
}
--
2.20.1

View File

@ -1,101 +0,0 @@
From 98b417fc63467339b919ef6d322c1893d6d55f86 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Fri, 24 Dec 2021 18:56:35 +0800
Subject: [PATCH 2/2] Handle blk_mq_ctx member changes for kernels 5.16-rc1 and
later
Kernel commit 9a14d6ce4135 ("block: remove debugfs blk_mq_ctx
dispatched/merged/completed attributes") removed the member
rq_dispatched and rq_completed from struct blk_mq_ctx. Without
the patch, "dev -d|-D" options will fail with the following error:
crash> dev -d
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
dev: invalid structure member offset: blk_mq_ctx_rq_dispatched
FILE: dev.c LINE: 4229 FUNCTION: get_one_mctx_diskio()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
dev.c | 57 +++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 39 insertions(+), 18 deletions(-)
diff --git a/dev.c b/dev.c
index effe789f38d8..a493e51ac95c 100644
--- a/dev.c
+++ b/dev.c
@@ -4246,6 +4246,10 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
unsigned long mctx_addr;
struct diskio tmp;
+ if (INVALID_MEMBER(blk_mq_ctx_rq_dispatched) ||
+ INVALID_MEMBER(blk_mq_ctx_rq_completed))
+ return;
+
memset(&tmp, 0x00, sizeof(struct diskio));
readmem(q + OFFSET(request_queue_queue_ctx), KVADDR, &queue_ctx,
@@ -4475,24 +4479,41 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
&& (io.read + io.write == 0))
return;
- fprintf(fp, "%s%s%s %s%s%s%s %s%5d%s%s%s%s%s",
- mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
- space(MINSPACE),
- mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
- space(MINSPACE),
- mkstring(buf2, 10, LJUST, disk_name),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
- LJUST|LONG_HEX, (char *)queue_addr),
- space(MINSPACE),
- io.read + io.write,
- space(MINSPACE),
- mkstring(buf4, 5, RJUST|INT_DEC,
- (char *)(unsigned long)io.read),
- space(MINSPACE),
- mkstring(buf5, 5, RJUST|INT_DEC,
- (char *)(unsigned long)io.write),
- space(MINSPACE));
+ if (use_mq_interface(queue_addr) &&
+ (INVALID_MEMBER(blk_mq_ctx_rq_dispatched) ||
+ INVALID_MEMBER(blk_mq_ctx_rq_completed)))
+ fprintf(fp, "%s%s%s %s%s%s%s %s%s%s",
+ mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
+ space(MINSPACE),
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
+ space(MINSPACE),
+ mkstring(buf2, 10, LJUST, disk_name),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
+ LJUST|LONG_HEX, (char *)queue_addr),
+ space(MINSPACE),
+ mkstring(buf4, 17, RJUST, "(not supported)"),
+ space(MINSPACE));
+
+ else
+ fprintf(fp, "%s%s%s %s%s%s%s %s%5d%s%s%s%s%s",
+ mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
+ space(MINSPACE),
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
+ space(MINSPACE),
+ mkstring(buf2, 10, LJUST, disk_name),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
+ LJUST|LONG_HEX, (char *)queue_addr),
+ space(MINSPACE),
+ io.read + io.write,
+ space(MINSPACE),
+ mkstring(buf4, 5, RJUST|INT_DEC,
+ (char *)(unsigned long)io.read),
+ space(MINSPACE),
+ mkstring(buf5, 5, RJUST|INT_DEC,
+ (char *)(unsigned long)io.write),
+ space(MINSPACE));
if (VALID_MEMBER(request_queue_in_flight)) {
if (!use_mq_interface(queue_addr)) {
--
2.20.1

View File

@ -1,41 +0,0 @@
From c477b04aee34d4f4784c326ed715e91b2c43eb3e Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
Date: Thu, 9 Dec 2021 01:05:07 +0000
Subject: [PATCH 2/3] defs.h: fix breakage of compatibility of struct
machdep_table for extension modules
Commit <2f967fb5ebd7> ("crash_taget: fetch_registers support") added new
member get_cpu_reg in the middle of struct machdep_table, which breaks
compatibility of struct machdep_table for extension modules. As the result,
crash gcore command results in unexpected behavior, furthermore may cause
segmentation fault.
Fixes: 2f967fb5ebd7 ("crash_taget: fetch_registers support")
Signed-off-by: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
---
defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/defs.h b/defs.h
index 7e2a16e34a59..7d3ed78fcd23 100644
--- a/defs.h
+++ b/defs.h
@@ -1013,7 +1013,6 @@ struct machdep_table {
ulong (*processor_speed)(void);
int (*uvtop)(struct task_context *, ulong, physaddr_t *, int);
int (*kvtop)(struct task_context *, ulong, physaddr_t *, int);
- int (*get_cpu_reg)(int, int, const char *, int, void *);
ulong (*get_task_pgd)(ulong);
void (*dump_irq)(int);
void (*get_stack_frame)(struct bt_info *, ulong *, ulong *);
@@ -1063,6 +1062,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 *);
};
/*
--
2.30.2

View File

@ -0,0 +1,118 @@
From a295cb40cd5d24fb5995cc78d29c5def3843d285 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:14 +0800
Subject: [PATCH 02/15] sbitmapq: fix invalid offset for
"sbitmap_queue_alloc_hint" on Linux v5.13-rc1
Kernel commit c548e62bcf6a ("scsi: sbitmap: Move allocation hint
into sbitmap") moved the alloc_hint member from struct sbitmap_queue
to struct sbitmap. Without the patch, the sbitmapq will fail:
crash> sbitmapq 0xffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_queue_alloc_hint
FILE: sbitmap.c LINE: 365 FUNCTION: sbitmap_queue_context_load()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 2 ++
sbitmap.c | 14 ++++++++++++--
symbols.c | 2 ++
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index a6735d07b32f..0aeb98c4f654 100644
--- a/defs.h
+++ b/defs.h
@@ -2168,6 +2168,7 @@ struct offset_table { /* stash of commonly-used offsets */
long sbitmap_queue_min_shallow_depth;
long sbq_wait_state_wait_cnt;
long sbq_wait_state_wait;
+ long sbitmap_alloc_hint;
};
struct size_table { /* stash of commonly-used sizes */
@@ -5907,6 +5908,7 @@ struct sbitmap_context {
unsigned shift;
unsigned map_nr;
ulong map_addr;
+ ulong alloc_hint;
};
typedef bool (*sbitmap_for_each_fn)(unsigned int idx, void *p);
diff --git a/sbitmap.c b/sbitmap.c
index 7693eef6cebd..2921d5447c65 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -285,6 +285,7 @@ void sbitmap_for_each_set(const struct sbitmap_context *sc,
static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
const struct sbitmap_context *sc)
{
+ ulong alloc_hint_addr = 0;
int cpus = get_cpus_possible();
int sbq_wait_state_size, wait_cnt_off, wait_off, list_head_off;
char *sbq_wait_state_buf;
@@ -297,6 +298,11 @@ static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
fprintf(fp, "bits_per_word = %u\n", 1U << sc->shift);
fprintf(fp, "map_nr = %u\n", sc->map_nr);
+ if (VALID_MEMBER(sbitmap_queue_alloc_hint))
+ alloc_hint_addr = sqc->alloc_hint;
+ else if (VALID_MEMBER(sbitmap_alloc_hint)) /* 5.13 and later */
+ alloc_hint_addr = sc->alloc_hint;
+
fputs("alloc_hint = {", fp);
first = true;
for (i = 0; i < cpus; i++) {
@@ -307,7 +313,7 @@ static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
fprintf(fp, ", ");
first = false;
- ptr = kt->__per_cpu_offset[i] + sqc->alloc_hint;
+ ptr = kt->__per_cpu_offset[i] + alloc_hint_addr;
readmem(ptr, KVADDR, &val, sizeof(val), "alloc_hint", FAULT_ON_ERROR);
fprintf(fp, "%u", val);
@@ -362,7 +368,8 @@ static void sbitmap_queue_context_load(ulong addr, struct sbitmap_queue_context
error(FATAL, "cannot read sbitmap_queue\n");
}
- sqc->alloc_hint = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_alloc_hint));
+ if (VALID_MEMBER(sbitmap_queue_alloc_hint))
+ sqc->alloc_hint = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_alloc_hint));
sqc->wake_batch = UINT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_batch));
sqc->wake_index = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_index));
sqc->ws_addr = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws));
@@ -387,6 +394,8 @@ void sbitmap_context_load(ulong addr, struct sbitmap_context *sc)
sc->shift = UINT(sbitmap_buf + OFFSET(sbitmap_shift));
sc->map_nr = UINT(sbitmap_buf + OFFSET(sbitmap_map_nr));
sc->map_addr = ULONG(sbitmap_buf + OFFSET(sbitmap_map));
+ if (VALID_MEMBER(sbitmap_alloc_hint))
+ sc->alloc_hint = ULONG(sbitmap_buf + OFFSET(sbitmap_alloc_hint));
FREEBUF(sbitmap_buf);
}
@@ -512,6 +521,7 @@ void sbitmapq_init(void)
MEMBER_OFFSET_INIT(sbitmap_shift, "sbitmap", "shift");
MEMBER_OFFSET_INIT(sbitmap_map_nr, "sbitmap", "map_nr");
MEMBER_OFFSET_INIT(sbitmap_map, "sbitmap", "map");
+ MEMBER_OFFSET_INIT(sbitmap_alloc_hint, "sbitmap", "alloc_hint");
MEMBER_OFFSET_INIT(sbitmap_queue_sb, "sbitmap_queue", "sb");
MEMBER_OFFSET_INIT(sbitmap_queue_alloc_hint, "sbitmap_queue", "alloc_hint");
diff --git a/symbols.c b/symbols.c
index ba5e2741347d..fd0eb06899f0 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10708,6 +10708,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(sbitmap_map_nr));
fprintf(fp, " sbitmap_map: %ld\n",
OFFSET(sbitmap_map));
+ fprintf(fp, " sbitmap_alloc_hint: %ld\n",
+ OFFSET(sbitmap_alloc_hint));
fprintf(fp, " sbitmap_queue_sb: %ld\n",
OFFSET(sbitmap_queue_sb));
fprintf(fp, " sbitmap_queue_alloc_hint: %ld\n",
--
2.30.2

View File

@ -1,35 +0,0 @@
From b9dc76e232e0226a14ae3089e3be5c915f2bb981 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 10 Jan 2022 17:25:06 +0800
Subject: [PATCH 03/10] Fix for HZ calculation on Linux 5.14 and later
Kernel commit 3e9a99eba058 ("block/mq-deadline: Rename dd_init_queue()
and dd_exit_queue()") renamed dd_init_queue to dd_init_sched. Without
the patch, the 'help -m' may print incorrect hz value as follows:
crash> help -m | grep hz
hz: 1000 <---The correct hz value on ppc64le machine is 100.
^^^^
Fixes: b93027ce5c75 ("Add alternate HZ calculation using write_expire")
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
task.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/task.c b/task.c
index b5ddc88e0acb..76e184ae70b1 100644
--- a/task.c
+++ b/task.c
@@ -440,6 +440,8 @@ task_init(void)
}
} else if ((symbol_exists("dd_init_queue") &&
gdb_set_crash_scope(symbol_value("dd_init_queue"), "dd_init_queue")) ||
+ (symbol_exists("dd_init_sched") &&
+ gdb_set_crash_scope(symbol_value("dd_init_sched"), "dd_init_sched")) ||
(symbol_exists("deadline_init_queue") &&
gdb_set_crash_scope(symbol_value("deadline_init_queue"), "deadline_init_queue"))) {
char buf[BUFSIZE];
--
2.20.1

View File

@ -1,41 +0,0 @@
From 6968345893178d2750b8872055498d2a6010a861 Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
Date: Wed, 8 Dec 2021 12:07:34 +0000
Subject: [PATCH 3/3] defs.h: fix breakage of compatibility of struct
symbol_table_data for extension modules
Commit <2fab8fbc0c4f> ("symbols: Implement install and remove operations
for mod_symname_hash") added new member variable mod_symname_hash in the
middle of struct symbol_table_date, which breaks compatibility of struct
symbol_table_data for extension modules. As the result, crash trace command
results in segmentation fault.
Fixes: 2fab8fbc0c4f ("symbols: Implement install and remove operations for mod_symname_hash")
Signed-off-by: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
---
defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/defs.h b/defs.h
index 7d3ed78fcd23..b63741c7d78b 100644
--- a/defs.h
+++ b/defs.h
@@ -2753,7 +2753,6 @@ struct symbol_table_data {
double val_hash_searches;
double val_hash_iterations;
struct syment *symname_hash[SYMNAME_HASH];
- struct syment *mod_symname_hash[SYMNAME_HASH];
struct symbol_namespace kernel_namespace;
struct syment *ext_module_symtable;
struct syment *ext_module_symend;
@@ -2780,6 +2779,7 @@ struct symbol_table_data {
ulong kaiser_init_vmlinux;
int kernel_symbol_type;
ulong linux_banner_vmlinux;
+ struct syment *mod_symname_hash[SYMNAME_HASH];
};
/* flags for st */
--
2.30.2

View File

@ -0,0 +1,103 @@
From 530fe6ad7e4d7ff6254596c1219d25ed929e3867 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:15 +0800
Subject: [PATCH 03/15] sbitmapq: fix invalid offset for
"sbitmap_queue_round_robin" on Linux v5.13-rc1
Kernel commit efe1f3a1d583 ("scsi: sbitmap: Maintain allocation
round_robin in sbitmap") moved the round_robin member from struct
sbitmap_queue to struct sbitmap. Without the patch, the sbitmapq
will fail:
crash> sbitmapq 0xffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_queue_round_robin
FILE: sbitmap.c LINE: 378 FUNCTION: sbitmap_queue_context_load()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 2 ++
sbitmap.c | 12 ++++++++++--
symbols.c | 2 ++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index 0aeb98c4f654..ecbced24d2e3 100644
--- a/defs.h
+++ b/defs.h
@@ -2169,6 +2169,7 @@ struct offset_table { /* stash of commonly-used offsets */
long sbq_wait_state_wait_cnt;
long sbq_wait_state_wait;
long sbitmap_alloc_hint;
+ long sbitmap_round_robin;
};
struct size_table { /* stash of commonly-used sizes */
@@ -5909,6 +5910,7 @@ struct sbitmap_context {
unsigned map_nr;
ulong map_addr;
ulong alloc_hint;
+ bool round_robin;
};
typedef bool (*sbitmap_for_each_fn)(unsigned int idx, void *p);
diff --git a/sbitmap.c b/sbitmap.c
index 2921d5447c65..7b318b533702 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -352,7 +352,11 @@ static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
FREEBUF(sbq_wait_state_buf);
- fprintf(fp, "round_robin = %d\n", sqc->round_robin);
+ if (VALID_MEMBER(sbitmap_queue_round_robin))
+ fprintf(fp, "round_robin = %d\n", sqc->round_robin);
+ else if (VALID_MEMBER(sbitmap_round_robin)) /* 5.13 and later */
+ fprintf(fp, "round_robin = %d\n", sc->round_robin);
+
fprintf(fp, "min_shallow_depth = %u\n", sqc->min_shallow_depth);
}
@@ -374,7 +378,8 @@ static void sbitmap_queue_context_load(ulong addr, struct sbitmap_queue_context
sqc->wake_index = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_index));
sqc->ws_addr = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws));
sqc->ws_active = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws_active));
- sqc->round_robin = BOOL(sbitmap_queue_buf + OFFSET(sbitmap_queue_round_robin));
+ if (VALID_MEMBER(sbitmap_queue_round_robin))
+ sqc->round_robin = BOOL(sbitmap_queue_buf + OFFSET(sbitmap_queue_round_robin));
sqc->min_shallow_depth = UINT(sbitmap_queue_buf + OFFSET(sbitmap_queue_min_shallow_depth));
FREEBUF(sbitmap_queue_buf);
@@ -396,6 +401,8 @@ void sbitmap_context_load(ulong addr, struct sbitmap_context *sc)
sc->map_addr = ULONG(sbitmap_buf + OFFSET(sbitmap_map));
if (VALID_MEMBER(sbitmap_alloc_hint))
sc->alloc_hint = ULONG(sbitmap_buf + OFFSET(sbitmap_alloc_hint));
+ if (VALID_MEMBER(sbitmap_round_robin))
+ sc->round_robin = BOOL(sbitmap_buf + OFFSET(sbitmap_round_robin));
FREEBUF(sbitmap_buf);
}
@@ -522,6 +529,7 @@ void sbitmapq_init(void)
MEMBER_OFFSET_INIT(sbitmap_map_nr, "sbitmap", "map_nr");
MEMBER_OFFSET_INIT(sbitmap_map, "sbitmap", "map");
MEMBER_OFFSET_INIT(sbitmap_alloc_hint, "sbitmap", "alloc_hint");
+ MEMBER_OFFSET_INIT(sbitmap_round_robin, "sbitmap", "round_robin");
MEMBER_OFFSET_INIT(sbitmap_queue_sb, "sbitmap_queue", "sb");
MEMBER_OFFSET_INIT(sbitmap_queue_alloc_hint, "sbitmap_queue", "alloc_hint");
diff --git a/symbols.c b/symbols.c
index fd0eb06899f0..5d12a021c769 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10710,6 +10710,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(sbitmap_map));
fprintf(fp, " sbitmap_alloc_hint: %ld\n",
OFFSET(sbitmap_alloc_hint));
+ fprintf(fp, " sbitmap_round_robin: %ld\n",
+ OFFSET(sbitmap_round_robin));
fprintf(fp, " sbitmap_queue_sb: %ld\n",
OFFSET(sbitmap_queue_sb));
fprintf(fp, " sbitmap_queue_alloc_hint: %ld\n",
--
2.30.2

View File

@ -1,39 +0,0 @@
From 14f8c460473c8613553b5defd174ca2af812ddcb Mon Sep 17 00:00:00 2001
From: Alexander Egorenkov <egorenar@linux.ibm.com>
Date: Mon, 6 Dec 2021 16:04:19 +0100
Subject: [PATCH 04/10] memory: Handle struct slab changes on Linux 5.17-rc1
and later
Since kernel commit d122019bf061 ("mm: Split slab into its own type"),
the struct slab is used for both SLAB and SLUB. Therefore, don't depend
on the non-presence of the struct slab to decide whether SLAB implementation
should be chosen and use the member variable "cpu_slab" of the struct
kmem_cache instead, it should be present only in SLUB.
Without the patch, crash fails to start with the error message:
crash: invalid structure member offset: kmem_cache_s_num
FILE: memory.c LINE: 9619 FUNCTION: kmem_cache_init()
Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
---
memory.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/memory.c b/memory.c
index 86c02c132890..5af45fd7d834 100644
--- a/memory.c
+++ b/memory.c
@@ -576,7 +576,8 @@ vm_init(void)
STRUCT_SIZE_INIT(cpucache_s, "cpucache_s");
} else if (!VALID_STRUCT(kmem_slab_s) &&
- !VALID_STRUCT(slab_s) &&
+ !VALID_STRUCT(slab_s) &&
+ !MEMBER_EXISTS("kmem_cache", "cpu_slab") &&
(VALID_STRUCT(slab) || (vt->flags & SLAB_OVERLOAD_PAGE))) {
vt->flags |= PERCPU_KMALLOC_V2;
--
2.20.1

View File

@ -0,0 +1,101 @@
From 3750803f6ae5f5ad071f86ca916dbbb17b7a83a5 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:16 +0800
Subject: [PATCH 04/15] sbitmapq: fix invalid offset for "sbitmap_word_depth"
on Linux v5.18-rc1
Kernel commit 3301bc53358a ("lib/sbitmap: kill 'depth' from sbitmap_word")
removed the depth member from struct sbitmap_word. Without the patch, the
sbitmapq will fail:
crash> sbitmapq 0xffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_word_depth
FILE: sbitmap.c LINE: 84 FUNCTION: __sbitmap_weight()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
sbitmap.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/sbitmap.c b/sbitmap.c
index 7b318b533702..e8ebd62fe01c 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -78,10 +78,16 @@ static unsigned long bitmap_weight(unsigned long bitmap, unsigned int bits)
return w;
}
+static inline unsigned int __map_depth(const struct sbitmap_context *sc, int index)
+{
+ if (index == sc->map_nr - 1)
+ return sc->depth - (index << sc->shift);
+ return 1U << sc->shift;
+}
+
static unsigned int __sbitmap_weight(const struct sbitmap_context *sc, bool set)
{
const ulong sbitmap_word_size = SIZE(sbitmap_word);
- const ulong w_depth_off = OFFSET(sbitmap_word_depth);
const ulong w_word_off = OFFSET(sbitmap_word_word);
const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
@@ -99,7 +105,7 @@ static unsigned int __sbitmap_weight(const struct sbitmap_context *sc, bool set)
error(FATAL, "cannot read sbitmap_word\n");
}
- depth = ULONG(sbitmap_word_buf + w_depth_off);
+ depth = __map_depth(sc, i);
if (set) {
word = ULONG(sbitmap_word_buf + w_word_off);
@@ -142,7 +148,6 @@ static void sbitmap_emit_byte(unsigned int offset, uint8_t byte)
static void sbitmap_bitmap_show(const struct sbitmap_context *sc)
{
const ulong sbitmap_word_size = SIZE(sbitmap_word);
- const ulong w_depth_off = OFFSET(sbitmap_word_depth);
const ulong w_word_off = OFFSET(sbitmap_word_word);
const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
@@ -165,7 +170,7 @@ static void sbitmap_bitmap_show(const struct sbitmap_context *sc)
word = ULONG(sbitmap_word_buf + w_word_off);
cleared = ULONG(sbitmap_word_buf + w_cleared_off);
- word_bits = ULONG(sbitmap_word_buf + w_depth_off);
+ word_bits = __map_depth(sc, i);
word &= ~cleared;
@@ -213,7 +218,6 @@ static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
unsigned int start, sbitmap_for_each_fn fn, void *data)
{
const ulong sbitmap_word_size = SIZE(sbitmap_word);
- const ulong w_depth_off = OFFSET(sbitmap_word_depth);
const ulong w_word_off = OFFSET(sbitmap_word_word);
const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
@@ -232,7 +236,7 @@ static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
while (scanned < sc->depth) {
unsigned long w_addr = sc->map_addr + (sbitmap_word_size * index);
- unsigned long w_depth, w_word, w_cleared;
+ unsigned long w_word, w_cleared;
unsigned long word, depth;
if (!readmem(w_addr, KVADDR, sbitmap_word_buf, sbitmap_word_size, "sbitmap_word", RETURN_ON_ERROR)) {
@@ -240,11 +244,10 @@ static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
error(FATAL, "cannot read sbitmap_word\n");
}
- w_depth = ULONG(sbitmap_word_buf + w_depth_off);
w_word = ULONG(sbitmap_word_buf + w_word_off);
w_cleared = ULONG(sbitmap_word_buf + w_cleared_off);
- depth = min(w_depth - nr, sc->depth - scanned);
+ depth = min(__map_depth(sc, index) - nr, sc->depth - scanned);
scanned += depth;
word = w_word & ~w_cleared;
--
2.30.2

View File

@ -0,0 +1,26 @@
From 9705669a49c341402efd8528e8fe809379dd798d Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
Date: Mon, 23 May 2022 14:48:50 +0900
Subject: [PATCH 05/15] Makefile: add missing crash_target.o to be cleaned
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index e520b1217a9d..162c2baa5164 100644
--- a/Makefile
+++ b/Makefile
@@ -184,7 +184,7 @@ GDB_7.6_FILES=
GDB_7.6_OFILES=${GDB}/gdb/symtab.o
GDB_10.2_FILES=
-GDB_10.2_OFILES=${GDB}/gdb/symtab.o
+GDB_10.2_OFILES=${GDB}/gdb/symtab.o crash_target.o
#
# GDB_FLAGS is passed up from the gdb Makefile.
--
2.30.2

View File

@ -1,75 +0,0 @@
From d16dc6fff0260ec26002046fae4aeb546d6b9a0e Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 17 Jan 2022 15:14:00 +0800
Subject: [PATCH 05/10] Move the initialization of "boot_date" to task_init()
The "boot_date" is initialized conditionally in the cmd_log(), which may
display incorrect "boot_date" value with the following command before
running the "log -T" command:
crash> help -k | grep date
date: Wed Dec 22 13:39:29 IST 2021
boot_date: Thu Jan 1 05:30:00 IST 1970
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The calculation of "boot_date" depends on the HZ value, and the HZ will
be calculated in task_init() at the latest, so let's move it here.
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
kernel.c | 18 +++---------------
task.c | 10 ++++++++++
2 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/kernel.c b/kernel.c
index 36c57ed501ad..094fe9b2efad 100644
--- a/kernel.c
+++ b/kernel.c
@@ -5025,21 +5025,9 @@ cmd_log(void)
if (argerrs)
cmd_usage(pc->curcmd, SYNOPSIS);
- if (msg_flags & SHOW_LOG_CTIME) {
- if (pc->flags & MINIMAL_MODE) {
- error(WARNING, "the option '-T' is not available in minimal mode\n");
- return;
- }
-
- if (kt->boot_date.tv_sec == 0) {
- ulonglong uptime_jiffies;
- ulong uptime_sec;
-
- get_uptime(NULL, &uptime_jiffies);
- uptime_sec = (uptime_jiffies)/(ulonglong)machdep->hz;
- kt->boot_date.tv_sec = kt->date.tv_sec - uptime_sec;
- kt->boot_date.tv_nsec = 0;
- }
+ if (msg_flags & SHOW_LOG_CTIME && pc->flags & MINIMAL_MODE) {
+ error(WARNING, "the option '-T' is not available in minimal mode\n");
+ return;
}
if (msg_flags & SHOW_LOG_AUDIT) {
diff --git a/task.c b/task.c
index 76e184ae70b1..263a8344dd94 100644
--- a/task.c
+++ b/task.c
@@ -692,6 +692,16 @@ task_init(void)
stack_overflow_check_init();
+ if (machdep->hz) {
+ ulonglong uptime_jiffies;
+ ulong uptime_sec;
+
+ get_uptime(NULL, &uptime_jiffies);
+ uptime_sec = (uptime_jiffies)/(ulonglong)machdep->hz;
+ kt->boot_date.tv_sec = kt->date.tv_sec - uptime_sec;
+ kt->boot_date.tv_nsec = 0;
+ }
+
tt->flags |= TASK_INIT_DONE;
}
--
2.20.1

View File

@ -1,78 +0,0 @@
From 2ebd8c5ecf1f077975b82325a38dd777b594d0a9 Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
Date: Wed, 19 Jan 2022 16:24:49 +0900
Subject: [PATCH 06/10] Remove ptype command from "ps -t" option to reduce
memory and time
With some vmlinux e.g. RHEL9 ones, the first execution of the gdb ptype
command heavily consumes memory and time. The "ps -t" option uses it in
start_time_timespec(), and it can be replaced with the crash macros.
This can reduce about 1.4 GB memory and 6 seconds time comsumption in
the following test:
$ echo "ps -t" | time crash vmlinux vmcore
Without the patch:
11.60user 0.43system 0:11.94elapsed 100%CPU (0avgtext+0avgdata 1837964maxresident)k
0inputs+400outputs (0major+413636minor)pagefaults 0swaps
With the patch:
5.40user 0.16system 0:05.46elapsed 101%CPU (0avgtext+0avgdata 417896maxresident)k
0inputs+384outputs (0major+41528minor)pagefaults 0swaps
Although the ptype command and similar ones cannot be fully removed,
but removing some of them will make the use of crash safer, especially
for an automatic crash reporter.
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
task.c | 25 +++++--------------------
1 file changed, 5 insertions(+), 20 deletions(-)
diff --git a/task.c b/task.c
index 263a8344dd94..a79ed0d96fb5 100644
--- a/task.c
+++ b/task.c
@@ -4662,8 +4662,6 @@ show_task_times(struct task_context *tcp, ulong flags)
static int
start_time_timespec(void)
{
- char buf[BUFSIZE];
-
switch(tt->flags & (TIMESPEC | NO_TIMESPEC | START_TIME_NSECS))
{
case TIMESPEC:
@@ -4677,24 +4675,11 @@ start_time_timespec(void)
tt->flags |= NO_TIMESPEC;
- open_tmpfile();
- sprintf(buf, "ptype struct task_struct");
- if (!gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR)) {
- close_tmpfile();
- return FALSE;
- }
-
- rewind(pc->tmpfile);
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- if (strstr(buf, "start_time;")) {
- if (strstr(buf, "struct timespec")) {
- tt->flags &= ~NO_TIMESPEC;
- tt->flags |= TIMESPEC;
- }
- }
- }
-
- close_tmpfile();
+ if (VALID_MEMBER(task_struct_start_time) &&
+ STREQ(MEMBER_TYPE_NAME("task_struct", "start_time"), "timespec")) {
+ tt->flags &= ~NO_TIMESPEC;
+ tt->flags |= TIMESPEC;
+ }
if ((tt->flags & NO_TIMESPEC) && (SIZE(task_struct_start_time) == 8)) {
tt->flags &= ~NO_TIMESPEC;
--
2.20.1

View File

@ -0,0 +1,204 @@
From 6833262bf87177d8affe4f91b2e7d2c76ecdf636 Mon Sep 17 00:00:00 2001
From: Qi Zheng <zhengqi.arch@bytedance.com>
Date: Tue, 24 May 2022 20:25:53 +0800
Subject: [PATCH 06/15] bt: x86_64: filter out idle task stack
When we use crash to troubleshoot softlockup and other problems,
we often use the 'bt -a' command to print the stacks of running
processes on all CPUs. But now some servers have hundreds of CPUs
(such as AMD machines), which causes the 'bt -a' command to output
a lot of process stacks. And many of these stacks are the stacks
of the idle process, which are not needed by us.
Therefore, in order to reduce this part of the interference information,
this patch adds the -n option to the bt command. When we specify
'-n idle' (meaning no idle), the stack of the idle process will be
filtered out, thus speeding up our troubleshooting.
And the option works only for crash dumps captured by kdump.
The command output is as follows:
crash> bt -a -n idle
[...]
PID: 0 TASK: ffff889ff8c34380 CPU: 8 COMMAND: "swapper/8"
PID: 0 TASK: ffff889ff8c32d00 CPU: 9 COMMAND: "swapper/9"
PID: 0 TASK: ffff889ff8c31680 CPU: 10 COMMAND: "swapper/10"
PID: 0 TASK: ffff889ff8c35a00 CPU: 11 COMMAND: "swapper/11"
PID: 0 TASK: ffff889ff8c3c380 CPU: 12 COMMAND: "swapper/12"
PID: 150773 TASK: ffff889fe85a1680 CPU: 13 COMMAND: "bash"
#0 [ffffc9000d35bcd0] machine_kexec at ffffffff8105a407
#1 [ffffc9000d35bd28] __crash_kexec at ffffffff8113033d
#2 [ffffc9000d35bdf0] panic at ffffffff81081930
#3 [ffffc9000d35be70] sysrq_handle_crash at ffffffff814e38d1
#4 [ffffc9000d35be78] __handle_sysrq.cold.12 at ffffffff814e4175
#5 [ffffc9000d35bea8] write_sysrq_trigger at ffffffff814e404b
#6 [ffffc9000d35beb8] proc_reg_write at ffffffff81330d86
#7 [ffffc9000d35bed0] vfs_write at ffffffff812a72d5
#8 [ffffc9000d35bf00] ksys_write at ffffffff812a7579
#9 [ffffc9000d35bf38] do_syscall_64 at ffffffff81004259
RIP: 00007fa7abcdc274 RSP: 00007fffa731f678 RFLAGS: 00000246
RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fa7abcdc274
RDX: 0000000000000002 RSI: 0000563ca51ee6d0 RDI: 0000000000000001
RBP: 0000563ca51ee6d0 R8: 000000000000000a R9: 00007fa7abd6be80
R10: 000000000000000a R11: 0000000000000246 R12: 00007fa7abdad760
R13: 0000000000000002 R14: 00007fa7abda8760 R15: 0000000000000002
ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b
[...]
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Acked-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Acked-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 1 +
help.c | 33 ++++++++++++++++++++++++++++++++-
kernel.c | 13 ++++++++++++-
x86_64.c | 8 ++++++++
4 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index ecbced24d2e3..c8444b4e54eb 100644
--- a/defs.h
+++ b/defs.h
@@ -5832,6 +5832,7 @@ ulong cpu_map_addr(const char *type);
#define BT_SHOW_ALL_REGS (0x2000000000000ULL)
#define BT_REGS_NOT_FOUND (0x4000000000000ULL)
#define BT_OVERFLOW_STACK (0x8000000000000ULL)
+#define BT_SKIP_IDLE (0x10000000000000ULL)
#define BT_SYMBOL_OFFSET (BT_SYMBOLIC_ARGS)
#define BT_REF_HEXVAL (0x1)
diff --git a/help.c b/help.c
index 51a0fe3d687c..e1bbc5abe029 100644
--- a/help.c
+++ b/help.c
@@ -1909,12 +1909,14 @@ char *help_bt[] = {
"bt",
"backtrace",
"[-a|-c cpu(s)|-g|-r|-t|-T|-l|-e|-E|-f|-F|-o|-O|-v|-p] [-R ref] [-s [-x|d]]"
-"\n [-I ip] [-S sp] [pid | task]",
+"\n [-I ip] [-S sp] [-n idle] [pid | task]",
" Display a kernel stack backtrace. If no arguments are given, the stack",
" trace of the current context will be displayed.\n",
" -a displays the stack traces of the active task on each CPU.",
" (only applicable to crash dumps)",
" -A same as -a, but also displays vector registers (S390X only).",
+" -n idle filter the stack of idle tasks (x86_64).",
+" (only applicable to crash dumps)",
" -p display the stack trace of the panic task only.",
" (only applicable to crash dumps)",
" -c cpu display the stack trace of the active task on one or more CPUs,",
@@ -2004,6 +2006,35 @@ char *help_bt[] = {
" DS: 002b ESI: bfffc8a0 ES: 002b EDI: 00000000 ",
" SS: 002b ESP: bfffc82c EBP: bfffd224 ",
" CS: 0023 EIP: 400d032e ERR: 0000008e EFLAGS: 00000246 ",
+" ",
+" Display the stack trace of the active task(s) when the kernel panicked,",
+" and filter out the stack of the idle tasks:",
+" ",
+" %s> bt -a -n idle",
+" ...",
+" PID: 0 TASK: ffff889ff8c35a00 CPU: 11 COMMAND: \"swapper/11\"",
+" ",
+" PID: 0 TASK: ffff889ff8c3c380 CPU: 12 COMMAND: \"swapper/12\"",
+" ",
+" PID: 150773 TASK: ffff889fe85a1680 CPU: 13 COMMAND: \"bash\"",
+" #0 [ffffc9000d35bcd0] machine_kexec at ffffffff8105a407",
+" #1 [ffffc9000d35bd28] __crash_kexec at ffffffff8113033d",
+" #2 [ffffc9000d35bdf0] panic at ffffffff81081930",
+" #3 [ffffc9000d35be70] sysrq_handle_crash at ffffffff814e38d1",
+" #4 [ffffc9000d35be78] __handle_sysrq.cold.12 at ffffffff814e4175",
+" #5 [ffffc9000d35bea8] write_sysrq_trigger at ffffffff814e404b",
+" #6 [ffffc9000d35beb8] proc_reg_write at ffffffff81330d86",
+" #7 [ffffc9000d35bed0] vfs_write at ffffffff812a72d5",
+" #8 [ffffc9000d35bf00] ksys_write at ffffffff812a7579",
+" #9 [ffffc9000d35bf38] do_syscall_64 at ffffffff81004259",
+" RIP: 00007fa7abcdc274 RSP: 00007fffa731f678 RFLAGS: 00000246",
+" RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fa7abcdc274",
+" RDX: 0000000000000002 RSI: 0000563ca51ee6d0 RDI: 0000000000000001",