Skip to contentSkip to conversation

arm64: Changes to register and stack dumps

PATCH New Will Deacon 3 participants 10 messages Oct 19, 2017 – Oct 23, 2017 arm64

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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.

Cc Catalin Marinas <[email protected]>
Cc Julien Thierry <[email protected]>
Cc Kristina Martsenko <[email protected]>
Cc Will Deacon <[email protected]>
---
 arch/arm64/mm/fault.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
arch/arm64/mm/fault.c +5 -2
index 02d92bdf1c49..eec09c623d8e 100644
@@ -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
#2 lore raw

PATCH 2/4 arm64: traps: Don't print stack or raw PC/LR values in backtraces

In reply to Will Deacon

Printing 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
index 2dc0f8482210..c20896b8fb2d 100644
@@ -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
#3 lore raw

PATCH 3/4 arm64: traps: Pretty-print pstate in register dumps

In reply to Will Deacon

We 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
index c20896b8fb2d..be3cf9cd7dec 100644
@@ -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
reviewer
#4 lore raw

PATCH 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.

---
 arch/arm64/kernel/process.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)
arch/arm64/kernel/process.c +6 -0
index c20896b8fb2d..be3cf9cd7dec 100644
@@ -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
#5 lore raw

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.

---
 arch/arm64/kernel/process.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)
arch/arm64/kernel/process.c +6 -0
index c20896b8fb2d..be3cf9cd7dec 100644
@@ -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.

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 ? '+' : '-');
+}

reviewer
#6 lore raw

PATCH 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.

---
 arch/arm64/kernel/process.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)
arch/arm64/kernel/process.c +6 -0
index c20896b8fb2d..be3cf9cd7dec 100644
@@ -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.

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.

#7 lore raw

PATCH 4/4 arm64: uapi: Remove PSR_Q_BIT

In reply to Will Deacon

PSTATE.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
index d1ff83dfe5de..3697d95ba0a1 100644
@@ -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
#8 lore raw

cover arm64: Changes to register and stack dumps

In reply to Will Deacon
Quoted 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 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(-)
#9 lore raw

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

Thanks, Laura.

Will