fix seek error IRQ stack pointer

This commit is contained in:
zhouwenpei 2021-12-30 17:22:50 +08:00
parent c10dc6cb03
commit 6cef8b237f
6 changed files with 373 additions and 371 deletions

View File

@ -0,0 +1,61 @@
From 5719afc7a40868418405a87a2711088556e68a3b Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Fri, 2 Jul 2021 10:14:21 +0800
Subject: [PATCH 13/16] arm64: rename ARM64_PAGE_OFFSET_ACTUAL to
ARM64_FLIP_PAGE_OFFSET_ACTUAL
Reflect the flipped layout of kernel VA, which is introduced by
kernel commit 14c127c957c1 ("arm64: mm: Flip kernel VA space").
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
arm64.c | 10 ++++++----
defs.h | 3 ++-
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/arm64.c b/arm64.c
index 8934961b109d..9fe1a4a3bddb 100644
--- a/arm64.c
+++ b/arm64.c
@@ -217,10 +217,12 @@ arm64_init(int when)
arm64_calc_VA_BITS();
arm64_calc_KERNELPACMASK();
ms = machdep->machspec;
+
+ /* vabits_actual introduced after mm flip, so it should be flipped layout */
if (ms->VA_BITS_ACTUAL) {
- ms->page_offset = ARM64_PAGE_OFFSET_ACTUAL;
- machdep->identity_map_base = ARM64_PAGE_OFFSET_ACTUAL;
- machdep->kvbase = ARM64_PAGE_OFFSET_ACTUAL;
+ ms->page_offset = ARM64_FLIP_PAGE_OFFSET_ACTUAL;
+ machdep->identity_map_base = ARM64_FLIP_PAGE_OFFSET_ACTUAL;
+ machdep->kvbase = ARM64_FLIP_PAGE_OFFSET_ACTUAL;
ms->userspace_top = ARM64_USERSPACE_TOP_ACTUAL;
} else {
ms->page_offset = ARM64_PAGE_OFFSET;
@@ -401,7 +403,7 @@ arm64_init(int when)
fprintf(fp, "CONFIG_ARM64_VA_BITS: %ld\n", ms->CONFIG_ARM64_VA_BITS);
fprintf(fp, " VA_BITS_ACTUAL: %ld\n", ms->VA_BITS_ACTUAL);
fprintf(fp, "(calculated) VA_BITS: %ld\n", ms->VA_BITS);
- fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_PAGE_OFFSET_ACTUAL);
+ fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_FLIP_PAGE_OFFSET_ACTUAL);
fprintf(fp, " VA_START: %lx\n", ms->VA_START);
fprintf(fp, " modules: %lx - %lx\n", ms->modules_vaddr, ms->modules_end);
fprintf(fp, " vmalloc: %lx - %lx\n", ms->vmalloc_start_addr, ms->vmalloc_end);
diff --git a/defs.h b/defs.h
index 5d32954905c2..eb7ce6aea331 100644
--- a/defs.h
+++ b/defs.h
@@ -3233,7 +3233,8 @@ typedef signed int s32;
#define ARM64_PAGE_OFFSET ((0xffffffffffffffffUL) \
<< (machdep->machspec->VA_BITS - 1))
-#define ARM64_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \
+/* kernels >= v5.4 the kernel VA space is flipped */
+#define ARM64_FLIP_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \
- ((1UL) << machdep->machspec->VA_BITS_ACTUAL) + 1)
#define ARM64_USERSPACE_TOP ((1UL) << machdep->machspec->VA_BITS)
--
2.30.2

View File

