0
|
1 //low-level trap handler glue code
|
|
2 #include "arm.h"
|
|
3
|
|
4 .text
|
|
5 .code 32
|
|
6
|
|
7 .global trap_swi
|
|
8 .global trap_irq
|
|
9 .global trap_reset
|
|
10 .global trap_und
|
|
11 .global trap_iabort
|
|
12 .global trap_dabort
|
|
13 .global trap_na
|
|
14 .global trap_fiq
|
|
15 .global trapret
|
|
16
|
|
17
|
|
18 # handle SWI, we allow nested SWI
|
|
19 trap_swi:
|
|
20 # build trapframe on the stack
|
|
21 STMFD sp!, {r0-r12, r14} // save context
|
|
22 MRS r2, spsr // copy spsr to r2
|
|
23 STMFD r13!, {r2} // save r2(spsr) to the stack
|
|
24 STMFD r13!, {r14} // save r14 again to have one uniform trapframe
|
|
25 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
26 SUB r13, r13, #8
|
|
27
|
|
28 # call traps (trapframe *fp)
|
|
29 MOV r0, r13 // copy r13_svc to r0
|
|
30 BL swi_handler // branch to the isr_swi
|
|
31
|
|
32 # restore states
|
|
33 trapret:
|
|
34 LDMFD r13, {sp, lr}^ // restore user mode sp and lr
|
|
35 ADD r13, r13, #8
|
|
36 LDMFD r13!, {r14} // restore r14
|
|
37 LDMFD r13!, {r2} // restore spsr
|
|
38 MSR spsr_cxsf, r2
|
|
39 LDMFD r13!,{r0-r12, pc}^ // restore context and return
|
|
40
|
|
41
|
|
42 # handle IRQ, we allow nested IRQs
|
|
43 trap_irq:
|
|
44 # save a few registers to the irq stack to provide scratch regs.
|
|
45 # r14 (lr_irq) contains the instruction (pc) to return to, need to
|
|
46 # save it on the stack as r14 is banked
|
|
47 SUB r14, r14, #4 // r14 (lr) contains the interrupted PC
|
|
48 STMFD r13!, {r0-r2, r14} //
|
|
49 MRS r1, spsr // save spsr_irq
|
|
50 MOV r0, r13 // save stack stop (r13_irq)
|
|
51 ADD r13, r13, #16 // reset the IRQ stack
|
|
52
|
|
53 # switch to the SVC mode
|
|
54 MRS r2, cpsr
|
|
55 BIC r2, r2, #MODE_MASK
|
|
56 ORR r2, r2, #SVC_MODE
|
|
57 MSR cpsr_cxsf, r2
|
|
58
|
|
59 # now, in SVC mode, sp, lr, pc (r13, r14, r15) are all banked
|
|
60 # build the trap frame
|
|
61 LDR r2, [r0, #12] // read the r14_irq, then save it
|
|
62 STMFD r13!, {r2}
|
|
63 STMFD r13!, {r3-r12} // r4-r12 are preserved (non-banked)
|
|
64 LDMFD r0, {r3-r5} // copy r0-r2 over from irq stack
|
|
65 STMFD r13!, {r3-r5}
|
|
66 STMFD r13!, {r1} // save spsr
|
|
67 STMFD r13!, {lr} // save r14_svc
|
|
68
|
|
69 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
70 SUB r13, r13, #8
|
|
71
|
|
72 # get the parameters, then call the handler
|
|
73 MOV r0, r13 // points to
|
|
74 BL irq_handler
|
|
75
|
|
76 # restore the previous status
|
|
77 B trapret
|
|
78
|
|
79 # handle reset/undefine instruction/abort/not-assigned/fiq
|
|
80 # these handler does not allow nested handling
|
|
81 trap_reset:
|
|
82 MOV r14, #0 // lr: not defined on reset
|
|
83 STMFD r13!, {r0-r12, r14}
|
|
84 MRS r2, spsr // copy spsr to r2
|
|
85 STMFD r13!, {r2} // save r2(spsr) to the stack
|
|
86 STMFD r13!, {r14} // save r14 again (it is not really correct)
|
|
87 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
88 SUB r13, r13, #8
|
|
89
|
|
90 # call traps (trapframe *fp)
|
|
91 MOV r0, r13 // copy r13_svc to r0
|
|
92 BL reset_handler
|
|
93 B .
|
|
94
|
|
95 trap_und:
|
|
96 STMFD r13!, {r0-r12, r14} // lr: instruction after the undefined
|
|
97 MRS r2, spsr // copy spsr to r2
|
|
98 STMFD r13!, {r2} // save r2(spsr) to the stack
|
|
99 STMFD r13!, {r14} // save r14 again (it is not really correct)
|
|
100 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
101 SUB r13, r13, #8
|
|
102
|
|
103 # call traps (trapframe *fp)
|
|
104 MOV r0, r13 // save trapframe as the first parameter
|
|
105 BL und_handler
|
|
106 B .
|
|
107
|
|
108 trap_iabort:
|
|
109 SUB r14, r14, #4 // lr: instruction causing the abort
|
|
110 STMFD r13!, {r0-r12, r14}
|
|
111 MRS r2, spsr // copy spsr to r2
|
|
112 STMFD r13!, {r2} // save r2(spsr) to the stack
|
|
113 STMFD r13!, {r14} // save r14 again (it is not really correct)
|
|
114 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
115 SUB r13, r13, #8
|
|
116
|
|
117 # call traps (trapframe *fp)
|
|
118 MOV r0, r13 // save trapframe as the first parameter
|
|
119 BL iabort_handler
|
|
120 B .
|
|
121
|
|
122 trap_dabort:
|
|
123 SUB r14, r14, #8 // lr: instruction causing the abort
|
|
124 STMFD r13!, {r0-r12, r14}
|
|
125 MRS r2, spsr // copy spsr to r2
|
|
126 STMFD r13!, {r2} // save r2(spsr) to the stack
|
|
127 STMFD r13!, {r14} // save r14 again (it is not really correct)
|
|
128 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
129 SUB r13, r13, #8
|
|
130
|
|
131 # call traps (trapframe *fp)
|
|
132 MOV r0, r13 // save trapframe as the first parameter
|
|
133 BL dabort_handler
|
|
134 MOV r0, #2 // #SYS_exit
|
|
135 SWI 0x00
|
|
136 B exit
|
|
137 #B . // trapret
|
|
138
|
|
139 trap_na:
|
|
140 STMFD r13!, {r0-r12, r14} // should never happen, hardware error
|
|
141 MRS r2, spsr // copy spsr to r2
|
|
142 STMFD r13!, {r2} // save r2(spsr) to the stack
|
|
143 STMFD r13!, {r14} // save r14 again (it is not really correct)
|
|
144 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
145 SUB r13, r13, #8
|
|
146
|
|
147 # call traps (trapframe *fp)
|
|
148 MOV r0, r13 // save trapframe as the first parameter
|
|
149 BL na_handler
|
|
150 B .
|
|
151
|
|
152 trap_fiq:
|
|
153 SUB r14, r14, #4 // lr: return address after the fiq handler
|
|
154 STMFD r13!, {r0-r12, r14}
|
|
155 MRS r2, spsr // copy spsr to r2
|
|
156 STMFD r13!, {r2} // save r2(spsr) to the stack
|
|
157 STMFD r13!, {r14} // save r14 again (it is not really correct)
|
|
158 STMFD r13, {sp, lr}^ // save user mode sp and lr
|
|
159 SUB r13, r13, #8
|
|
160
|
|
161 # call traps (trapframe *fp)
|
|
162 MOV r0, r13 // save trapframe as the first parameter
|
|
163 BL fiq_handler
|
|
164 B .
|
|
165
|