代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/crash 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
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
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。