1 Star 0 Fork 41

jlwwlsqc/crash

forked from src-openEuler/crash 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
add-SDEI-stack-resolution.patch 11.73 KB
一键复制 编辑 原始数据 按行查看 历史
hexiaowen 提交于 2019-09-30 10:35 . Package init
From e43071b6ceaa4fe20c65befe1b5685b68dc9f33f Mon Sep 17 00:00:00 2001
From: Jialong Chen <chenjialong@huawei.com>
Date: Wed, 5 Jun 2019 21:25:34 +0800
Subject: [PATCH] crash: add SDEI stack resolution
reason: The kernel adds NMI dog detection, and the NMI interrupt stack uses a separate SDEI stack.
When the NMI dog is called, the kernel stack will switch to the sdei stack.
If the crash reads the stack data, the stack data cannot be parsed normally.
normal call trace as follows:
PID: 55429 TASK: ffff802772e3ae80 CPU: 19 COMMAND: "insmod"
#0 [ffff00000d4e3c70] __crash_kexec at ffff0000081b4ac0
#1 [ffff00000d4e3e00] panic at ffff0000080ebd0c
#2 [ffff00000d4e3ee0] nmi_panic at ffff0000080eb864
#3 [ffff00000d4e3f00] watchdog_hardlockup_check at ffff0000081ecd6c
#4 [ffff00000d4e3f40] sdei_watchdog_callback at ffff0000080a411c
#5 [ffff00000d4e3f60] sdei_event_handler at ffff0000087971ec
#6 [ffff00000d4e3f90] __sdei_handler at ffff000008995964
#7 [ffff00000d4e3ff0] __sdei_asm_handler at ffff0000080862dc
--- <IRQ stack> ---
#8 [ffff0000ccad3b70] __delay at ffff000008973658
#9 [ffff0000ccad3ba0] __const_udelay at ffff0000089735e8
#10 [ffff0000ccad3bb0] init_module at ffff0000009c6038 [test]
#11 [ffff0000ccad3bd0] do_one_initcall at ffff000008084ae0
#12 [ffff0000ccad3c60] do_init_module at ffff0000081b1418
#13 [ffff0000ccad3c90] load_module at ffff0000081afc54
#14 [ffff0000ccad3d80] __se_sys_finit_module at ffff0000081b0134
#15 [ffff0000ccad3e40] __arm64_sys_finit_module at ffff0000081b01a0
#16 [ffff0000ccad3e60] el0_svc_common at ffff000008097b44
#17 [ffff0000ccad3ea0] el0_svc_handler at ffff000008097c34
#18 [ffff0000ccad3ff0] el0_svc at ffff000008084144
Signed-off-by: Jialong Chen <chenjialong@huawei.com>
---
arm64.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
defs.h | 3 +
2 files changed, 209 insertions(+), 4 deletions(-)
diff --git a/arm64.c b/arm64.c
index 4ee53ce..95e7d72 100644
--- a/arm64.c
+++ b/arm64.c
@@ -82,6 +82,10 @@ static int arm64_get_crash_notes(void);
static void arm64_calc_VA_BITS(void);
static int arm64_is_uvaddr(ulong, struct task_context *);
+static int arm64_in_sdei_normal_stack(int cpu, ulong stkptr);
+static void arm64_set_sdei_normal_stack(struct bt_info *bt);
+static void arm64_sdei_stack_init(void);
+static int arm64_in_kdump_text_on_sdei_stack(struct bt_info *bt);
/*
* Do all necessary machine-specific setup here. This is called several times
@@ -406,6 +410,7 @@ arm64_init(int when)
arm64_irq_stack_init();
arm64_stackframe_init();
+ arm64_sdei_stack_init();
break;
case POST_VM:
@@ -1446,6 +1451,70 @@ arm64_irq_stack_init(void)
readmem(p, KVADDR, &(ms->irq_stacks[i]), sizeof(ulong),
"IRQ stack pointer", RETURN_ON_ERROR);
}
+ }
+}
+
+/*
+ * Gather IRQ stack values.
+ */
+static void
+arm64_sdei_stack_init(void)
+{
+ int i;
+ struct syment *sp;
+ struct gnu_request request, *req;
+ struct machine_specific *ms = machdep->machspec;
+ ulong p, sz;
+ req = &request;
+
+ if (symbol_exists("sdei_stack_normal_ptr") &&
+ (sp = per_cpu_symbol_search("sdei_stack_normal_ptr")) &&
+ get_symbol_type("sdei_stack_normal_ptr", NULL, req)) {
+ /* v4.14 and later with CONFIG_VMAP_STACK enabled */
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "sdei_stack_normal_ptr: \n");
+ fprintf(fp, " type: %x, %s\n",
+ (int)req->typecode,
+ (req->typecode == TYPE_CODE_PTR) ?
+ "TYPE_CODE_PTR" : "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->sdei_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
+ error(FATAL, "cannot malloc irq_stack addresses\n");
+
+ /*
+ * Determining the IRQ_STACK_SIZE is tricky, but for now
+ * 4.14 kernel has:
+ *
+ * #define IRQ_STACK_SIZE THREAD_SIZE
+ *
+ * and finding a solid usage of THREAD_SIZE is hard, but:
+ *
+ * union thread_union {
+ * ...
+ * unsigned long stack[THREAD_SIZE/sizeof(long)];
+ * };
+ */
+ if (MEMBER_EXISTS("thread_union", "stack")) {
+ if ((sz = MEMBER_SIZE("thread_union", "stack")) > 0)
+ ms->sdei_stack_size = sz;
+ } else
+ ms->sdei_stack_size = ARM64_IRQ_STACK_SIZE;
+
+ machdep->flags |= IRQ_STACKS;
+
+ for (i = 0; i < kt->cpus; i++) {
+ p = kt->__per_cpu_offset[i] + sp->value;
+ readmem(p, KVADDR, &(ms->sdei_stacks[i]), sizeof(ulong),
+ "SDEI stack pointer", RETURN_ON_ERROR);
+ }
}
}
@@ -1943,7 +2012,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
{
unsigned long high, low, fp;
unsigned long stack_mask;
- unsigned long irq_stack_ptr, orig_sp;
+ unsigned long irq_stack_ptr, orig_sp, sdei_stack_ptr;
struct arm64_pt_regs *ptregs;
struct machine_specific *ms;
@@ -1971,7 +2040,8 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
if (machdep->flags & UNW_4_14) {
if ((bt->flags & BT_IRQSTACK) &&
- !arm64_on_irq_stack(bt->tc->processor, frame->fp)) {
+ !arm64_on_irq_stack(bt->tc->processor, frame->fp) &&
+ !arm64_in_sdei_normal_stack(bt->tc->processor, frame->fp)) {
if (arm64_on_process_stack(bt, frame->fp)) {
arm64_set_process_stack(bt);
@@ -2012,6 +2082,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
*/
ms = machdep->machspec;
irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - 16;
+ sdei_stack_ptr = ms->sdei_stacks[bt->tc->processor] + ms->sdei_stack_size - 16;
if (frame->sp == irq_stack_ptr) {
orig_sp = GET_STACK_ULONG(irq_stack_ptr - 8);
@@ -2032,6 +2103,25 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)");
return FALSE;
}
+ } else if (frame->sp == sdei_stack_ptr) {
+ orig_sp = GET_STACK_ULONG(sdei_stack_ptr - 8);
+ arm64_set_process_stack(bt);
+ if (INSTACK(orig_sp, bt) && (INSTACK(frame->fp, bt) || (frame->fp == 0))) {
+ ptregs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(orig_sp))];
+ frame->sp = orig_sp;
+ frame->pc = ptregs->pc;
+ bt->bptr = fp;
+ if (CRASHDEBUG(1))
+ error(INFO,
+ "arm64_unwind_frame: switch stacks: fp: %lx sp: %lx pc: %lx\n",
+ frame->fp, frame->sp, frame->pc);
+ } else {
+ error(WARNING,
+ "arm64_unwind_frame: on IRQ stack: oriq_sp: %lx%s fp: %lx%s\n",
+ orig_sp, INSTACK(orig_sp, bt) ? "" : " (?)",
+ frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)");
+ return FALSE;
+ }
}
return TRUE;
@@ -2371,6 +2461,10 @@ arm64_back_trace_cmd(struct bt_info *bt)
arm64_set_irq_stack(bt);
bt->flags |= BT_IRQSTACK;
}
+ if (arm64_in_sdei_normal_stack(bt->tc->processor, bt->bptr)) {
+ arm64_set_sdei_normal_stack(bt);
+ bt->flags |= BT_IRQSTACK;
+ }
stackframe.fp = GET_STACK_ULONG(bt->bptr - 8);
stackframe.pc = GET_STACK_ULONG(bt->bptr);
stackframe.sp = bt->bptr + 8;
@@ -2380,6 +2474,10 @@ arm64_back_trace_cmd(struct bt_info *bt)
arm64_set_irq_stack(bt);
bt->flags |= BT_IRQSTACK;
}
+ if (arm64_in_sdei_normal_stack(bt->tc->processor, bt->hp->esp)) {
+ arm64_set_sdei_normal_stack(bt);
+ bt->flags |= BT_IRQSTACK;
+ }
stackframe.fp = GET_STACK_ULONG(bt->hp->esp - 8);
stackframe.pc = bt->hp->eip ?
bt->hp->eip : GET_STACK_ULONG(bt->hp->esp);
@@ -2390,6 +2488,10 @@ arm64_back_trace_cmd(struct bt_info *bt)
arm64_set_irq_stack(bt);
bt->flags |= BT_IRQSTACK;
}
+ if (arm64_in_sdei_normal_stack(bt->tc->processor, bt->frameptr)) {
+ arm64_set_sdei_normal_stack(bt);
+ bt->flags |= BT_IRQSTACK;
+ }
stackframe.sp = bt->stkptr;
stackframe.pc = bt->instptr;
stackframe.fp = bt->frameptr;
@@ -2451,7 +2553,8 @@ arm64_back_trace_cmd(struct bt_info *bt)
}
if ((bt->flags & BT_IRQSTACK) &&
- !arm64_on_irq_stack(bt->tc->processor, stackframe.fp)) {
+ !arm64_on_irq_stack(bt->tc->processor, stackframe.fp) &&
+ !arm64_in_sdei_normal_stack(bt->tc->processor, stackframe.fp)) {
bt->flags &= ~BT_IRQSTACK;
if (arm64_switch_stack(bt, &stackframe, ofp) == USER_MODE)
break;
@@ -2729,6 +2832,79 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame)
return FALSE;
}
+static int
+arm64_in_kdump_text_on_sdei_stack(struct bt_info *bt)
+{
+ int cpu;
+ ulong stackbase;
+ char *stackbuf;
+ ulong *ptr, *start, *base;
+ struct machine_specific *ms;
+
+ if ((machdep->flags & (IRQ_STACKS|KDUMP_ENABLED)) != (IRQ_STACKS|KDUMP_ENABLED))
+ return FALSE;
+
+ ms = machdep->machspec;
+ cpu = bt->tc->processor;
+ stackbase = ms->sdei_stacks[cpu];
+ stackbuf = GETBUF(ms->sdei_stack_size);
+
+ if (!readmem(stackbase, KVADDR, stackbuf,
+ ms->sdei_stack_size, "IRQ stack contents", RETURN_ON_ERROR)) {
+ error(INFO, "read of IRQ stack at %lx failed\n", stackbase);
+ FREEBUF(stackbuf);
+ return FALSE;
+ }
+
+ base = (ulong *)stackbuf;
+ start = (ulong *)(stackbuf + ms->sdei_stack_size);
+
+ for (ptr = start - 8; ptr >= base; ptr--) {
+ if (bt->flags & BT_OPT_BACK_TRACE) {
+ if ((*ptr >= ms->crash_kexec_start) &&
+ (*ptr < ms->crash_kexec_end) &&
+ INSTACK(*(ptr - 1), bt)) {
+ bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase;
+ if (CRASHDEBUG(1))
+ fprintf(fp, "%lx: %lx (crash_kexec on IRQ stack)\n",
+ bt->bptr, *ptr);
+ FREEBUF(stackbuf);
+ return TRUE;
+ }
+ if ((*ptr >= ms->crash_save_cpu_start) &&
+ (*ptr < ms->crash_save_cpu_end) &&
+ INSTACK(*(ptr - 1), bt)) {
+ bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase;
+ if (CRASHDEBUG(1))
+ fprintf(fp, "%lx: %lx (crash_save_cpu on IRQ stack)\n",
+ bt->bptr, *ptr);
+ FREEBUF(stackbuf);
+ return TRUE;
+ }
+ } else {
+ if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) {
+ bt->bptr = ((ulong)ptr - (ulong)base) + stackbase;
+ if (CRASHDEBUG(1))
+ fprintf(fp, "%lx: %lx (crash_kexec on IRQ stack)\n",
+ bt->bptr, *ptr);
+ FREEBUF(stackbuf);
+ return TRUE;
+ }
+ if ((*ptr >= ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) {
+ bt->bptr = ((ulong)ptr - (ulong)base) + stackbase;
+ if (CRASHDEBUG(1))
+ fprintf(fp, "%lx: %lx (crash_save_cpu on IRQ stack)\n",
+ bt->bptr, *ptr);
+ FREEBUF(stackbuf);
+ return TRUE;
+ }
+ }
+ }
+
+ FREEBUF(stackbuf);
+ return FALSE;
+}
+
static int
arm64_in_kdump_text_on_irq_stack(struct bt_info *bt)
{
@@ -2876,7 +3052,8 @@ try_kernel:
}
if (arm64_in_kdump_text(bt, frame) ||
- arm64_in_kdump_text_on_irq_stack(bt))
+ arm64_in_kdump_text_on_irq_stack(bt) ||
+ arm64_in_kdump_text_on_sdei_stack(bt))
bt->flags |= BT_KDUMP_ADJUST;
return TRUE;
@@ -3563,6 +3740,31 @@ arm64_in_alternate_stack(int cpu, ulong stkptr)
return FALSE;
}
+static int
+arm64_in_sdei_normal_stack(int cpu, ulong stkptr)
+{
+ struct machine_specific *ms = machdep->machspec;
+
+ if (!ms->sdei_stack_size || (cpu >= kt->cpus))
+ return FALSE;
+
+ if ((stkptr >= ms->sdei_stacks[cpu]) &&
+ (stkptr < (ms->sdei_stacks[cpu] + ms->sdei_stack_size)))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+arm64_set_sdei_normal_stack(struct bt_info *bt)
+{
+ struct machine_specific *ms = machdep->machspec;
+
+ bt->stackbase = ms->sdei_stacks[bt->tc->processor];
+ bt->stacktop = bt->stackbase + ms->sdei_stack_size;
+ alter_stackbuf(bt);
+}
+
static void
arm64_set_irq_stack(struct bt_info *bt)
{
diff --git a/defs.h b/defs.h
index d6492c5..ab25a27 100644
--- a/defs.h
+++ b/defs.h
@@ -3194,6 +3194,9 @@ struct machine_specific {
ulong irq_stack_size;
ulong *irq_stacks;
char *irq_stackbuf;
+ ulong sdei_stack_size;
+ ulong *sdei_stacks;
+ char *sdei_stackbuf;
ulong __irqentry_text_start;
ulong __irqentry_text_end;
/* for exception vector code */
--
2.19.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jlwwlsqc/crash.git
git@gitee.com:jlwwlsqc/crash.git
jlwwlsqc
crash
crash
master

搜索帮助