@ -0,0 +1,56 @@
From 167d37e347fe35c6f7db826e8539e192c4375564 Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Fri, 2 Jul 2021 10:14:22 +0800
Subject: [PATCH 14/16] arm64: assign page_offset with VA_BITS kernel
configuration value
On RHEL9, crash hits a bug when executing "crash /proc/kcore":
seek error: kernel virtual address: ffff6a0f3fff0000 type: "pmd page"
The kernel virtual address does not vary with vabits_actual, instead,
is determined by configuration value. But crash does not observe this
fact.
Since vabits_actual related kernel commit is introduced after arm64
mm layout flip commit, so changes are safe under the condition if
(ms->VA_BITS_ACTUAL), and keep the else branch untouched.
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
arm64.c | 7 ++++---
defs.h | 1 +
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arm64.c b/arm64.c
index 9fe1a4a3bddb..149db36cd119 100644
--- a/arm64.c
+++ b/arm64.c
@@ -220,9 +220,10 @@ arm64_init(int when)
/* vabits_actual introduced after mm flip, so it should be flipped layout */
if (ms->VA_BITS_ACTUAL) {
- ms->page_offset = ARM64_FLIP_PAGE_OFFSET_ACTUAL;
- machdep->identity_map_base = ARM64_FLIP_PAGE_OFFSET_ACTUAL;
- machdep->kvbase = ARM64_FLIP_PAGE_OFFSET_ACTUAL;
+ ms->page_offset = ARM64_FLIP_PAGE_OFFSET;
+ /* useless on arm64 */
+ machdep->identity_map_base = ARM64_FLIP_PAGE_OFFSET;
+ machdep->kvbase = ARM64_FLIP_PAGE_OFFSET;
ms->userspace_top = ARM64_USERSPACE_TOP_ACTUAL;
} else {
ms->page_offset = ARM64_PAGE_OFFSET;
diff --git a/defs.h b/defs.h
index eb7ce6aea331..b7b20af4bcf9 100644
--- a/defs.h
+++ b/defs.h
@@ -3234,6 +3234,7 @@ typedef signed int s32;
#define ARM64_PAGE_OFFSET ((0xffffffffffffffffUL) \
<< (machdep->machspec->VA_BITS - 1))
/* kernels >= v5.4 the kernel VA space is flipped */
+#define ARM64_FLIP_PAGE_OFFSET (-(1UL) << machdep->machspec->CONFIG_ARM64_VA_BITS)
#define ARM64_FLIP_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \
- ((1UL) << machdep->machspec->VA_BITS_ACTUAL) + 1)
--
2.30.2

View File

