1
2
3
4
5
6
7
8
9 #include <linux/linkage.h>
10 #include <asm/assembler.h>
11 .text
12
13 @ fp is 0 or stack frame
14
15 #define frame v4
16 #define sv_fp v5
17 #define sv_pc v6
18 #define offset v8
19
20 ENTRY(__backtrace)
21 mov r0, fp
22
23 ENTRY(c_backtrace)
24
25 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
26 mov pc, lr
27 ENDPROC(__backtrace)
28 ENDPROC(c_backtrace)
29 #else
30 stm.w (v4 - v8, lr), [sp-] @ Save an extra register
31 @ so we have a location...
32 mov.a frame, r0 @ if frame pointer is zero
33 beq no_frame @ we have no stack frames
34
35 1: stm.w (pc), [sp-] @ calculate offset of PC stored
36 ldw.w r0, [sp]+, #4 @ by stmfd for this CPU
37 adr r1, 1b
38 sub offset, r0, r1
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 for_each_frame:
56
57 1001: ldw sv_pc, [frame+], #0 @ get saved pc
58 1002: ldw sv_fp, [frame+], #-12 @ get saved fp
59
60 sub sv_pc, sv_pc, offset @ Correct PC for prefetching
61
62 1003: ldw r2, [sv_pc+], #-4 @ if stmfd sp, {args} exists,
63 ldw r3, .Ldsi+4 @ adjust saved 'pc' back one
64 cxor.a r3, r2 >> #14 @ instruction
65 beq 201f
66 sub r0, sv_pc, #4 @ allow for mov
67 b 202f
68 201:
69 sub r0, sv_pc, #8 @ allow for mov + stmia
70 202:
71 ldw r1, [frame+], #-4 @ get saved lr
72 mov r2, frame
73 b.l dump_backtrace_entry
74
75 ldw r1, [sv_pc+], #-4 @ if stmfd sp, {args} exists,
76 ldw r3, .Ldsi+4
77 cxor.a r3, r1 >> #14
78 bne 1004f
79 ldw r0, [frame+], #-8 @ get sp
80 sub r0, r0, #4 @ point at the last arg
81 b.l .Ldumpstm @ dump saved registers
82
83 1004: ldw r1, [sv_pc+], #0 @ if stmfd {, fp, ip, lr, pc}
84 ldw r3, .Ldsi @ instruction exists,
85 cxor.a r3, r1 >> #14
86 bne 201f
87 sub r0, frame, #16
88 b.l .Ldumpstm @ dump saved registers
89 201:
90 cxor.a sv_fp, #0 @ zero saved fp means
91 beq no_frame @ no further frames
92
93 csub.a sv_fp, frame @ next frame must be
94 mov frame, sv_fp @ above the current frame
95 bua for_each_frame
96
97 1006: adr r0, .Lbad
98 mov r1, frame
99 b.l printk
100 no_frame: ldm.w (v4 - v8, pc), [sp]+
101 ENDPROC(__backtrace)
102 ENDPROC(c_backtrace)
103
104 .pushsection __ex_table,"a"
105 .align 3
106 .long 1001b, 1006b
107 .long 1002b, 1006b
108 .long 1003b, 1006b
109 .long 1004b, 1006b
110 .popsection
111
112 #define instr v4
113 #define reg v5
114 #define stack v6
115
116 .Ldumpstm: stm.w (instr, reg, stack, v7, lr), [sp-]
117 mov stack, r0
118 mov instr, r1
119 mov reg, #14
120 mov v7, #0
121 1: mov r3, #1
122 csub.a reg, #8
123 bne 201f
124 sub reg, reg, #3
125 201:
126 cand.a instr, r3 << reg
127 beq 2f
128 add v7, v7, #1
129 cxor.a v7, #6
130 cmoveq v7, #1
131 cmoveq r1, #'\n'
132 cmovne r1, #' '
133 ldw.w r3, [stack]+, #-4
134 mov r2, reg
135 csub.a r2, #8
136 bsl 201f
137 sub r2, r2, #3
138 201:
139 cand.a instr, #0x40 @ if H is 1, high 16 regs
140 beq 201f
141 add r2, r2, #0x10 @ so r2 need add 16
142 201:
143 adr r0, .Lfp
144 b.l printk
145 2: sub.a reg, reg, #1
146 bns 1b
147 cxor.a v7, #0
148 beq 201f
149 adr r0, .Lcr
150 b.l printk
151 201: ldm.w (instr, reg, stack, v7, pc), [sp]+
152
153 .Lfp: .asciz "%cr%d:%08x"
154 .Lcr: .asciz "\n"
155 .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
156 .align
157 .Ldsi: .word 0x92eec000 >> 14 @ stm.w sp, (... fp, ip, lr, pc)
158 .word 0x92e10000 >> 14 @ stm.w sp, ()
159
160 #endif