Blame view

kernel/linux-imx6_3.14.28/arch/arm/lib/backtrace.S 3.72 KB
6b13f685e   김민수   BSP 최초 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  /*
   *  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/linkage.h>
  #include <asm/assembler.h>
  		.text
  
  @ fp is 0 or stack frame
  
  #define frame	r4
  #define sv_fp	r5
  #define sv_pc	r6
  #define mask	r7
  #define offset	r8
  
  ENTRY(c_backtrace)
  
  #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
  		mov	pc, lr
  ENDPROC(c_backtrace)
  #else
  		stmfd	sp!, {r4 - r8, 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
  
  		tst	r1, #0x10		@ 26 or 32-bit mode?
   ARM(		moveq	mask, #0xfc000003	)
   THUMB(		moveq	mask, #0xfc000000	)
   THUMB(		orreq	mask, #0x03		)
  		movne	mask, #0		@ mask for 32-bit
  
  1:		stmfd	sp!, {pc}		@ calculate offset of PC stored
  		ldr	r0, [sp], #4		@ by stmfd for this CPU
  		adr	r1, 1b
  		sub	offset, r0, r1
  
  /*
   * Stack frame layout:
   *             optionally saved caller registers (r4 - r10)
   *             saved fp
   *             saved sp
   *             saved lr
   *    frame => saved pc
   *             optionally saved arguments (r0 - r3)
   * saved sp => <next word>
   *
   * Functions start with the following code sequence:
   *                  mov   ip, sp
   *                  stmfd sp!, {r0 - r3} (optional)
   * corrected pc =>  stmfd sp!, {..., fp, ip, lr, pc}
   */
  for_each_frame:	tst	frame, mask		@ Check for address exceptions
  		bne	no_frame
  
  1001:		ldr	sv_pc, [frame, #0]	@ get saved pc
  1002:		ldr	sv_fp, [frame, #-12]	@ get saved fp
  
  		sub	sv_pc, sv_pc, offset	@ Correct PC for prefetching
  		bic	sv_pc, sv_pc, mask	@ mask PC/LR for the mode
  
  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
  		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
  		bl	dump_backtrace_entry
  
  		ldr	r1, [sv_pc, #-4]	@ if stmfd sp!, {args} exists,
  		ldr	r3, .Ldsi+4
  		teq	r3, r1, lsr #11
  		ldreq	r0, [frame, #-8]	@ get sp
  		subeq	r0, r0, #4		@ point at the last arg
  		bleq	.Ldumpstm		@ 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
  		bleq	.Ldumpstm		@ dump saved registers
  
  		teq	sv_fp, #0		@ zero saved fp means
  		beq	no_frame		@ no further frames
  
  		cmp	sv_fp, frame		@ next frame must be
  		mov	frame, sv_fp		@ above the current frame
  		bhi	for_each_frame
  
  1006:		adr	r0, .Lbad
  		mov	r1, frame
  		bl	printk
  no_frame:	ldmfd	sp!, {r4 - r8, pc}
  ENDPROC(c_backtrace)
  		
  		.pushsection __ex_table,"a"
  		.align	3
  		.long	1001b, 1006b
  		.long	1002b, 1006b
  		.long	1003b, 1006b
  		.long	1004b, 1006b
  		.popsection
  
  #define instr r4
  #define reg   r5
  #define stack r6
  
  .Ldumpstm:	stmfd	sp!, {instr, reg, stack, r7, lr}
  		mov	stack, r0
  		mov	instr, r1
  		mov	reg, #10
  		mov	r7, #0
  1:		mov	r3, #1
   ARM(		tst	instr, r3, lsl reg	)
   THUMB(		lsl	r3, reg			)
   THUMB(		tst	instr, r3		)
  		beq	2f
  		add	r7, r7, #1
  		teq	r7, #6
  		moveq	r7, #0
  		adr	r3, .Lcr
  		addne	r3, r3, #1		@ skip newline
  		ldr	r2, [stack], #-4
  		mov	r1, reg
  		adr	r0, .Lfp
  		bl	printk
  2:		subs	reg, reg, #1
  		bpl	1b
  		teq	r7, #0
  		adrne	r0, .Lcr
  		blne	printk
  		ldmfd	sp!, {instr, reg, stack, r7, pc}
  
  .Lfp:		.asciz	" r%d:%08x%s"
  .Lcr:		.asciz	"
  "
  .Lbad:		.asciz	"Backtrace aborted due to bad frame pointer <%p>
  "
  		.align
  .Ldsi:		.word	0xe92dd800 >> 11	@ stmfd sp!, {... fp, ip, lr, pc}
  		.word	0xe92d0000 >> 11	@ stmfd sp!, {}
  
  #endif