summaryrefslogtreecommitdiff
path: root/arch/arm/lib/backtrace.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lib/backtrace.S')
-rw-r--r--arch/arm/lib/backtrace.S32
1 files changed, 21 insertions, 11 deletions
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 7d7952e5a3b1..293a2716bd20 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/arch/arm/lib/backtrace.S
*
* Copyright (C) 1995, 1996 Russell King
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
* 27/03/03 Ian Molton Clean up CONFIG_CPU
- *
*/
#include <linux/kern_levels.h>
#include <linux/linkage.h>
@@ -22,6 +18,7 @@
#define sv_pc r6
#define mask r7
#define offset r8
+#define loglvl r9
ENTRY(c_backtrace)
@@ -29,9 +26,10 @@ ENTRY(c_backtrace)
ret lr
ENDPROC(c_backtrace)
#else
- stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
+ stmfd sp!, {r4 - r9, lr} @ Save an extra register so we have a location...
movs frame, r0 @ if frame pointer is zero
beq no_frame @ we have no stack frames
+ mov loglvl, r2
tst r1, #0x10 @ 26 or 32-bit mode?
ARM( moveq mask, #0xfc000003 )
@@ -70,13 +68,14 @@ for_each_frame: tst frame, mask @ Check for address exceptions
1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
ldr r3, .Ldsi+4 @ adjust saved 'pc' back one
- teq r3, r2, lsr #10 @ instruction
+ teq r3, r2, lsr #11 @ instruction
subne r0, sv_pc, #4 @ allow for mov
subeq r0, sv_pc, #8 @ allow for mov + stmia
ldr r1, [frame, #-4] @ get saved lr
mov r2, frame
bic r1, r1, mask @ mask PC/LR for the mode
+ mov r3, loglvl
bl dump_backtrace_entry
ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
@@ -84,12 +83,14 @@ for_each_frame: tst frame, mask @ Check for address exceptions
teq r3, r1, lsr #11
ldreq r0, [frame, #-8] @ get sp
subeq r0, r0, #4 @ point at the last arg
+ mov r2, loglvl
bleq dump_backtrace_stm @ dump saved registers
1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc}
ldr r3, .Ldsi @ instruction exists,
teq r3, r1, lsr #11
subeq r0, frame, #16
+ mov r2, loglvl
bleq dump_backtrace_stm @ dump saved registers
teq sv_fp, #0 @ zero saved fp means
@@ -97,12 +98,21 @@ for_each_frame: tst frame, mask @ Check for address exceptions
cmp sv_fp, frame @ next frame must be
mov frame, sv_fp @ above the current frame
+#ifdef CONFIG_IRQSTACKS
+ @
+ @ Kernel stacks may be discontiguous in memory. If the next
+ @ frame is below the previous frame, accept it as long as it
+ @ lives in kernel memory.
+ @
+ cmpls sv_fp, #PAGE_OFFSET
+#endif
bhi for_each_frame
1006: adr r0, .Lbad
- mov r1, frame
- bl printk
-no_frame: ldmfd sp!, {r4 - r8, pc}
+ mov r1, loglvl
+ mov r2, frame
+ bl _printk
+no_frame: ldmfd sp!, {r4 - r9, pc}
ENDPROC(c_backtrace)
.pushsection __ex_table,"a"
@@ -113,7 +123,7 @@ ENDPROC(c_backtrace)
.long 1004b, 1006b
.popsection
-.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
+.Lbad: .asciz "%sBacktrace aborted due to bad frame pointer <%p>\n"
.align
.Ldsi: .word 0xe92dd800 >> 11 @ stmfd sp!, {... fp, ip, lr, pc}
.word 0xe92d0000 >> 11 @ stmfd sp!, {}