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