@ -0,0 +1,83 @@
From bf1379a8b6ff8d6a8fa12978f7194f15f85c4380 Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Fri, 2 Jul 2021 10:14:23 +0800
Subject: [PATCH 15/16] arm64: use dedicated bits to record the VA space layout
changes
arm64 memory layout experiences big changes due to the following kernel
commits in date descending order:
5. 7bc1a0f9e176 arm64: mm: use single quantity to represent the PA to VA translation
4. b6d00d47e81a arm64: mm: Introduce 52-bit Kernel VAs
3. 5383cc6efed1 arm64: mm: Introduce vabits_actual
2. 14c127c957c1 arm64: mm: Flip kernel VA space
1. f80fb3a3d508 arm64: add support for kernel ASLR
For 1, crash has already used NEW_VMEMMAP to trace it.
For 2, crash lacks a flag to tag it and handle it differently.
For 3, two important kernel variables vabits_actual and physvirt_offset
are introduced.
For 4, since it comes immediately after 3, crash-utility does not need
to distinguish it.
For 5, kernel variable phyvirt_offset is removed
These changes have effects on PTOV()/VTOP() formula. So introducing
two bits HAS_PHYSVIRT_OFFSET and FLIPPED_VM as hint to apply different
formula.
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
arm64.c | 10 ++++++++++
defs.h | 2 ++
2 files changed, 12 insertions(+)
diff --git a/arm64.c b/arm64.c
index 149db36cd119..b04369f6d4d8 100644
--- a/arm64.c
+++ b/arm64.c
@@ -563,6 +563,10 @@ arm64_dump_machdep_table(ulong arg)
fprintf(fp, "%sMACHDEP_BT_TEXT", others++ ? "|" : "");
if (machdep->flags & NEW_VMEMMAP)
fprintf(fp, "%sNEW_VMEMMAP", others++ ? "|" : "");
+ if (machdep->flags & FLIPPED_VM)
+ fprintf(fp, "%sFLIPPED_VM", others++ ? "|" : "");
+ if (machdep->flags & HAS_PHYSVIRT_OFFSET)
+ fprintf(fp, "%sHAS_PHYSVIRT_OFFSET", others++ ? "|" : "");
fprintf(fp, ")\n");
fprintf(fp, " kvbase: %lx\n", machdep->kvbase);
@@ -997,6 +1001,7 @@ arm64_calc_physvirt_offset(void)
if (READMEM(pc->mfd, &physvirt_offset, sizeof(physvirt_offset),
sp->value, sp->value -
machdep->machspec->kimage_voffset) > 0) {
+ machdep->flags |= HAS_PHYSVIRT_OFFSET;
ms->physvirt_offset = physvirt_offset;
}
}
@@ -3963,6 +3968,11 @@ arm64_calc_VA_BITS(void)
error(FATAL, "cannot determine VA_BITS_ACTUAL\n");
}
+ /*
+ * The mm flip commit is introduced before 52-bits VA, which is before the
+ * commit to export NUMBER(TCR_EL1_T1SZ)
+ */
+ machdep->flags |= FLIPPED_VM;
return;
}
diff --git a/defs.h b/defs.h
index b7b20af4bcf9..eca145cb881c 100644
--- a/defs.h
+++ b/defs.h
@@ -3214,6 +3214,8 @@ typedef signed int s32;
#define NEW_VMEMMAP (0x80)
#define VM_L4_4K (0x100)
#define UNW_4_14 (0x200)
+#define FLIPPED_VM (0x400)
+#define HAS_PHYSVIRT_OFFSET (0x800)
/*
* Get kimage_voffset from /dev/crash
--
2.30.2

View File

@ -0,0 +1,165 @@
From f53b73e8380bca054cebd2b61ff118c46609429b Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Fri, 2 Jul 2021 10:14:24 +0800
Subject: [PATCH 16/16] arm64: implement switchable PTOV()/VTOP() for kernels
>= 5.10
Crash encounters a bug like the following:
...
SECTION_SIZE_BITS: 30
CONFIG_ARM64_VA_BITS: 52
VA_BITS_ACTUAL: 48
(calculated) VA_BITS: 48
PAGE_OFFSET: ffff000000000000
VA_START: ffff800000000000
modules: ffff800008000000 - ffff80000fffffff
vmalloc: ffff800010000000 - ffffffdfdffeffff
kernel image: ffff800010000000 - ffff800012750000
vmemmap: ffffffdfffe00000 - ffffffffffffffff
<readmem: ffff800011c53bc8, KVADDR, "nr_irqs", 4, (FOE), b47bdc>
<read_kdump: addr: ffff800011c53bc8 paddr: eb453bc8 cnt: 4>
read_netdump: addr: ffff800011c53bc8 paddr: eb453bc8 cnt: 4 offset: 1c73bc8
irq_stack_ptr:
type: 1, TYPE_CODE_PTR
target_typecode: 8, TYPE_CODE_INT
target_length: 8
length: 8
GNU_GET_DATATYPE[thread_union]: returned via gdb_error_hook
<readmem: ffff000b779c0050, KVADDR, "IRQ stack pointer", 8, (ROE), 3a37bea0>
<read_kdump: addr: ffff000b779c0050 paddr: fff1000bf79c0050 cnt: 8>
read_netdump: READ_ERROR: offset not found for paddr: fff1000bf79c0050
crash: read error: kernel virtual address: ffff000b779c0050 type: "IRQ stack pointer"
...
Apparently, for a normal system, the 'paddr: fff1000bf79c0050' is
unreasonable.
This bug connects with kernel commit 7bc1a0f9e176 ("arm64: mm: use
single quantity to represent the PA to VA translation"), which removed
physvirt_offset kernel variable and changed the PTOV()/VTOP() formulas.
Implement switchable PTOV()/VTOP() to cope with different kernel
version.
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
arm64.c | 37 +++++++++++++++++++++++++++++++++----
defs.h | 9 ++++-----
2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/arm64.c b/arm64.c
index b04369f6d4d8..d73d5c5a4fed 100644
--- a/arm64.c
+++ b/arm64.c
@@ -994,8 +994,6 @@ arm64_calc_physvirt_offset(void)
ulong physvirt_offset;
struct syment *sp;
- ms->physvirt_offset = ms->phys_offset - ms->page_offset;
-
if ((sp = kernel_symbol_search("physvirt_offset")) &&
machdep->machspec->kimage_voffset) {
if (READMEM(pc->mfd, &physvirt_offset, sizeof(physvirt_offset),
@@ -1003,8 +1001,13 @@ arm64_calc_physvirt_offset(void)
machdep->machspec->kimage_voffset) > 0) {
machdep->flags |= HAS_PHYSVIRT_OFFSET;
ms->physvirt_offset = physvirt_offset;
+ return;
}
}
+
+ /* Useless if no symbol 'physvirt_offset', just keep semantics */
+ ms->physvirt_offset = ms->phys_offset - ms->page_offset;
+
}
static void
@@ -1051,6 +1054,7 @@ arm64_calc_phys_offset(void)
if (READMEM(pc->mfd, &phys_offset, sizeof(phys_offset),
vaddr, paddr) > 0) {
ms->phys_offset = phys_offset;
+
return;
}
}
@@ -1178,6 +1182,21 @@ arm64_init_kernel_pgd(void)
vt->kernel_pgd[i] = value;
}
+ulong arm64_PTOV(ulong paddr)
+{
+ struct machine_specific *ms = machdep->machspec;
+
+ /*
+ * Either older kernel before kernel has 'physvirt_offset' or newer
+ * kernel which removes 'physvirt_offset' has the same formula:
+ * #define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
+ */
+ if (!(machdep->flags & HAS_PHYSVIRT_OFFSET))
+ return (paddr - ms->phys_offset) | PAGE_OFFSET;
+ else
+ return paddr - ms->physvirt_offset;
+}
+
ulong
arm64_VTOP(ulong addr)
{
@@ -1188,8 +1207,18 @@ arm64_VTOP(ulong addr)
return addr - machdep->machspec->kimage_voffset;
}
- if (addr >= machdep->machspec->page_offset)
- return addr + machdep->machspec->physvirt_offset;
+ if (addr >= machdep->machspec->page_offset) {
+ if (machdep->flags & HAS_PHYSVIRT_OFFSET) {
+ return addr + machdep->machspec->physvirt_offset;
+ } else {
+ /*
+ * Either older kernel before kernel has 'physvirt_offset' or newer
+ * kernel which removes 'physvirt_offset' has the same formula:
+ * #define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
+ */
+ return (addr & ~PAGE_OFFSET) + machdep->machspec->phys_offset;
+ }
+ }
else if (machdep->machspec->kimage_voffset)
return addr - machdep->machspec->kimage_voffset;
else /* no randomness */
diff --git a/defs.h b/defs.h
index eca145cb881c..c91177a245fd 100644
--- a/defs.h
+++ b/defs.h
@@ -3092,11 +3092,6 @@ typedef u64 pte_t;
#define _64BIT_
#define MACHINE_TYPE "ARM64"
-#define PTOV(X) \
- ((unsigned long)(X) - (machdep->machspec->physvirt_offset))
-
-#define VTOP(X) arm64_VTOP((ulong)(X))
-
#define USERSPACE_TOP (machdep->machspec->userspace_top)
#define PAGE_OFFSET (machdep->machspec->page_offset)
#define VMALLOC_START (machdep->machspec->vmalloc_start_addr)
@@ -3106,6 +3101,9 @@ typedef u64 pte_t;
#define MODULES_VADDR (machdep->machspec->modules_vaddr)
#define MODULES_END (machdep->machspec->modules_end)
+#define PTOV(X) arm64_PTOV((ulong)(X))
+#define VTOP(X) arm64_VTOP((ulong)(X))
+
#define IS_VMALLOC_ADDR(X) arm64_IS_VMALLOC_ADDR((ulong)(X))
#define PAGEBASE(X) (((ulong)(X)) & (ulong)machdep->pagemask)
@@ -5910,6 +5908,7 @@ void unwind_backtrace(struct bt_info *);
void arm64_init(int);
void arm64_dump_machdep_table(ulong);
ulong arm64_VTOP(ulong);
+ulong arm64_PTOV(ulong);
int arm64_IS_VMALLOC_ADDR(ulong);
ulong arm64_swp_type(ulong);
ulong arm64_swp_offset(ulong);
--
2.30.2

