1 /* $NetBSD: trap_subr.S,v 1.10.38.1 2007/05/28 20:01:43 freza Exp $ */
4 * Copyright 2001 Wasabi Systems, Inc.
7 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
40 * Copyright (C) 1995, 1996 TooLs GmbH.
41 * All rights reserved.
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by TooLs GmbH.
54 * 4. The name of TooLs GmbH may not be used to endorse or promote products
55 * derived from this software without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
61 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
62 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
63 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
64 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
65 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
66 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 * NOTICE: This is not a standalone file. to use it, #include it in
71 * your port's locore.S, like so:
73 * #include <powerpc/ibm4xx/trap_subr.S>
77 * Data used during primary/secondary traps/interrupts
79 #define tempsave 0x2e0 /* primary save area for trap handling */
80 #define disisave 0x3e0 /* primary save area for dsi/isi traps */
81 #define exitsave 0x4e0 /* use this so trap return does not conflict */
83 * XXX Interrupt and spill stacks need to be per-CPU.
90 #define STANDARD_PROLOG(savearea) \
91 mtsprg 1,1; /* save SP */ \
92 stmw 28,savearea(0); /* free r28-r31 */ \
93 mflr 28; /* save LR */ \
94 mfcr 29; /* save CR */ \
95 mfsrr1 31; /* Test whether we already had PR set */ \
97 bc 4,17,1f; /* branch if PSL_PR is clear */ \
99 addi 1,1,USPACE; /* stack is top of user struct */ \
102 #define CRITICAL_PROLOG(savearea) \
103 mtsprg 1,1; /* save SP */ \
104 stmw 28,savearea(0); /* free r28-r31 */ \
105 mflr 28; /* save LR */ \
106 mfcr 29; /* save CR */ \
107 mfsrr2 30; /* Fake a standard trap */ \
109 mfsrr3 31; /* Test whether we already had PR set */ \
112 bc 4,17,1f; /* branch if PSL_PR is clear */ \
114 addi 1,1,USPACE; /* stack is top of user struct */ \
118 /* Standard handler saves r1,r28-31,LR,CR, sets up the stack and calls s_trap */
119 #define STANDARD_EXC_HANDLER(name)\
120 .globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
121 _C_LABEL(name ## trap): \
122 STANDARD_PROLOG(tempsave); \
124 _C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
126 /* Access exceptions also need DEAR and ESR saved */
127 #define ACCESS_EXC_HANDLER(name)\
128 .globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
129 _C_LABEL(name ## trap): \
130 STANDARD_PROLOG(tempsave); \
133 stmw 30,16+tempsave(0); \
135 _C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
137 /* Maybe this should call ddb.... */
138 #define CRITICAL_EXC_HANDLER(name)\
139 .globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
140 _C_LABEL(name ## trap): \
141 CRITICAL_PROLOG(tempsave); \
143 _C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
146 * This code gets copied to all the trap vectors
147 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
148 * traps when using IPKDB).
151 STANDARD_EXC_HANDLER(default)
152 ACCESS_EXC_HANDLER(ali)
153 ACCESS_EXC_HANDLER(dsi)
154 ACCESS_EXC_HANDLER(isi)
155 STANDARD_EXC_HANDLER(debug)
156 CRITICAL_EXC_HANDLER(mchk)
159 * This one for the external interrupt handler.
161 .globl _C_LABEL(extint),_C_LABEL(extsize)
163 mtsprg 1,1 /* save SP */
164 stmw 28,tempsave(0) /* free r28-r31 */
165 mflr 28 /* save LR */
166 mfcr 29 /* save CR */
167 mfxer 30 /* save XER */
169 lwz 31,CI_INTRDEPTH(1) /* were we already running on intstk? */
171 stw 31,CI_INTRDEPTH(1)
172 lwz 1,CI_INTSTK(1) /* get intstk */
174 mfsprg 1,1 /* yes, get old SP */
177 _C_LABEL(extsize) = .-_C_LABEL(extint)
180 #if defined(DDB) || defined(KGDB)
181 #define ddbsave 0xde0 /* primary save area for DDB */
183 * In case of DDB we want a separate trap catcher for it
186 .comm ddbstk,INTSTK,8 /* ddb stack */
188 .globl _C_LABEL(ddblow),_C_LABEL(ddbsize)
190 mtsprg 1,1 /* save SP */
191 stmw 28,ddbsave(0) /* free r28-r31 */
192 mflr 28 /* save LR */
193 mfcr 29 /* save CR */
194 lis 1,ddbstk+INTSTK@ha /* get new SP */
195 addi 1,1,ddbstk+INTSTK@l
197 _C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
198 #endif /* DDB || KGDB */
201 #define ipkdbsave 0xde0 /* primary save area for IPKDB */
203 * In case of IPKDB we want a separate trap catcher for it
207 .comm ipkdbstk,INTSTK,8 /* ipkdb stack */
209 .globl _C_LABEL(ipkdblow),_C_LABEL(ipkdbsize)
211 mtsprg 1,1 /* save SP */
212 stmw 28,ipkdbsave(0) /* free r28-r31 */
213 mflr 28 /* save LR */
214 mfcr 29 /* save CR */
215 lis 1,ipkdbstk+INTSTK@ha /* get new SP */
216 addi 1,1,ipkdbstk+INTSTK@l
218 _C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow)
222 #define TRAP_IF_ZERO(r) tweqi r,0
224 #define TRAP_IF_ZERO(r)
228 * FRAME_SETUP assumes:
230 * savearea r28-r31,DEAR,ESR (DEAR & ESR only for DSI traps)
235 * SRR0/1 as at start of trap
237 #define FRAME_SETUP(savearea) \
238 /* Have to enable translation to allow access of kernel stack: */ \
241 stmw 30,savearea+24(0); \
246 ori 31,31,(PSL_DR|PSL_IR)@l; \
250 stwu 31,-FRAMELEN(1); \
251 stw 30,FRAME_PID+8(1); \
252 stw 0,FRAME_0+8(1); \
253 stw 31,FRAME_1+8(1); \
254 stw 28,FRAME_LR+8(1); \
255 stw 29,FRAME_CR+8(1); \
256 lmw 28,savearea(0); \
257 stmw 2,FRAME_2+8(1); \
258 lmw 28,savearea+16(0); \
263 stw 3,FRAME_XER+8(1); \
264 stw 4,FRAME_CTR+8(1); \
265 stw 5,FRAME_EXC+8(1); \
266 stw 28,FRAME_DEAR+8(1); \
267 stw 29,FRAME_ESR+8(1); \
268 stw 30,FRAME_SRR0+8(1); \
269 stw 31,FRAME_SRR1+8(1)
271 #define FRAME_LEAVE(savearea) \
272 /* Now restore regs: */ \
273 lwz 3,FRAME_PID+8(1); \
274 lwz 4,FRAME_SRR1+8(1); \
275 bl _C_LABEL(ctx_setup); \
277 stw 3,FRAME_PID+8(1); \
278 lmw 26,FRAME_LR+8(1); \
285 lmw 2,FRAME_2+8(1); \
286 lwz 0,FRAME_0+8(1); \
287 stmw 29,savearea(0); \
288 lwz 30,FRAME_PID+8(1); \
289 lwz 1,FRAME_1+8(1); \
291 li 29,(PSL_DR|PSL_IR)@l; \
301 realtrap: /* entry point after IPKDB is done with exception */
302 /* Test whether we already had PR set */
305 mfsprg 1,1 /* restore SP (might have been
307 bc 4,17,s_trap /* branch if PSL_PR is false */
309 addi 1,1,USPACE /* stack is top of user struct */
311 * Now the common trap catching code.
314 FRAME_SETUP(tempsave)
315 /* Now we can recover interrupts again: */
317 wrteei 1 /* Enable interrupts */
318 /* Call C trap code: */
321 .globl _C_LABEL(trapexit)
323 /* Disable interrupts: */
325 /* Test AST pending: */
326 lwz 5,FRAME_SRR1+8(1)
328 bc 4,17,1f /* branch if PSL_PR is false */
330 lwz 4,CI_ASTPENDING(3)
337 FRAME_LEAVE(exitsave)
339 ba . /* Protect against prefetch */
343 .globl _C_LABEL(sctrap),_C_LABEL(scsize),_C_LABEL(sctrapexit)
345 STANDARD_PROLOG(tempsave);
347 _C_LABEL(scsize) = .-_C_LABEL(sctrap)
350 FRAME_SETUP(tempsave)
351 /* Now we can recover interrupts again: */
352 wrteei 1 /* Enable interrupts */
353 /* Call the appropriate syscall handler: */
358 lwz 4,P_MD_SYSCALL(4)
361 _C_LABEL(sctrapexit):
362 /* Disable interrupts: */
364 /* Test AST pending: */
365 lwz 5,FRAME_SRR1+8(1)
367 bc 4,17,1f /* branch if PSL_PR is false */
369 lwz 4,CI_ASTPENDING(3)
376 FRAME_LEAVE(exitsave)
378 ba . /* Protect against prefetch */
382 * External interrupt second level handler
386 /* Save non-volatile registers: */ \
387 stwu 1,-IFRAMELEN(1); /* temporarily */ \
388 stw 0,IFRAME_R0(1); \
389 mfsprg 0,1; /* get original SP */ \
390 stw 0,IFRAME_R1(1); /* and store it */ \
391 stw 3,IFRAME_R3(1); \
392 stw 4,IFRAME_R4(1); \
393 stw 5,IFRAME_R5(1); \
394 stw 6,IFRAME_R6(1); \
395 stw 7,IFRAME_R7(1); \
396 stw 8,IFRAME_R8(1); \
397 stw 9,IFRAME_R9(1); \
398 stw 10,IFRAME_R10(1); \
399 stw 11,IFRAME_R11(1); \
400 stw 12,IFRAME_R12(1); \
401 stw 28,IFRAME_LR(1); /* saved LR */ \
402 stw 29,IFRAME_CR(1); /* saved CR */ \
403 stw 30,IFRAME_XER(1); /* saved XER */ \
404 lmw 28,tempsave(0); /* restore r28-r31 */ \
407 lwz 5,CI_INTRDEPTH(5); \
410 stw 6,IFRAME_CTR(1); \
411 stw 5,IFRAME_INTR_DEPTH(1); \
412 stw 4,IFRAME_SRR0(1); \
413 stw 3,IFRAME_SRR1(1); \
414 mfpid 0; /* get currect PID register */ \
415 stw 0,IFRAME_PID(1); \
418 /* interrupts are recoverable here, and enable translation */ \
420 ori 5,5,(PSL_IR|PSL_DR); \
424 .globl _C_LABEL(extint_call)
427 _C_LABEL(extint_call):
428 bl _C_LABEL(extint_call) /* to be filled in later */
431 /* Disable interrupts (should already be disabled) and MMU here: */
435 lwz 4,IFRAME_SRR1(1) /* Load srr1 */
436 bl _C_LABEL(ctx_setup) /* Get proper ctx */
438 lis 4,(PSL_EE|PSL_DR|PSL_IR)@h
439 ori 4,4,(PSL_EE|PSL_DR|PSL_IR)@l
443 mtpid 3 /* Load CTX */
445 /* restore possibly overwritten registers: */
460 /* Returning to user mode? */
462 lwz 4,CI_INTRDEPTH(5)
463 addi 4,4,-1 /* adjust reentrancy count */
464 stw 4,CI_INTRDEPTH(5)
465 mtcr 6 /* saved SRR1 */
466 bc 4,17,1f /* branch if PSL_PR is false */
468 lwz 4,CI_ASTPENDING(5) /* Test AST pending */
471 /* Setup for entry to realtrap: */
472 lwz 3,0(1) /* get saved SP */
475 stmw 28,tempsave(0) /* establish tempsave again */
477 lwz 28,IFRAME_LR(1) /* saved LR */
478 lwz 29,IFRAME_CR(1) /* saved CR */
486 /* Here is the normal exit of extintr: */
498 ba . /* Protect against prefetch */
501 * PIT interrupt handler.
505 mtsprg 1,1 /* save SP */
506 stmw 28,tempsave(0) /* free r28-r31 */
507 mflr 28 /* save LR */
508 mfcr 29 /* save CR */
509 mfxer 30 /* save XER */
511 lwz 31,CI_INTRDEPTH(1) /* were we already running on intstk? */
513 stw 31,CI_INTRDEPTH(1)
514 lwz 1,CI_INTSTK(1) /* get intstk */
516 mfsprg 1,1 /* yes, get old SP */
519 addi 3,1,8 /* intr frame */
520 bl _C_LABEL(decr_intr)
524 * FIT interrupt handler.
528 mtsprg 1,1 /* save SP */
529 stmw 28,tempsave(0) /* free r28-r31 */
530 mflr 28 /* save LR */
531 mfcr 29 /* save CR */
532 mfxer 30 /* save XER */
534 lwz 31,CI_INTRDEPTH(1) /* were we already running on intstk? */
536 stw 31,CI_INTRDEPTH(1)
537 lwz 1,CI_INTSTK(1) /* get intstk */
539 mfsprg 1,1 /* yes, get old SP */
542 addi 3,1,8 /* intr frame */
543 bl _C_LABEL(stat_intr)
546 #if defined(DDB) || defined(KGDB)
548 * Deliberate entry to ddbtrap
550 .globl _C_LABEL(ddb_trap)
555 wrteei 0 /* disable interrupts */
565 * Now the ddb/kgdb trap catching code.
569 /* Call C trap code: */
571 bl _C_LABEL(ddb_trap_glue)
574 /* This wasn't for DDB, so switch to real trap: */
575 lwz 3,FRAME_EXC+8(1) /* save exception */
578 mtsprg 1,1 /* prepare for entrance to realtrap */
588 ba . /* Protect against prefetch */
589 #endif /* DDB || KGDB */
593 * Deliberate entry to ipkdbtrap
595 .globl _C_LABEL(ipkdb_trap)
596 _C_LABEL(ipkdb_trap):
600 wrteei 0 /* disable interrupts */
610 * Now the ipkdb trap catching code.
613 FRAME_SETUP(ipkdbsave)
614 /* Call C trap code: */
616 bl _C_LABEL(ipkdb_trap_glue)
619 /* This wasn't for IPKDB, so switch to real trap: */
620 lwz 3,FRAME_EXC+8(1) /* save exception */
622 FRAME_LEAVE(ipkdbsave)
623 mtsprg 1,1 /* prepare for entrance to realtrap */
627 lwz 31,ipkdbsave+8(0)
631 FRAME_LEAVE(ipkdbsave)
633 ba . /* Protect against prefetch */
643 ba . /* Protect against prefetch */
646 * int ipkdbfbyte(unsigned char *p)
648 .globl _C_LABEL(ipkdbfbyte)
649 _C_LABEL(ipkdbfbyte):
650 li 9,EXC_DSI /* establish new fault routine */
653 lwz 6,ipkdbfault@l(6)
657 lis 8,_C_LABEL(ipkdbsr)@ha
658 lwz 8,_C_LABEL(ipkdbsr)@l(8)
663 dcbst 0,9 /* flush data... */
665 icbi 0,9 /* and instruction caches */
666 lbz 3,0(3) /* fetch data */
667 stw 5,0(9) /* restore previous fault handler */
668 dcbst 0,9 /* and flush data... */
670 icbi 0,9 /* and instruction caches */
674 * int ipkdbsbyte(unsigned char *p, int c)
676 .globl _C_LABEL(ipkdbsbyte)
677 _C_LABEL(ipkdbsbyte):
678 li 9,EXC_DSI /* establish new fault routine */
681 lwz 6,ipkdbfault@l(6)
685 lis 8,_C_LABEL(ipkdbsr)@ha
686 lwz 8,_C_LABEL(ipkdbsr)@l(8)
691 dcbst 0,9 /* flush data... */
693 icbi 0,9 /* and instruction caches */
697 dcbst 0,6 /* Now do appropriate flushes
700 icbi 0,6 /* and instruction caches */
701 stw 5,0(9) /* restore previous fault handler */
702 dcbst 0,9 /* and flush data... */
704 icbi 0,9 /* and instruction caches */