arm64: Changes to register and stack dumps
cover arm64: Changes to register and stack dumps
Hi all,
This handful of patches makes some significant changes to how we print register/stack dumps and brings us inline with recent changes to x86. The main changes are that we no longer print out the 'Exception stack:' section and PC/LR values are resolved to a symbol+offset format where possible.
Feedback welcome.
Will
--->8
Mark Rutland (1):
arm64: consistently log ESR and page table
Will Deacon (3):
arm64: traps: Don't print stack or raw PC/LR values in backtraces
arm64: traps: Pretty-print pstate in register dumps
arm64: uapi: Remove PSR_Q_BIT
arch/arm64/include/uapi/asm/ptrace.h | 1 - arch/arm64/kernel/process.c | 24 ++++++++++--- arch/arm64/kernel/traps.c | 65 ++---------------------------------- arch/arm64/mm/fault.c | 7 ++-- 4 files changed, 28 insertions(+), 69 deletions(-)
Signature · 1 line
2.1.4
PATCH 1/4 arm64: consistently log ESR and page table
From: Mark Rutland <[email protected]>
When we take a fault we can't handle, we try to dump some relevant information, but we're not consistent about doing so.
In do_mem_abort(), we log the full ESR, but don't dump a page table walk. In __do_kernel_fault, we dump an attempted decoding of the ESR (but not the ESR itself) along with a page table walk.
Let's try to make things more consistent by dumping the full ESR in mem_abort_decode(), and having do_mem_abort dump a page table walk. The existing dump of the ESR in do_mem_abort() is rendered redundant, and removed.
--- arch/arm64/mm/fault.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
arch/arm64/mm/fault.c +5 -2
@@ -112,6 +112,7 @@ static void mem_abort_decode(unsigned int esr) {pr_alert ("Mem abort info:\n" ); +pr_alert (" ESR = 0x%08x\n" , esr);pr_alert (" Exception class = %s, IL = %u bits\n" ,esr_get_class_string (esr), (esr & ESR_ELx_IL) ?32 :16 );
@@ -745,11 +746,13 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,if (!inf->fn (addr, esr, regs))return ; -pr_alert ("Unhandled fault: %s (0x%08x) at 0x%016lx\n" , - inf->name, esr, addr); +pr_alert ("Unhandled fault: %s at 0x%016lx\n" , + inf->name, addr);mem_abort_decode (esr); +show_pte (addr); + info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
Signature · 1 line
2.1.4
PATCH 2/4 arm64: traps: Don't print stack or raw PC/LR values in backtraces
In reply to Will DeaconPrinting raw pointer values in backtraces has potential security implications and are of questionable value anyway.
This patch follows x86's lead and removes the "Exception stack:" dump from kernel backtraces, as well as converting PC/LR values to symbols such as "sysrq_handle_crash+0x20/0x30".
--- arch/arm64/kernel/process.c | 8 +++--- arch/arm64/kernel/traps.c | 65 +++------------------------------------------ 2 files changed, 6 insertions(+), 67 deletions(-)
arch/arm64/kernel/process.c +3 -5
@@ -186,11 +186,9 @@ void __show_regs(struct pt_regs *regs) }show_regs_print_info (KERN_DEFAULT ); -print_symbol ("PC is at %s\n" ,instruction_pointer (regs)); -print_symbol ("LR is at %s\n" , lr); -printk ("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n" , - regs->pc, lr, regs->pstate); -printk ("sp : %016llx\n" , sp); +print_symbol ("pc : %s\n" , regs->pc); +print_symbol ("lr : %s\n" , lr); +printk ("sp : %016llx pstate : %08llx\n" , sp, regs->pstate); i = top_reg;
arch/arm64/kernel/traps.c +3 -62
85 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH 3/4 arm64: traps: Pretty-print pstate in register dumps
In reply to Will DeaconWe can decode the PSTATE easily enough, so pretty-print it in register dumps.
--- arch/arm64/kernel/process.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
arch/arm64/kernel/process.c +19 -1
@@ -170,6 +170,23 @@ void machine_restart(char *cmd)while (1 ); } +static void print_pstate (struct pt_regs *regs) +{ +u64 pstate = regs->pstate; +printk ("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO)\n" , + pstate, + pstate &PSR_N_BIT ?'N' :'n' , + pstate &PSR_Z_BIT ?'Z' :'z' , + pstate &PSR_C_BIT ?'C' :'c' , + pstate &PSR_V_BIT ?'V' :'v' , + pstate &PSR_D_BIT ?'D' :'d' , + pstate &PSR_A_BIT ?'A' :'a' , + pstate &PSR_I_BIT ?'I' :'i' , + pstate &PSR_F_BIT ?'F' :'f' , + pstate &PSR_PAN_BIT ?'+' :'-' , + pstate &PSR_UAO_BIT ?'+' :'-' ); +} +void __show_regs (struct pt_regs *regs) {int i, top_reg;
@@ -186,9 +203,10 @@ void __show_regs(struct pt_regs *regs) }show_regs_print_info (KERN_DEFAULT ); +print_pstate (regs);print_symbol ("pc : %s\n" , regs->pc);print_symbol ("lr : %s\n" , lr); -printk ("sp : %016llx pstate : %08llx\n" , sp, regs->pstate); +printk ("sp : %016llx\n" , sp); i = top_reg;
Signature · 1 line
2.1.4
Mark Rutland
reviewerPATCH 3/4 arm64: traps: Pretty-print pstate in register dumps
Quoted 22 lines · Will Deacon
We can decode the PSTATE easily enough, so pretty-print it in register dumps.
Signed-off-by Will Deacon <[email protected]>--- arch/arm64/kernel/process.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)arch/arm64/kernel/process.c +6
-0@@ -170,6 +170,23 @@ void machine_restart(char *cmd)while (1 ); } +static void print_pstate (struct pt_regs *regs) +{ +u64 pstate = regs->pstate; + printk("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO)\n", + pstate, + pstate & PSR_N_BIT ? 'N' : 'n',
arch/arm64/kernel/process.c void machine_restart(char *cmd) · line 188
Quoted 10 lines
arch/arm64/kernel/process.c +10
-0+ pstate &PSR_Z_BIT ?'Z' :'z' , + pstate &PSR_C_BIT ?'C' :'c' , + pstate &PSR_V_BIT ?'V' :'v' , + pstate &PSR_D_BIT ?'D' :'d' , + pstate &PSR_A_BIT ?'A' :'a' , + pstate &PSR_I_BIT ?'I' :'i' , + pstate &PSR_F_BIT ?'F' :'f' , + pstate &PSR_PAN_BIT ?'+' :'-' , + pstate & PSR_UAO_BIT ? '+' : '-'); +}
Given we use __show_regs for user state, I think we need to check compat_user_mode() regs, and adjust the decoding accordingly.
e.g. AArch32 has an E bit where the D in DAIF is.
Thanks,
Mark.
Quoted 19 lines
arch/arm64/kernel/process.c +3
-1+void __show_regs (struct pt_regs *regs) {int i, top_reg;@@ -186,9 +203,10 @@ void __show_regs(struct pt_regs *regs) }show_regs_print_info (KERN_DEFAULT ); +print_pstate (regs);print_symbol ("pc : %s\n" , regs->pc);print_symbol ("lr : %s\n" , lr); -printk ("sp : %016llx pstate : %08llx\n" , sp, regs->pstate); +printk ("sp : %016llx\n" , sp); i = top_reg;Signature · 1 line
2.1.4
PATCH 3/4 arm64: traps: Pretty-print pstate in register dumps
Quoted 37 lines · Mark Rutland
Quoted 22 lines · Will Deacon
We can decode the PSTATE easily enough, so pretty-print it in register dumps.
Signed-off-by Will Deacon <[email protected]>--- arch/arm64/kernel/process.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)arch/arm64/kernel/process.c +6
-0@@ -170,6 +170,23 @@ void machine_restart(char *cmd)while (1 ); } +static void print_pstate (struct pt_regs *regs) +{ +u64 pstate = regs->pstate; + printk("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO)\n", + pstate, + pstate & PSR_N_BIT ? 'N' : 'n',arch/arm64/kernel/process.c void machine_restart(char *cmd) · line 188
Quoted 10 lines
arch/arm64/kernel/process.c +10
-0+ pstate &PSR_Z_BIT ?'Z' :'z' , + pstate &PSR_C_BIT ?'C' :'c' , + pstate &PSR_V_BIT ?'V' :'v' , + pstate &PSR_D_BIT ?'D' :'d' , + pstate &PSR_A_BIT ?'A' :'a' , + pstate &PSR_I_BIT ?'I' :'i' , + pstate &PSR_F_BIT ?'F' :'f' , + pstate &PSR_PAN_BIT ?'+' :'-' , + pstate & PSR_UAO_BIT ? '+' : '-'); +}Given we use
__show_regsfor user state, I think we need to checkcompat_user_mode()regs, and adjust the decoding accordingly.
Quoted 1 line
e.g. AArch32 has an E bit where the D in DAIF is.
Yes, you're right. There's lots of exciting bits in the AArch32 pstate too. I ended up with the diff below.
Will
--->8
+static void print_pstate(struct pt_regs *regs)
+{
+ u64 pstate = regs->pstate;
+
+ if (compat_user_mode(regs))
+ printk("pstate: %08llx (%c%c%c%c %c %s %s-endian %c%c%c)\n",
+ pstate,
+ pstate & COMPAT_PSR_N_BIT ? 'N' : 'n',
+ pstate & COMPAT_PSR_Z_BIT ? 'Z' : 'z',
+ pstate & COMPAT_PSR_C_BIT ? 'C' : 'c',
+ pstate & COMPAT_PSR_V_BIT ? 'V' : 'v',
+ pstate & COMPAT_PSR_Q_BIT ? 'Q' : 'q',
+ pstate & COMPAT_PSR_T_BIT ? "T32" : "A32",
+ pstate & COMPAT_PSR_E_BIT ? "big" : "little",
+ pstate & COMPAT_PSR_A_BIT ? 'A' : 'a',
+ pstate & COMPAT_PSR_I_BIT ? 'I' : 'i',
+ pstate & COMPAT_PSR_F_BIT ? 'F' : 'f');
+ else
+ printk("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO)\n",
+ pstate,
+ pstate & PSR_N_BIT ? 'N' : 'n',
+ pstate & PSR_Z_BIT ? 'Z' : 'z',
+ pstate & PSR_C_BIT ? 'C' : 'c',
+ pstate & PSR_V_BIT ? 'V' : 'v',
+ pstate & PSR_D_BIT ? 'D' : 'd',
+ pstate & PSR_A_BIT ? 'A' : 'a',
+ pstate & PSR_I_BIT ? 'I' : 'i',
+ pstate & PSR_F_BIT ? 'F' : 'f',
+ pstate & PSR_PAN_BIT ? '+' : '-',
+ pstate & PSR_UAO_BIT ? '+' : '-');
+}
Mark Rutland
reviewerPATCH 3/4 arm64: traps: Pretty-print pstate in register dumps
Quoted 51 lines · Will Deacon
Quoted 37 lines · Mark Rutland
Quoted 22 lines · Will Deacon
We can decode the PSTATE easily enough, so pretty-print it in register dumps.
Signed-off-by Will Deacon <[email protected]>--- arch/arm64/kernel/process.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)arch/arm64/kernel/process.c +6
-0@@ -170,6 +170,23 @@ void machine_restart(char *cmd)while (1 ); } +static void print_pstate (struct pt_regs *regs) +{ +u64 pstate = regs->pstate; + printk("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO)\n", + pstate, + pstate & PSR_N_BIT ? 'N' : 'n',arch/arm64/kernel/process.c void machine_restart(char *cmd) · line 188
Quoted 10 lines
arch/arm64/kernel/process.c +10
-0+ pstate &PSR_Z_BIT ?'Z' :'z' , + pstate &PSR_C_BIT ?'C' :'c' , + pstate &PSR_V_BIT ?'V' :'v' , + pstate &PSR_D_BIT ?'D' :'d' , + pstate &PSR_A_BIT ?'A' :'a' , + pstate &PSR_I_BIT ?'I' :'i' , + pstate &PSR_F_BIT ?'F' :'f' , + pstate &PSR_PAN_BIT ?'+' :'-' , + pstate & PSR_UAO_BIT ? '+' : '-'); +}Given we use
__show_regsfor user state, I think we need to checkcompat_user_mode()regs, and adjust the decoding accordingly.Quoted 1 line
e.g. AArch32 has an E bit where the D in DAIF is.
Yes, you're right. There's lots of exciting bits in the AArch32 pstate too. I ended up with the diff below.
Will
--->8
(quoted diff) +4
-0+static void print_pstate(struct pt_regs *regs) +{ + u64 pstate = regs->pstate; +
Review
Quoted 10 lines
(quoted diff) +10
-0+ if (compat_user_mode(regs)) + printk("pstate: %08llx (%c%c%c%c %c %s %s-endian %c%c%c)\n", + pstate, + pstate & COMPAT_PSR_N_BIT ? 'N' : 'n', + pstate & COMPAT_PSR_Z_BIT ? 'Z' : 'z', + pstate & COMPAT_PSR_C_BIT ? 'C' : 'c', + pstate & COMPAT_PSR_V_BIT ? 'V' : 'v', + pstate & COMPAT_PSR_Q_BIT ? 'Q' : 'q', + pstate & COMPAT_PSR_T_BIT ? "T32" : "A32", + pstate & COMPAT_PSR_E_BIT ? "big" : "little",
We could say BE/LE for these so as to keep the line short.
Review
Quoted 4 lines
(quoted diff) +4
-0+ pstate & COMPAT_PSR_A_BIT ? 'A' : 'a', + pstate & COMPAT_PSR_I_BIT ? 'I' : 'i', + pstate & COMPAT_PSR_F_BIT ? 'F' : 'f'); + else
Given the either side of the if-else is several lines, could we add braces for clarity?
arch/arm64/kernel/process.c void machine_restart(char *cmd) · line 188
Quoted 13 lines
arch/arm64/kernel/process.c +13
-0+printk ("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO)\n" , + pstate, + pstate &PSR_N_BIT ?'N' :'n' , + pstate &PSR_Z_BIT ?'Z' :'z' , + pstate &PSR_C_BIT ?'C' :'c' , + pstate &PSR_V_BIT ?'V' :'v' , + pstate &PSR_D_BIT ?'D' :'d' , + pstate &PSR_A_BIT ?'A' :'a' , + pstate &PSR_I_BIT ?'I' :'i' , + pstate &PSR_F_BIT ?'F' :'f' , + pstate &PSR_PAN_BIT ?'+' :'-' , + pstate &PSR_UAO_BIT ?'+' :'-' ); +}
Otherwise, looks good!
Thanks,
Mark.
PATCH 4/4 arm64: uapi: Remove PSR_Q_BIT
In reply to Will DeaconPSTATE.Q only exists for AArch32, which can be referred to using COMPAT_PSR_Q_BIT. Remove PSR_Q_BIT, since the native bit doesn't exist in the architecture
--- arch/arm64/include/uapi/asm/ptrace.h | 1 - 1 file changed, 1 deletion(-)
arch/arm64/include/uapi/asm/ptrace.h +0 -1
@@ -46,7 +46,6 @@#define PSR_D_BIT 0x00000200#define PSR_PAN_BIT 0x00400000#define PSR_UAO_BIT 0x00800000 -#define PSR_Q_BIT 0x08000000#define PSR_V_BIT 0x10000000#define PSR_C_BIT 0x20000000#define PSR_Z_BIT 0x40000000
Signature · 1 line
2.1.4
cover arm64: Changes to register and stack dumps
In reply to Will DeaconQuoted 10 lines · Will Deacon
Hi all,
This handful of patches makes some significant changes to how we print register/stack dumps and brings us inline with recent changes to x86. The main changes are that we no longer print out the 'Exception stack:' section and PC/LR values are resolved to a symbol+offset format where possible.
Feedback welcome.
In very petty complaints, I can no longer just use the PC/LR with addr2line. Yes I can use gdb or one of the scripts but that's a few more steps when I'm doing debugging on my own. Like I said, very minor and overall this is good for both security and alignment.
I ran this through several of the LKDTM tests and the backtraces looked fine. You're welcome to add
Quoted 18 lines
Will
--->8
Mark Rutland (1):
arm64: consistently log ESR and page tableWill Deacon (3):
arm64: traps: Don't print stack or raw PC/LR values in backtraces
arm64: traps: Pretty-print pstate in register dumps
arm64: uapi: RemovePSR_Q_BITarch/arm64/include/uapi/asm/ptrace.h | 1 - arch/arm64/kernel/process.c | 24 ++++++++++--- arch/arm64/kernel/traps.c | 65 ++---------------------------------- arch/arm64/mm/fault.c | 7 ++-- 4 files changed, 28 insertions(+), 69 deletions(-)
cover arm64: Changes to register and stack dumps
Quoted 7 lines · Laura Abbott
Quoted 6 lines · Will Deacon
This handful of patches makes some significant changes to how we print register/stack dumps and brings us inline with recent changes to x86. The main changes are that we no longer print out the 'Exception stack:' section and PC/LR values are resolved to a symbol+offset format where possible.
Quoted 7 lines
Quoted 2 lines
Feedback welcome.
In very petty complaints, I can no longer just use the PC/LR with addr2line. Yes I can use gdb or one of the scripts but that's a few more steps when I'm doing debugging on my own. Like I said, very minor and overall this is good for both security and alignment.
Understood. scripts/faddr2line seems to do a reasonable job, but I agree that it's a little annoying that you have to do some pointer arithmetic if you want to e.g. locate disassembly in objdump. Setting KALLSYMS=n will give you the addresses if you *really* want them.
Quoted 4 lines
I ran this through several of the LKDTM tests and the backtraces looked fine. You're welcome to add
Tested-by Laura Abbott <[email protected]>
Thanks, Laura.
Will