exception.S revision 1.13 1 /* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */
2
3 /*
4 * Copyright (c) 1994-1997 Mark Brinicombe.
5 * Copyright (c) 1994 Brini.
6 * All rights reserved.
7 *
8 * This code is derived from software written for Brini by Mark Brinicombe
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Brini.
21 * 4. The name of the company nor the name of the author may be used to
22 * endorse or promote products derived from this software without specific
23 * prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * RiscBSD kernel project
38 *
39 * exception.S
40 *
41 * Low level handlers for exception vectors
42 *
43 * Created : 24/09/94
44 *
45 * Based on kate/display/abort.s
46 */
47
48 #include "opt_ipkdb.h"
49 #include <machine/asm.h>
50 #include <machine/cpu.h>
51 #include <machine/frame.h>
52 #include "assym.h"
53
54 .text
55 .align 0
56
57 AST_ALIGNMENT_FAULT_LOCALS
58
59 /*
60 * reset_entry:
61 *
62 * Handler for Reset exception.
63 */
64 ASENTRY_NP(reset_entry)
65 adr r0, Lreset_panicmsg
66 mov r1, lr
67 bl _C_LABEL(panic)
68 /* NOTREACHED */
69 Lreset_panicmsg:
70 .asciz "Reset vector called, LR = 0x%08x"
71 .balign 4
72
73 /*
74 * swi_entry
75 *
76 * Handler for the Software Interrupt exception.
77 */
78 ASENTRY_NP(swi_entry)
79 PUSHFRAME
80 ENABLE_ALIGNMENT_FAULTS
81
82 mov r0, sp /* Pass the frame to any function */
83 bl _C_LABEL(swi_handler) /* It's a SWI ! */
84
85 DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
86 PULLFRAME
87 movs pc, lr /* Exit */
88
89 /*
90 * prefetch_abort_entry:
91 *
92 * Handler for the Prefetch Abort exception.
93 */
94 ASENTRY_NP(prefetch_abort_entry)
95 #ifdef __XSCALE__
96 nop /* Make absolutely sure any pending */
97 nop /* imprecise aborts have occurred. */
98 #endif
99 sub lr, lr, #0x00000004 /* Adjust the lr */
100
101 PUSHFRAMEINSVC
102 ENABLE_ALIGNMENT_FAULTS
103
104 ldr r1, Lprefetch_abort_handler_address
105 adr lr, exception_exit
106 mov r0, sp /* pass the stack pointer as r0 */
107 ldr pc, [r1]
108
109 Lprefetch_abort_handler_address:
110 .word _C_LABEL(prefetch_abort_handler_address)
111
112 .data
113 .global _C_LABEL(prefetch_abort_handler_address)
114
115 _C_LABEL(prefetch_abort_handler_address):
116 .word abortprefetch
117
118 .text
119 abortprefetch:
120 adr r0, abortprefetchmsg
121 b _C_LABEL(panic)
122
123 abortprefetchmsg:
124 .asciz "abortprefetch"
125 .align 0
126
127 /*
128 * data_abort_entry:
129 *
130 * Handler for the Data Abort exception.
131 */
132 ASENTRY_NP(data_abort_entry)
133 #ifdef __XSCALE__
134 nop /* Make absolutely sure any pending */
135 nop /* imprecise aborts have occurred. */
136 #endif
137 sub lr, lr, #0x00000008 /* Adjust the lr */
138
139 PUSHFRAMEINSVC /* Push trap frame and switch */
140 /* to SVC32 mode */
141 ENABLE_ALIGNMENT_FAULTS
142
143 ldr r1, Ldata_abort_handler_address
144 adr lr, exception_exit
145 mov r0, sp /* pass the stack pointer as r0 */
146 ldr pc, [r1]
147
148 Ldata_abort_handler_address:
149 .word _C_LABEL(data_abort_handler_address)
150
151 .data
152 .global _C_LABEL(data_abort_handler_address)
153 _C_LABEL(data_abort_handler_address):
154 .word abortdata
155
156 .text
157 abortdata:
158 adr r0, abortdatamsg
159 b _C_LABEL(panic)
160
161 abortdatamsg:
162 .asciz "abortdata"
163 .align 0
164
165 /*
166 * address_exception_entry:
167 *
168 * Handler for the Address Exception exception.
169 *
170 * NOTE: This exception isn't really used on arm32. We
171 * print a warning message to the console and then treat
172 * it like a Data Abort.
173 */
174 ASENTRY_NP(address_exception_entry)
175 mrs r1, cpsr_all
176 mrs r2, spsr_all
177 mov r3, lr
178 adr r0, Laddress_exception_msg
179 bl _C_LABEL(printf) /* XXX CLOBBERS LR!! */
180 b data_abort_entry
181 Laddress_exception_msg:
182 .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
183 .balign 4
184
185 /*
186 * General exception exit handler
187 * (Placed here to be within range of all the references to it)
188 *
189 * It exits straight away if not returning to USR mode.
190 * This loops around delivering any pending ASTs.
191 * Interrupts are disabled at suitable points to avoid ASTs
192 * being posted between testing and exit to user mode.
193 *
194 * This function uses PULLFRAMEFROMSVCANDEXIT and
195 * DO_AST_AND_RESTORE_ALIGNMENT_FAULTS thus should
196 * only be called if the exception handler used PUSHFRAMEINSVC
197 * followed by ENABLE_ALIGNMENT_FAULTS.
198 */
199
200 exception_exit:
201 DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
202 PULLFRAMEFROMSVCANDEXIT
203
204 /*
205 * undefined_entry:
206 *
207 * Handler for the Undefined Instruction exception.
208 *
209 * We indirect the undefined vector via the handler address
210 * in the data area. Entry to the undefined handler must
211 * look like direct entry from the vector.
212 */
213 ASENTRY_NP(undefined_entry)
214 #ifdef IPKDB
215 /*
216 * IPKDB must be hooked in at the earliest possible entry point.
217 *
218 */
219 /*
220 * Make room for all registers saving real r0-r7 and r15.
221 * The remaining registers are updated later.
222 */
223 stmfd sp!, {r0,r1} /* psr & spsr */
224 stmfd sp!, {lr} /* pc */
225 stmfd sp!, {r0-r14} /* r0-r7, r8-r14 */
226 /*
227 * Get previous psr.
228 */
229 mrs r7, cpsr_all
230 mrs r0, spsr_all
231 str r0, [sp, #(16*4)]
232 /*
233 * Test for user mode.
234 */
235 tst r0, #0xf
236 bne .Lprenotuser_push
237 add r1, sp, #(8*4)
238 stmia r1,{r8-r14}^ /* store user mode r8-r14*/
239 b .Lgoipkdb
240 /*
241 * Switch to previous mode to get r8-r13.
242 */
243 .Lprenotuser_push:
244 orr r0, r0, #(I32_bit) /* disable interrupts */
245 msr cpsr_all, r0
246 mov r1, r8
247 mov r2, r9
248 mov r3, r10
249 mov r4, r11
250 mov r5, r12
251 mov r6, r13
252 msr cpsr_all, r7 /* back to undefined mode */
253 add r8, sp, #(8*4)
254 stmia r8, {r1-r6} /* r8-r13 */
255 /*
256 * Now back to previous mode to get r14 and spsr.
257 */
258 msr cpsr_all, r0
259 mov r1, r14
260 mrs r2, spsr
261 msr cpsr_all, r7 /* back to undefined mode */
262 str r1, [sp, #(14*4)] /* r14 */
263 str r2, [sp, #(17*4)] /* spsr */
264 /*
265 * Now to IPKDB.
266 */
267 .Lgoipkdb:
268 mov r0, sp
269 bl _C_LABEL(ipkdb_trap_glue)
270 ldr r1, .Lipkdb_trap_return
271 str r0,[r1]
272
273 /*
274 * Have to load all registers from the stack.
275 *
276 * Start with spsr and pc.
277 */
278 ldr r0, [sp, #(16*4)] /* spsr */
279 ldr r1, [sp, #(15*4)] /* r15 */
280 msr spsr_all, r0
281 mov r14, r1
282 /*
283 * Test for user mode.
284 */
285 tst r0, #0xf
286 bne .Lprenotuser_pull
287 add r1, sp, #(8*4)
288 ldmia r1, {r8-r14}^ /* load user mode r8-r14 */
289 b .Lpull_r0r7
290 .Lprenotuser_pull:
291 /*
292 * Now previous mode spsr and r14.
293 */
294 ldr r1, [sp, #(17*4)] /* spsr */
295 ldr r2, [sp, #(14*4)] /* r14 */
296 orr r0, r0, #(I32_bit)
297 msr cpsr_all, r0 /* switch to previous mode */
298 msr spsr_all, r1
299 mov r14, r2
300 msr cpsr_all, r7 /* back to undefined mode */
301 /*
302 * Now r8-r13.
303 */
304 add r8, sp, #(8*4)
305 ldmia r8, {r1-r6} /* r8-r13 */
306 msr cpsr_all, r0
307 mov r8, r1
308 mov r9, r2
309 mov r10, r3
310 mov r11, r4
311 mov r12, r5
312 mov r13, r6
313 msr cpsr_all, r7
314 .Lpull_r0r7:
315 /*
316 * Now the rest of the registers.
317 */
318 ldr r1,Lipkdb_trap_return
319 ldr r0,[r1]
320 tst r0,r0
321 ldmfd sp!, {r0-r7} /* r0-r7 */
322 add sp, sp, #(10*4) /* adjust sp */
323
324 /*
325 * Did IPKDB handle it?
326 */
327 movnes pc, lr /* return */
328
329 #endif
330 stmfd sp!, {r0, r1}
331 ldr r0, Lundefined_handler_indirection
332 ldr r1, [sp], #0x0004
333 str r1, [r0, #0x0000]
334 ldr r1, [sp], #0x0004
335 str r1, [r0, #0x0004]
336 ldmia r0, {r0, r1, pc}
337
338 #ifdef IPKDB
339 Lipkdb_trap_return:
340 .word Lipkdb_trap_return_data
341 #endif
342
343 Lundefined_handler_indirection:
344 .word Lundefined_handler_indirection_data
345
346 /*
347 * assembly bounce code for calling the kernel
348 * undefined instruction handler. This uses
349 * a standard trap frame and is called in SVC mode.
350 */
351
352 ENTRY_NP(undefinedinstruction_bounce)
353 PUSHFRAMEINSVC
354 ENABLE_ALIGNMENT_FAULTS
355
356 mov r0, sp
357 adr lr, exception_exit
358 b _C_LABEL(undefinedinstruction)
359
360 .data
361 .align 0
362
363 #ifdef IPKDB
364 Lipkdb_trap_return_data:
365 .word 0
366 #endif
367
368 /*
369 * Indirection data
370 * 2 words use for preserving r0 and r1
371 * 3rd word contains the undefined handler address.
372 */
373
374 Lundefined_handler_indirection_data:
375 .word 0
376 .word 0
377
378 .global _C_LABEL(undefined_handler_address)
379 _C_LABEL(undefined_handler_address):
380 .word _C_LABEL(undefinedinstruction_bounce)
381