exception.S revision 1.1 1 /* $NetBSD: exception.S,v 1.1 2001/07/28 13:28:03 chris 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 Lastpending:
58 .word _C_LABEL(astpending)
59
60 /*
61 * General exception exit handler
62 *
63 * It exits straight away if not returning to USR mode.
64 * This loops around delivering any pending ASTs.
65 * Interrupts are disabled at suitable points to avoid ASTs
66 * being posted between testing and exit to user mode.
67 *
68 * This function uses PULLFRAMEFROMSVCANDEXIT thus should
69 * only be called if the exception handler used PUSHFRAMEINSVC
70 */
71
72 exception_exit:
73 mrs r4, cpsr_all /* Get CPSR */
74
75 ldr r0, [sp] /* Get the SPSR from stack */
76 and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the AST */
77 teq r0, #(PSR_USR32_MODE)
78 bne do_exit /* Not USR mode so no AST delivery */
79
80 ldr r5, Lastpending /* Get address of astpending */
81
82 Lexception_exit_loop:
83 orr r0, r4, #(I32_bit) /* Block IRQs */
84 msr cpsr_all, r0
85
86 ldr r1, [r5] /* Do we have an AST pending */
87 teq r1, #0x00000000
88 bne do_ast
89
90 PULLFRAMEFROMSVCANDEXIT /* No AST so exit */
91
92 do_ast:
93 msr cpsr_all, r4 /* Restore interrupts */
94
95 mov r1, #0x00000000 /* Clear ast pending */
96 str r1, [r5]
97
98 mov r0, sp /* arg 0 = trap frame */
99 bl _C_LABEL(ast) /* call the AST handler */
100 b Lexception_exit_loop /* Try and exit again */
101
102 do_exit:
103 orr r0, r4, #(I32_bit) /* Disable interupts */
104 msr cpsr_all, r0
105
106 PULLFRAMEFROMSVCANDEXIT /* Restore the trap frame and exit */
107
108
109 /* entry point for CPU data abort */
110
111 ASENTRY_NP(data_abort_entry)
112 sub lr, lr, #0x00000008 /* Adjust the lr */
113
114 PUSHFRAMEINSVC /* Push trap frame and switch */
115 /* to SVC32 mode */
116
117 mov r0, sp /* pass the stack pointer as r0 */
118
119 /* add lr, pc, #exception_exitLdata_abort_return - . - 8*/
120 add lr, pc, #exception_exit - . - 8
121 ldr r1, Ldata_abort_handler_address
122 ldr pc, [r1]
123
124 Ldata_abort_return: /* XXX - could just straight to exception_exit */
125 b exception_exit
126
127 Ldata_abort_handler_address:
128 .word _C_LABEL(data_abort_handler_address)
129
130 .data
131 .global _C_LABEL(data_abort_handler_address)
132 _C_LABEL(data_abort_handler_address):
133 .word abortdata
134
135 .text
136 abortdata:
137 add r0, pc, #abortdatamsg - . - 8
138 b _C_LABEL(panic)
139
140 abortdatamsg:
141 .asciz "abortdata"
142 .align 0
143
144
145 ASENTRY_NP(prefetch_abort_entry)
146 sub lr, lr, #0x00000004 /* Adjust the lr */
147
148 PUSHFRAMEINSVC
149
150 mov r0, sp /* pass the stack pointer as r0 */
151
152 # add lr, pc, #Lprefetch_abort_return - . - 8
153 add lr, pc, #exception_exit - . - 8
154 ldr r1, Lprefetch_abort_handler_address
155 ldr pc, [r1]
156
157 Lprefetch_abort_return: /* XXX - could just straight to exception_exit */
158 b exception_exit
159
160 Lprefetch_abort_handler_address:
161 .word _C_LABEL(prefetch_abort_handler_address)
162
163 .data
164 .global _C_LABEL(prefetch_abort_handler_address)
165
166 _C_LABEL(prefetch_abort_handler_address):
167 .word abortprefetch
168
169 .text
170 abortprefetch:
171 add r0, pc, #abortprefetchmsg - . - 8
172 b _C_LABEL(panic)
173
174 abortprefetchmsg:
175 .asciz "abortprefetch"
176 .align 0
177
178
179 /*
180 * swi_entry
181 *
182 * Main entry point for the SWI vector
183 */
184
185 ASENTRY_NP(swi_entry)
186 PUSHFRAME
187
188 sub r0, lr, #0x00000004 /* Get the address of the SWI */
189 ldr r4, [r0] /* Get the instruction */
190
191 bic r1, r4, #0xff000000 /* Extract the comment field */
192
193 mov r0, sp /* Pass the frame to any function */
194
195 bl _C_LABEL(syscall) /* It's a syscall ! */
196
197 ldr r5, Lastpending /* Get address of astpending */
198 mrs r4, cpsr_all /* Get CPSR */
199
200 swi_exit_loop:
201 orr r0, r4, #(I32_bit) /* Disable IRQs */
202 msr cpsr_all, r0
203
204 ldr r1, [r5] /* Do we have an AST pending */
205 teq r1, #0x00000000
206 bne do_swi_ast
207
208 PULLFRAME
209 movs pc, lr /* Exit */
210
211 do_swi_ast:
212 msr cpsr_all, r4 /* Restore interrupts */
213
214 mov r1, #0x00000000 /* Clear ast pending */
215 str r1, [r5]
216
217 mov r0, sp /* arg 0 = trap frame */
218 bl _C_LABEL(ast) /* call the AST handler */
219 b swi_exit_loop /* Try and exit again */
220
221
222 /*
223 * We indirect the undefined vector via the handler address
224 * in the data area.
225 * Entry to the undefined handler must look like direct
226 * entry from the vector.
227 */
228
229 ASENTRY_NP(undefined_entry)
230 #ifdef IPKDB
231 /*
232 * IPKDB must be hooked in at the earliest possible entry point.
233 *
234 */
235 /*
236 * Make room for all registers saving real r0-r7 and r15.
237 * The remaining registers are updated later.
238 */
239 stmfd sp!, {r0,r1} /* psr & spsr */
240 stmfd sp!, {lr} /* pc */
241 stmfd sp!, {r0-r14} /* r0-r7, r8-r14 */
242 /*
243 * Get previous psr.
244 */
245 mrs r7, cpsr_all
246 mrs r0, spsr_all
247 str r0, [sp, #(16*4)]
248 /*
249 * Test for user mode.
250 */
251 tst r0, #0xf
252 bne Lprenotuser_push
253 add r1, sp, #(8*4)
254 stmia r1,{r8-r14}^ /* store user mode r8-r14*/
255 b Lgoipkdb
256 /*
257 * Switch to previous mode to get r8-r13.
258 */
259 Lprenotuser_push:
260 orr r0, r0, #(I32_bit) /* disable interrupts */
261 msr cpsr_all, r0
262 mov r1, r8
263 mov r2, r9
264 mov r3, r10
265 mov r4, r11
266 mov r5, r12
267 mov r6, r13
268 msr cpsr_all, r7 /* back to undefined mode */
269 add r8, sp, #(8*4)
270 stmia r8, {r1-r6} /* r8-r13 */
271 /*
272 * Now back to previous mode to get r14 and spsr.
273 */
274 msr cpsr_all, r0
275 mov r1, r14
276 mrs r2, spsr
277 msr cpsr_all, r7 /* back to undefined mode */
278 str r1, [sp, #(14*4)] /* r14 */
279 str r2, [sp, #(17*4)] /* spsr */
280 /*
281 * Now to IPKDB.
282 */
283 Lgoipkdb:
284 mov r0, sp
285 bl _C_LABEL(ipkdb_trap_glue)
286 ldr r1, Lipkdb_trap_return
287 str r0,[r1]
288 /*
289 * Have to load all registers from the stack.
290 *
291 * Start with spsr and pc.
292 */
293 ldr r0, [sp, #(16*4)] /* spsr */
294 ldr r1, [sp, #(15*4)] /* r15 */
295 msr spsr_all, r0
296 mov r14, r1
297 /*
298 * Test for user mode.
299 */
300 tst r0, #0xf
301 bne Lprenotuser_pull
302 add r1, sp, #(8*4)
303 ldmia r1, {r8-r14}^ /* load user mode r8-r14 */
304 b Lpull_r0r7
305 Lprenotuser_pull:
306 /*
307 * Now previous mode spsr and r14.
308 */
309 ldr r1, [sp, #(17*4)] /* spsr */
310 ldr r2, [sp, #(14*4)] /* r14 */
311 orr r0, r0, #(I32_bit)
312 msr cpsr_all, r0 /* switch to previous mode */
313 msr spsr_all, r1
314 mov r14, r2
315 msr cpsr_all, r7 /* back to undefined mode */
316 /*
317 * Now r8-r13.
318 */
319 add r8, sp, #(8*4)
320 ldmia r8, {r1-r6} /* r8-r13 */
321 msr cpsr_all, r0
322 mov r8, r1
323 mov r9, r2
324 mov r10, r3
325 mov r11, r4
326 mov r12, r5
327 mov r13, r6
328 msr cpsr_all, r7
329 Lpull_r0r7:
330 /*
331 * Now the rest of the registers.
332 */
333 ldr r1,Lipkdb_trap_return
334 ldr r0,[r1]
335 tst r0,r0
336 ldmfd sp!, {r0-r7} /* r0-r7 */
337 add sp, sp, #(10*4) /* adjust sp */
338
339 /*
340 * Did IPKDB handle it?
341 */
342 movnes pc, lr /* return */
343
344 #endif
345 stmfd sp!, {r0, r1}
346 ldr r0, Lundefined_handler_indirection
347 ldr r1, [sp], #0x0004
348 str r1, [r0, #0x0000]
349 ldr r1, [sp], #0x0004
350 str r1, [r0, #0x0004]
351 ldmia r0, {r0, r1, pc}
352
353 #ifdef IPKDB
354 Lipkdb_trap_return:
355 .word Lipkdb_trap_return_data
356 #endif
357
358 Lundefined_handler_indirection:
359 .word Lundefined_handler_indirection_data
360
361 /*
362 * assembly bounce code for calling the kernel
363 * undefined instruction handler. This uses
364 * a standard trap frame and is called in SVC mode.
365 */
366
367 ENTRY_NP(undefinedinstruction_bounce)
368 PUSHFRAMEINSVC
369 mov r0, sp
370 bl _C_LABEL(undefinedinstruction)
371
372 b exception_exit
373
374 .data
375 .align 0
376
377 #ifdef IPKDB
378 Lipkdb_trap_return_data:
379 .word 0
380 #endif
381
382 /*
383 * Indirection data
384 * 2 words use for preserving r0 and r1
385 * 3rd word contains the undefined handler address.
386 */
387
388 Lundefined_handler_indirection_data:
389 .word 0
390 .word 0
391
392 .global _C_LABEL(undefined_handler_address)
393 _C_LABEL(undefined_handler_address):
394 .word _C_LABEL(undefinedinstruction_bounce)
395
396 /* End of exception.S */
397