This value is used to mask the PAC bits and generate correct backtrace
and symbol name.
(amit.kachhap(a)arm.com)
---
Changes since v1:
* Moved PAC mask code from arm64_print_stackframe_entry to
arm64_unwind_frame.
* PAC mask check on all kernel text during complete stack parsing
with bt -t <pid> command.
* dump_machdep_table now prints CONFIG_ARM64_KERNELPACMASK.
The kernel version for the corresponding vmcoreinfo entry is posted here[1].
[1]:
https://lore.kernel.org/patchwork/patch/1211981/
arm64.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
defs.h | 1 +
2 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/arm64.c b/arm64.c
index 7662d71..326b8e0 100644
--- a/arm64.c
+++ b/arm64.c
@@ -84,6 +84,7 @@ static int arm64_get_kvaddr_ranges(struct vaddr_range *);
static void arm64_get_crash_notes(void);
static void arm64_calc_VA_BITS(void);
static int arm64_is_uvaddr(ulong, struct task_context *);
+static void arm64_calc_KERNELPACMASK(void);
/*
@@ -213,6 +214,7 @@ arm64_init(int when)
machdep->pagemask = ~((ulonglong)machdep->pageoffset);
arm64_calc_VA_BITS();
+ arm64_calc_KERNELPACMASK();
ms = machdep->machspec;
if (ms->VA_BITS_ACTUAL) {
ms->page_offset = ARM64_PAGE_OFFSET_ACTUAL;
@@ -472,6 +474,7 @@ arm64_init(int when)
case LOG_ONLY:
machdep->machspec = &arm64_machine_specific;
arm64_calc_VA_BITS();
+ arm64_calc_KERNELPACMASK();
arm64_calc_phys_offset();
machdep->machspec->page_offset = ARM64_PAGE_OFFSET;
break;
@@ -659,6 +662,11 @@ arm64_dump_machdep_table(ulong arg)
fprintf(fp, "%ld\n", ms->VA_BITS_ACTUAL);
else
fprintf(fp, "(unused)\n");
+ fprintf(fp, "CONFIG_ARM64_KERNELPACMASK: ");
+ if (ms->CONFIG_ARM64_KERNELPACMASK)
+ fprintf(fp, "%lx\n", ms->CONFIG_ARM64_KERNELPACMASK);
+ else
+ fprintf(fp, "(unused)\n");
fprintf(fp, " userspace_top: %016lx\n", ms->userspace_top);
fprintf(fp, " page_offset: %016lx\n", ms->page_offset);
fprintf(fp, " vmalloc_start_addr: %016lx\n", ms->vmalloc_start_addr);
@@ -1774,13 +1782,14 @@ static int
arm64_is_kernel_exception_frame(struct bt_info *bt, ulong stkptr)
{
struct arm64_pt_regs *regs;
+ struct machine_specific *ms = machdep->machspec;
regs = (struct arm64_pt_regs
*)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(stkptr))];
if (INSTACK(regs->sp, bt) && INSTACK(regs->regs[29], bt) &&
!(regs->pstate & (0xffffffff00000000ULL | PSR_MODE32_BIT)) &&
- is_kernel_text(regs->pc) &&
- is_kernel_text(regs->regs[30])) {
+ is_kernel_text(regs->pc | ms->CONFIG_ARM64_KERNELPACMASK) &&
+ is_kernel_text(regs->regs[30] | ms->CONFIG_ARM64_KERNELPACMASK)) {
switch (regs->pstate & PSR_MODE_MASK)
{
case PSR_MODE_EL1t:
@@ -1924,6 +1933,7 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct
arm64_stackfr
* See, for example, "bl schedule" before ret_to_user().
*/
branch_pc = frame->pc - 4;
+
name = closest_symbol(branch_pc);
name_plus_offset = NULL;
@@ -2135,7 +2145,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe
*frame)
unsigned long stack_mask;
unsigned long irq_stack_ptr, orig_sp;
struct arm64_pt_regs *ptregs;
- struct machine_specific *ms;
+ struct machine_specific *ms = machdep->machspec;
stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1;
fp = frame->fp;
@@ -2149,6 +2159,8 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe
*frame)
frame->sp = fp + 0x10;
frame->fp = GET_STACK_ULONG(fp);
frame->pc = GET_STACK_ULONG(fp + 8);
+ if (is_kernel_text(frame->pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ frame->pc |= ms->CONFIG_ARM64_KERNELPACMASK;
if ((frame->fp == 0) && (frame->pc == 0))
return FALSE;
@@ -2200,7 +2212,6 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe
*frame)
* irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id());
* orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); (pt_regs pointer on process
stack)
*/
- ms = machdep->machspec;
irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size -
16;
if (frame->sp == irq_stack_ptr) {
@@ -2802,6 +2813,8 @@ arm64_print_text_symbols(struct bt_info *bt, struct arm64_stackframe
*frame, FIL
char buf2[BUFSIZE];
char *name;
ulong start;
+ ulong val;
+ struct machine_specific *ms = machdep->machspec;
if (bt->flags & BT_TEXT_SYMBOLS_ALL)
start = bt->stackbase;
@@ -2816,8 +2829,10 @@ arm64_print_text_symbols(struct bt_info *bt, struct
arm64_stackframe *frame, FIL
for (i = (start - bt->stackbase)/sizeof(ulong); i < LONGS_PER_STACK; i++) {
up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]);
- if (is_kernel_text(*up)) {
- name = closest_symbol(*up);
+ val = *up;
+ if (is_kernel_text(val | ms->CONFIG_ARM64_KERNELPACMASK)) {
+ val |= ms->CONFIG_ARM64_KERNELPACMASK;
+ name = closest_symbol(val);
fprintf(ofp, " %s[%s] %s at %lx",
bt->flags & BT_ERROR_MASK ?
" " : "",
@@ -2826,13 +2841,13 @@ arm64_print_text_symbols(struct bt_info *bt, struct
arm64_stackframe *frame, FIL
MKSTR(bt->stackbase +
(i * sizeof(long)))),
bt->flags & BT_SYMBOL_OFFSET ?
- value_to_symstr(*up, buf2, bt->radix) :
- name, *up);
- if (module_symbol(*up, NULL, &lm, NULL, 0))
+ value_to_symstr(val, buf2, bt->radix) :
+ name, val);
+ if (module_symbol(val, NULL, &lm, NULL, 0))
fprintf(ofp, " [%s]", lm->mod_name);
fprintf(ofp, "\n");
if (BT_REFERENCE_CHECK(bt))
- arm64_do_bt_reference_check(bt, *up, name);
+ arm64_do_bt_reference_check(bt, val, name);
}
}
}
@@ -3135,6 +3150,7 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int
mode, FILE *o
struct syment *sp;
ulong LR, SP, offset;
char buf[BUFSIZE];
+ struct machine_specific *ms = machdep->machspec;
if (CRASHDEBUG(1))
fprintf(ofp, "pt_regs: %lx\n", pt_regs);
@@ -3150,6 +3166,8 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int
mode, FILE *o
rows = 4;
} else {
LR = regs->regs[30];
+ if (is_kernel_text (LR | ms->CONFIG_ARM64_KERNELPACMASK))
+ LR |= ms->CONFIG_ARM64_KERNELPACMASK;
SP = regs->sp;
top_reg = 29;
is_64_bit = TRUE;
@@ -4058,6 +4076,20 @@ arm64_swp_offset(ulong pte)
return pte;
}
+static void arm64_calc_KERNELPACMASK(void)
+{
+ ulong value;
+ char *string;
+
+ if ((string = pc->read_vmcoreinfo("NUMBER(KERNELPACMASK)"))) {
+ value = htol(string, QUIET, NULL);
+ free(string);
+ machdep->machspec->CONFIG_ARM64_KERNELPACMASK = value;
+ if (CRASHDEBUG(1))
+ fprintf(fp, "CONFIG_ARM64_KERNELPACMASK=%lx\n", value);
+ }
+}
+
#endif /* ARM64 */
diff --git a/defs.h b/defs.h
index ac24a5d..4c3e509 100644
--- a/defs.h
+++ b/defs.h
@@ -3263,6 +3263,7 @@ struct machine_specific {
ulong machine_kexec_end;
ulong VA_BITS_ACTUAL;
ulong CONFIG_ARM64_VA_BITS;
+ ulong CONFIG_ARM64_KERNELPACMASK;
ulong VA_START;
};
--
2.17.1