View File

@ -1,368 +0,0 @@
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 fdf77bd..cc32d9d 100644
--- a/arm64.c
+++ b/arm64.c
@@ -87,6 +87,10 @@ static void arm64_calc_VA_BITS(void);
static int arm64_is_uvaddr(ulong, struct task_context *);
static void arm64_calc_KERNELPACMASK(void);
+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
@@ -461,6 +465,7 @@ arm64_init(int when)
arm64_irq_stack_init();
arm64_stackframe_init();
+ arm64_sdei_stack_init();
break;
case POST_VM:
@@ -1655,6 +1660,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);
+ }
}
}
@@ -2173,7 +2242,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 = machdep->machspec;
@@ -2203,7 +2272,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);
@@ -2243,6 +2313,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
* orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); (pt_regs pointer on process stack)
*/
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);
@@ -2263,6 +2334,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;
@@ -2602,6 +2692,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;
@@ -2611,6 +2705,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);
@@ -2621,6 +2719,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;
@@ -2682,7 +2784,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;
@@ -2965,6 +3068,81 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame)
}
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;
+ if (!ms->sdei_stacks)
+ return FALSE;
+ 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)
{
int cpu;
@@ -3111,7 +3287,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;
@@ -3804,6 +3981,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 9594950..9cd5ffa 100644
--- a/defs.h
+++ b/defs.h
@@ -3283,6 +3283,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.13.7

View File

@ -1,6 +1,6 @@
Name: crash
Version: 7.3.0
Release: 1
Release: 2
Summary: Linux kernel crash utility.
License: GPLv3
URL: https://crash-utility.github.io
@ -9,8 +9,10 @@ Source1: http://ftp.gnu.org/gnu/gdb/gdb-7.6.tar.gz
Patch0: lzo_snappy.patch
Patch1: use_system_readline_v3.patch
Patch9000: add-SDEI-stack-resolution.patch
Patch2: 0001-arm64-rename-ARM64_PAGE_OFFSET_ACTUAL-to-ARM64_FLIP_.patch
Patch3: 0002-arm64-assign-page_offset-with-VA_BITS-kernel-configu.patch
Patch4: 0003-arm64-use-dedicated-bits-to-record-the-VA-space-layo.patch
Patch5: 0004-arm64-implement-switchable-PTOV-VTOP-for-kernels-5.1.patch
BuildRequires: ncurses-devel zlib-devel lzo-devel snappy-devel
BuildRequires: gcc gcc-c++ bison readline-devel m4
@ -76,6 +78,9 @@ install -D -m 0644 defs.h %{buildroot}%{_includedir}/%{name}/defs.h
%{_mandir}/man8/crash.8*
%changelog
* Thu Dec 30 2021 zhouwenpei <zhouwenpei1@huawei.com> - 7.3.0-2
- fix seek error "IRQ stack pointer"
* Tue Nov 30 2021 zhouwenpei <zhouwenpei1@huawei.com> - 7.3.0-1
- Upgrade version to 7.3.0