Annotation of src/sys/arch/macppc/macppc/locore.S, Revision 1.22
1.22 ! thorpej 1: /* $NetBSD: locore.S,v 1.21 2000/03/24 17:05:32 ws Exp $ */
1.1 tsubai 2:
3: /*
4: * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5: * Copyright (C) 1995, 1996 TooLs GmbH.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by TooLs GmbH.
19: * 4. The name of TooLs GmbH may not be used to endorse or promote products
20: * derived from this software without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
1.4 jonathan 34: #include "opt_ddb.h"
1.21 ws 35: #include "opt_ipkdb.h"
1.1 tsubai 36: #include "assym.h"
37:
38: #include <sys/syscall.h>
39:
40: #include <machine/param.h>
41: #include <machine/pmap.h>
42: #include <machine/psl.h>
43: #include <machine/trap.h>
44: #include <machine/asm.h>
45:
46: /*
47: * Some instructions gas doesn't understand (yet?)
48: */
49: #define bdneq bdnzf 2,
50:
51: /*
52: * Globals
53: */
54: .data
55: GLOBAL(esym)
56: .long 0 /* end of symbol table */
57: GLOBAL(proc0paddr)
58: .long 0 /* proc0 p_addr */
59:
60: GLOBAL(intrnames)
61: .asciz "irq0", "irq1", "irq2", "irq3"
62: .asciz "irq4", "irq5", "irq6", "irq7"
63: .asciz "irq8", "irq9", "irq10", "irq11"
64: .asciz "irq12", "irq13", "irq14", "irq15"
65: .asciz "irq16", "irq17", "irq18", "irq19"
66: .asciz "irq20", "irq21", "irq22", "irq23"
67: .asciz "irq24", "irq25", "irq26", "irq27"
68: .asciz "irq28", "irq29", "irq30", "irq31"
1.9 tsubai 69: .asciz "irq32", "irq33", "irq34", "irq35"
70: .asciz "irq36", "irq37", "irq38", "irq39"
71: .asciz "irq40", "irq41", "irq42", "irq43"
72: .asciz "irq44", "irq45", "irq46", "irq47"
73: .asciz "irq48", "irq49", "irq50", "irq51"
74: .asciz "irq52", "irq53", "irq54", "irq55"
75: .asciz "irq56", "irq57", "irq58", "irq59"
76: .asciz "irq60", "irq61", "irq62", "irq63"
77: .asciz "clock", "softclock", "softnet", "softserial"
1.1 tsubai 78: GLOBAL(eintrnames)
79: .align 4
80: GLOBAL(intrcnt)
81: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
82: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1.9 tsubai 83: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
84: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
85: .long 0,0,0,0
1.1 tsubai 86: GLOBAL(eintrcnt)
87:
1.10 tsubai 88: GLOBAL(ofmsr)
89: .long 0 /* msr used in Open Firmware */
1.8 tsubai 90:
1.20 tsubai 91: GLOBAL(powersave)
92: .long 0
93:
1.1 tsubai 94: /*
95: * File-scope for locore.S
96: */
97: idle_u:
98: .long 0 /* fake uarea during idle after exit */
99: openfirmware_entry:
100: .long 0 /* openfirmware entry point */
1.11 tsubai 101: srsave:
102: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1.1 tsubai 103:
104: /*
105: * This symbol is here for the benefit of kvm_mkdb, and is supposed to
106: * mark the start of kernel text.
107: */
108: .text
109: .globl _C_LABEL(kernel_text)
110: _C_LABEL(kernel_text):
111:
112: /*
113: * Startup entry. Note, this must be the first thing in the text
114: * segment!
115: */
116: .text
117: .globl __start
118: __start:
119: #ifdef FIRMWORKSBUGS
120: mfmsr 0
121: andi. 0,0,PSL_IR|PSL_DR
122: beq 1f
123:
124: bl _C_LABEL(ofwr_init)
125: 1:
126: #endif
1.5 tsubai 127: mfmsr 0
1.8 tsubai 128: lis 9,ofmsr@ha
129: stw 0,ofmsr@l(9)
1.5 tsubai 130:
1.1 tsubai 131: li 0,0
132: mtmsr 0 /* Disable FPU/MMU/exceptions */
133: isync
134:
135: /* compute end of kernel memory */
136: lis 8,_C_LABEL(end)@ha
137: addi 8,8,_C_LABEL(end)@l
138: #ifdef DDB
1.14 tsubai 139: /* skip symbol table */
1.15 tsubai 140: cmpwi 6,0
141: beq 1f
1.14 tsubai 142: add 9,6,7 /* r9 = args + l */
143: lwz 9,-8(9) /* esym */
144: cmpwi 9,0
145: beq 1f
146: mr 8,9
147: 1:
1.1 tsubai 148: #endif
149: li 9,PGOFSET
150: add 8,8,9
151: andc 8,8,9
152: lis 9,_C_LABEL(OF_buf)@ha
153: stw 8,_C_LABEL(OF_buf)@l(9)
154: addi 8,8,NBPG
155: lis 9,idle_u@ha
156: stw 8,idle_u@l(9)
157: addi 8,8,USPACE /* space for idle_u */
158: lis 9,_C_LABEL(proc0paddr)@ha
159: stw 8,_C_LABEL(proc0paddr)@l(9)
160: addi 1,8,USPACE-FRAMELEN /* stackpointer for proc0 */
161: mr 4,1 /* end of mem reserved for kernel */
162: xor 0,0,0
163: stwu 0,-16(1) /* end of stack chain */
164:
165: lis 8,openfirmware_entry@ha
166: stw 5,openfirmware_entry@l(8) /* save client interface handler */
167: lis 3,__start@ha
168: addi 3,3,__start@l
169: mr 5,6 /* args string */
170: bl _C_LABEL(initppc)
171: bl _C_LABEL(main)
172: b _C_LABEL(OF_exit)
173:
174: /*
175: * OpenFirmware entry point
176: */
177: ENTRY(openfirmware)
178: mflr 0 /* save return address */
179: stw 0,4(1)
180: stwu 1,-16(1) /* setup stack frame */
181:
182: mfmsr 4 /* save msr */
183: stw 4,8(1)
184:
185: lis 4,openfirmware_entry@ha /* get firmware entry point */
186: lwz 4,openfirmware_entry@l(4)
187: mtlr 4
1.16 tsubai 188:
189: li 0,0 /* clear battable translations */
190: mtdbatu 2,0
191: mtdbatu 3,0
192: mtibatu 2,0
193: mtibatu 3,0
1.1 tsubai 194:
1.8 tsubai 195: lis 4,ofmsr@ha /* Open Firmware msr */
196: lwz 4,ofmsr@l(4)
1.5 tsubai 197: mtmsr 4
1.1 tsubai 198: isync
199:
1.11 tsubai 200: lis 4,srsave@ha /* save old SR */
201: addi 4,4,srsave@l
202: li 5,0
203: 1: mfsrin 0,5
204: stw 0,0(4)
205: addi 4,4,4
206: addis 5,5,0x10000000@h
207: cmpwi 5,0
208: bne 1b
209:
210: lis 4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */
211: addi 4,4,_C_LABEL(ofw_pmap)@l
212: lwz 0,PM_KERNELSR(4)
213: cmpwi 0,0 /* pm_sr[KERNEL_SR] == 0? */
214: beq 2f /* then skip (not initialized yet) */
215: li 5,0
216: 1: lwz 0,0(4)
217: mtsrin 0,5
218: addi 4,4,4
219: addis 5,5,0x10000000@h
220: cmpwi 5,0
221: bne 1b
222: 2:
1.8 tsubai 223: blrl /* call Open Firmware */
1.11 tsubai 224:
225: lis 4,srsave@ha /* restore saved SR */
226: addi 4,4,srsave@l
227: li 5,0
1.12 tsubai 228: 1: lwz 0,0(4)
229: mtsrin 0,5
1.11 tsubai 230: addi 4,4,4
231: addis 5,5,0x10000000@h
232: cmpwi 5,0
233: bne 1b
1.1 tsubai 234:
235: lwz 4,8(1) /* restore msr */
236: mtmsr 4
237: isync
238:
239: lwz 1,0(1) /* and return */
240: lwz 0,4(1)
241: mtlr 0
242: blr
243:
244: /*
245: * Switch to/from OpenFirmware real mode stack
246: *
247: * Note: has to be called as the very first thing in OpenFirmware interface
248: * routines.
249: * E.g.:
250: * int
251: * OF_xxx(arg1, arg2)
252: * type arg1, arg2;
253: * {
254: * static struct {
255: * char *name;
256: * int nargs;
257: * int nreturns;
258: * char *method;
259: * int arg1;
260: * int arg2;
261: * int ret;
262: * } args = {
263: * "xxx",
264: * 2,
265: * 1,
266: * };
267: *
268: * ofw_stack();
269: * args.arg1 = arg1;
270: * args.arg2 = arg2;
271: * if (openfirmware(&args) < 0)
272: * return -1;
273: * return args.ret;
274: * }
275: */
276:
277: .local firmstk
278: .comm firmstk,NBPG,8
279:
280: ENTRY(ofw_stack)
281: mfmsr 8 /* turn off interrupts */
282: andi. 0,8,~(PSL_EE|PSL_RI)@l
283: mtmsr 0
284: stw 8,4(1) /* abuse return address slot */
285:
286: lwz 5,0(1) /* get length of stack frame */
287: subf 5,1,5
288:
289: lis 7,firmstk+NBPG-8@ha
290: addi 7,7,firmstk+NBPG-8@l
291: lis 6,ofw_back@ha
292: addi 6,6,ofw_back@l
293: subf 4,5,7 /* make room for stack frame on
294: new stack */
295: stw 6,-4(7) /* setup return pointer */
296: stwu 1,-8(7)
297:
298: stw 7,-8(4)
299:
300: addi 3,1,8
301: addi 1,4,-8
302: subi 5,5,8
303:
304: b _C_LABEL(ofbcopy) /* and copy it */
305:
306: ofw_back:
307: lwz 1,0(1) /* get callers original stack pointer */
308:
309: lwz 0,4(1) /* get saved msr from abused slot */
310: mtmsr 0
311:
312: lwz 1,0(1) /* return */
313: lwz 0,4(1)
314: mtlr 0
315: blr
316:
317:
318: /*
319: * No processes are runnable, so loop waiting for one.
320: * Separate label here for accounting purposes.
321: */
322: ASENTRY(Idle)
323: mfmsr 3
324: andi. 3,3,~PSL_EE@l /* disable interrupts while
325: manipulating runque */
326: mtmsr 3
327:
328: lis 8,_C_LABEL(whichqs)@ha
329: lwz 9,_C_LABEL(whichqs)@l(8)
330:
331: or. 9,9,9
332: bne- .Lsw1 /* at least one queue non-empty */
333:
334: ori 3,3,PSL_EE@l /* reenable ints again */
335: mtmsr 3
336: isync
337:
1.20 tsubai 338: /* Check if we can use power saving mode */
339: lis 8,_C_LABEL(powersave)@ha
340: lwz 9,_C_LABEL(powersave)@l(8)
341:
342: or. 9,9,9
343: beq 1f
344:
345: sync
346: oris 3,3,PSL_POW@h /* enter power saving mode */
347: mtmsr 3
348: isync
349: 1:
1.1 tsubai 350: b _ASM_LABEL(Idle)
351:
352: /*
1.6 thorpej 353: * switchexit gets called from cpu_exit to complete the exit procedure.
1.1 tsubai 354: */
355: ENTRY(switchexit)
356: /* First switch to the idle pcb/kernel stack */
357: lis 6,idle_u@ha
358: lwz 6,idle_u@l(6)
359: lis 7,_C_LABEL(curpcb)@ha
360: stw 6,_C_LABEL(curpcb)@l(7)
361: addi 1,6,USPACE-16 /* 16 bytes are reserved at stack top */
1.6 thorpej 362: /*
363: * Schedule the vmspace and stack to be freed (the proc arg is
364: * already in r3).
365: */
366: bl _C_LABEL(exit2)
367:
1.1 tsubai 368: /* Fall through to cpu_switch to actually select another proc */
369: li 3,0 /* indicate exited process */
370:
371: /*
372: * void cpu_switch(struct proc *p)
373: * Find a runnable process and switch to it.
374: */
375: /* XXX noprofile? --thorpej@netbsd.org */
376: ENTRY(cpu_switch)
377: mflr 0 /* save lr */
378: stw 0,4(1)
379: stwu 1,-16(1)
380: stw 31,12(1)
381: stw 30,8(1)
382:
383: mr 30,3
384: lis 3,_C_LABEL(curproc)@ha
385: xor 31,31,31
386: stw 31,_C_LABEL(curproc)@l(3) /* Zero to not accumulate cpu time */
387: lis 3,_C_LABEL(curpcb)@ha
388: lwz 31,_C_LABEL(curpcb)@l(3)
389:
390: xor 3,3,3
391: bl _C_LABEL(lcsplx)
392: stw 3,PCB_SPL(31) /* save spl */
393:
394: /* Find a new process */
395: mfmsr 3
396: andi. 3,3,~PSL_EE@l /* disable interrupts while
397: manipulating runque */
398: mtmsr 3
399: isync
400:
401: lis 8,_C_LABEL(whichqs)@ha
402: lwz 9,_C_LABEL(whichqs)@l(8)
403:
404: or. 9,9,9
405: beq- _ASM_LABEL(Idle) /* all queues empty */
406: .Lsw1:
407: cntlzw 10,9
408: lis 4,_C_LABEL(qs)@ha
409: addi 4,4,_C_LABEL(qs)@l
410: slwi 3,10,3
411: add 3,3,4 /* select queue */
412:
413: lwz 31,P_FORW(3) /* unlink first proc from queue */
414: lwz 4,P_FORW(31)
415: stw 4,P_FORW(3)
416: stw 3,P_BACK(4)
417:
418: cmpl 0,3,4 /* queue empty? */
419: bne 1f
420:
421: lis 3,0x80000000@h
422: srw 3,3,10
423: andc 9,9,3
424: stw 9,_C_LABEL(whichqs)@l(8) /* mark it empty */
425:
426: 1:
427: /* just did this resched thing */
428: xor 3,3,3
429: lis 4,_C_LABEL(want_resched)@ha
430: stw 3,_C_LABEL(want_resched)@l(4)
431:
432: stw 3,P_BACK(31) /* probably superfluous */
1.22 ! thorpej 433:
! 434: /* Process now running on a processor. */
! 435: li 3,SONPROC /* p->p_stat = SONPROC */
! 436: stb 3,P_STAT(31)
1.1 tsubai 437:
438: /* record new process */
439: lis 4,_C_LABEL(curproc)@ha
440: stw 31,_C_LABEL(curproc)@l(4)
441:
442: mfmsr 3
443: ori 3,3,PSL_EE@l /* Now we can interrupt again */
444: mtmsr 3
445:
446: cmpl 0,31,30 /* is it the same process? */
447: beq switch_return
448:
449: or. 30,30,30 /* old process was exiting? */
450: beq switch_exited
451:
452: mfsr 10,USER_SR /* save USER_SR for copyin/copyout */
453: mfcr 11 /* save cr */
454: mr 12,2 /* save r2 */
455: stwu 1,-SFRAMELEN(1) /* still running on old stack */
456: stmw 10,8(1)
457: lwz 3,P_ADDR(30)
458: stw 1,PCB_SP(3) /* save SP */
459:
460: switch_exited:
461: mfmsr 3
462: andi. 3,3,~PSL_EE@l /* disable interrupts while
463: actually switching */
464: mtmsr 3
465:
466: /* indicate new pcb */
467: lwz 4,P_ADDR(31)
468: lis 5,_C_LABEL(curpcb)@ha
469: stw 4,_C_LABEL(curpcb)@l(5)
470:
471: /* save real pmap pointer for spill fill */
472: lwz 5,PCB_PMR(4)
473: lis 6,_C_LABEL(curpm)@ha
474: stwu 5,_C_LABEL(curpm)@l(6)
475: stwcx. 5,0,6 /* clear possible reservation */
476:
477: addic. 5,5,64
478: li 6,0
479: mfsr 8,KERNEL_SR /* save kernel SR */
480: 1:
481: addis 6,6,-0x10000000@ha /* set new procs segment registers */
482: or. 6,6,6 /* This is done from the real
483: address pmap */
484: lwzu 7,-4(5) /* so we don't have to worry */
485: mtsrin 7,6 /* about accessibility */
486: bne 1b
487: mtsr KERNEL_SR,8 /* restore kernel SR */
488: isync
489:
490: lwz 1,PCB_SP(4) /* get new procs SP */
491:
492: ori 3,3,PSL_EE@l /* interrupts are okay again */
493: mtmsr 3
494:
495: lmw 10,8(1) /* get other regs */
496: lwz 1,0(1) /* get saved SP */
497: mr 2,12 /* get saved r2 */
498: mtcr 11 /* get saved cr */
499: isync
500: mtsr USER_SR,10 /* get saved USER_SR */
501: isync
502:
503: switch_return:
504: mr 30,7 /* save proc pointer */
505: lwz 3,PCB_SPL(4)
506: bl _C_LABEL(lcsplx)
507:
508: mr 3,30 /* get curproc for special fork
509: returns */
510:
511: lwz 31,12(1)
512: lwz 30,8(1)
513: addi 1,1,16
514: lwz 0,4(1)
515: mtlr 0
516: blr
517:
518:
519: /*
520: * Data used during primary/secondary traps/interrupts
521: */
522: #define tempsave 0x2e0 /* primary save area for trap handling */
523: #define disisave 0x3e0 /* primary save area for dsi/isi traps */
524:
525: #define INTSTK (8*1024) /* 8K interrupt stack */
526: .data
527: .align 4
528: intstk:
529: .space INTSTK /* interrupt stack */
530:
531: GLOBAL(intr_depth)
532: .long -1 /* in-use marker */
533:
534: #define SPILLSTK 1024 /* 1K spill stack */
535:
536: .comm spillstk,SPILLSTK,8
537:
538: /*
539: * This code gets copied to all the trap vectors
1.19 danw 540: * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
541: * traps when using IPKDB).
1.1 tsubai 542: */
543: .text
544: .globl _C_LABEL(trapcode),_C_LABEL(trapsize)
545: _C_LABEL(trapcode):
546: mtsprg 1,1 /* save SP */
547: stmw 28,tempsave(0) /* free r28-r31 */
548: mflr 28 /* save LR */
549: mfcr 29 /* save CR */
550: /* Test whether we already had PR set */
551: mfsrr1 31
552: mtcr 31
553: bc 4,17,1f /* branch if PSL_PR is clear */
554: lis 1,_C_LABEL(curpcb)@ha
555: lwz 1,_C_LABEL(curpcb)@l(1)
556: addi 1,1,USPACE /* stack is top of user struct */
557: 1:
558: bla s_trap
559: _C_LABEL(trapsize) = .-_C_LABEL(trapcode)
1.19 danw 560:
561: /*
562: * For ALI: has to save DSISR and DAR
563: */
564: .globl _C_LABEL(alitrap),_C_LABEL(alisize)
565: _C_LABEL(alitrap):
566: mtsprg 1,1 /* save SP */
567: stmw 28,tempsave(0) /* free r28-r31 */
568: mfdar 30
569: mfdsisr 31
570: stmw 30,tempsave+16(0)
571: mflr 28 /* save LR */
572: mfcr 29 /* save CR */
573: /* Test whether we already had PR set */
574: mfsrr1 31
575: mtcr 31
576: bc 4,17,1f /* branch if PSL_PR is clear */
577: lis 1,_C_LABEL(curpcb)@ha
578: lwz 1,_C_LABEL(curpcb)@l(1)
579: addi 1,1,USPACE /* stack is top of user struct */
580: 1:
581: bla s_trap
582: _C_LABEL(alisize) = .-_C_LABEL(alitrap)
1.1 tsubai 583:
584: /*
585: * Similar to the above for DSI
586: * Has to handle BAT spills
587: * and standard pagetable spills
588: */
589: .globl _C_LABEL(dsitrap),_C_LABEL(dsisize)
590: _C_LABEL(dsitrap):
591: stmw 28,disisave(0) /* free r28-r31 */
592: mfcr 29 /* save CR */
593: mfxer 30 /* save XER */
594: mtsprg 2,30 /* in SPRG2 */
595: mfsrr1 31 /* test kernel mode */
596: mtcr 31
597: bc 12,17,1f /* branch if PSL_PR is set */
598: mfdar 31 /* get fault address */
599: rlwinm 31,31,7,25,28 /* get segment * 8 */
600:
601: /* get batu */
602: addis 31,31,_C_LABEL(battable)@ha
603: lwz 30,_C_LABEL(battable)@l(31)
604: mtcr 30
605: bc 4,30,1f /* branch if supervisor valid is
606: false */
607: /* get batl */
608: lwz 31,_C_LABEL(battable)+4@l(31)
609: /* We randomly use the highest two bat registers here */
610: mftb 28
611: andi. 28,28,1
612: bne 2f
613: mtdbatu 2,30
614: mtdbatl 2,31
615: b 3f
616: 2:
617: mtdbatu 3,30
618: mtdbatl 3,31
619: 3:
620: mfsprg 30,2 /* restore XER */
621: mtxer 30
622: mtcr 29 /* restore CR */
623: lmw 28,disisave(0) /* restore r28-r31 */
624: rfi /* return to trapped code */
625: 1:
626: mflr 28 /* save LR */
627: bla s_dsitrap
628: _C_LABEL(dsisize) = .-_C_LABEL(dsitrap)
629:
630: /*
631: * Similar to the above for ISI
632: */
633: .globl _C_LABEL(isitrap),_C_LABEL(isisize)
634: _C_LABEL(isitrap):
635: stmw 28,disisave(0) /* free r28-r31 */
636: mflr 28 /* save LR */
637: mfcr 29 /* save CR */
638: mfsrr1 31 /* test kernel mode */
639: mtcr 31
640: bc 12,17,1f /* branch if PSL_PR is set */
641: mfsrr0 31 /* get fault address */
642: rlwinm 31,31,7,25,28 /* get segment * 8 */
643:
644: /* get batu */
645: addis 31,31,_C_LABEL(battable)@ha
646: lwz 30,_C_LABEL(battable)@l(31)
647: mtcr 30
648: bc 4,30,1f /* branch if supervisor valid is
649: false */
650: mtibatu 3,30
651:
652: /* get batl */
653: lwz 30,_C_LABEL(battable)+4@l(31)
654: mtibatl 3,30
655:
656: mtcr 29 /* restore CR */
657: lmw 28,disisave(0) /* restore r28-r31 */
658: rfi /* return to trapped code */
659: 1:
660: bla s_isitrap
661: _C_LABEL(isisize)= .-_C_LABEL(isitrap)
662:
663: /*
664: * This one for the external interrupt handler.
665: */
666: .globl _C_LABEL(extint),_C_LABEL(extsize)
667: _C_LABEL(extint):
668: mtsprg 1,1 /* save SP */
669: stmw 28,tempsave(0) /* free r28-r31 */
670: mflr 28 /* save LR */
671: mfcr 29 /* save CR */
672: mfxer 30 /* save XER */
673: lis 1,intstk+INTSTK@ha /* get interrupt stack */
674: addi 1,1,intstk+INTSTK@l
675: lwz 31,0(1) /* were we already running on intstk? */
676: addic. 31,31,1
677: stw 31,0(1)
678: beq 1f
679: mfsprg 1,1 /* yes, get old SP */
680: 1:
681: ba extintr
682: _C_LABEL(extsize) = .-_C_LABEL(extint)
683:
684: /*
685: * And this one for the decrementer interrupt handler.
686: */
687: .globl _C_LABEL(decrint),_C_LABEL(decrsize)
688: _C_LABEL(decrint):
689: mtsprg 1,1 /* save SP */
690: stmw 28,tempsave(0) /* free r28-r31 */
691: mflr 28 /* save LR */
692: mfcr 29 /* save CR */
693: mfxer 30 /* save XER */
694: lis 1,intstk+INTSTK@ha /* get interrupt stack */
695: addi 1,1,intstk+INTSTK@l
696: lwz 31,0(1) /* were we already running on intstk? */
697: addic. 31,31,1
698: stw 31,0(1)
699: beq 1f
700: mfsprg 1,1 /* yes, get old SP */
701: 1:
702: ba decrintr
703: _C_LABEL(decrsize) = .-_C_LABEL(decrint)
704:
705: /*
706: * Now the tlb software load for 603 processors:
707: * (Code essentially from the 603e User Manual, Chapter 5, but
708: * corrected a lot.)
709: */
710: #define DMISS 976
711: #define DCMP 977
712: #define HASH1 978
713: #define HASH2 979
714: #define IMISS 980
715: #define ICMP 981
716: #define RPA 982
717:
718: .globl _C_LABEL(tlbimiss),_C_LABEL(tlbimsize)
719: _C_LABEL(tlbimiss):
720: mfspr 2,HASH1 /* get first pointer */
721: li 1,8
722: mfctr 0 /* save counter */
723: mfspr 3,ICMP /* get first compare value */
724: addi 2,2,-8 /* predec pointer */
725: 1:
726: mtctr 1 /* load counter */
727: 2:
728: lwzu 1,8(2) /* get next pte */
729: cmpl 0,1,3 /* see if found pte */
730: bdneq 2b /* loop if not eq */
731: bne 3f /* not found */
732: lwz 1,4(2) /* load tlb entry lower word */
733: andi. 3,1,8 /* check G-bit */
734: bne 4f /* if guarded, take ISI */
735: mtctr 0 /* restore counter */
736: mfspr 0,IMISS /* get the miss address for the tlbli */
737: mfsrr1 3 /* get the saved cr0 bits */
738: mtcrf 0x80,3 /* and restore */
739: ori 1,1,0x100 /* set the reference bit */
740: mtspr RPA,1 /* set the pte */
741: srwi 1,1,8 /* get byte 7 of pte */
742: tlbli 0 /* load the itlb */
743: stb 1,6(2) /* update page table */
744: rfi
745:
746: 3: /* not found in pteg */
747: andi. 1,3,0x40 /* have we already done second hash? */
748: bne 5f
749: mfspr 2,HASH2 /* get the second pointer */
750: ori 3,3,0x40 /* change the compare value */
751: li 1,8
752: addi 2,2,-8 /* predec pointer */
753: b 1b
754: 4: /* guarded */
755: mfsrr1 3
756: andi. 2,3,0xffff /* clean upper srr1 */
757: oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */
758: b 6f
759: 5: /* not found anywhere */
760: mfsrr1 3
761: andi. 2,3,0xffff /* clean upper srr1 */
762: oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */
763: 6:
764: mtctr 0 /* restore counter */
765: mtsrr1 2
766: mfmsr 0
767: xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */
768: mtcrf 0x80,3 /* restore cr0 */
769: mtmsr 0 /* now with native gprs */
770: isync
771: ba EXC_ISI
772: _C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss)
773:
774: .globl _C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize)
775: _C_LABEL(tlbdlmiss):
776: mfspr 2,HASH1 /* get first pointer */
777: li 1,8
778: mfctr 0 /* save counter */
779: mfspr 3,DCMP /* get first compare value */
780: addi 2,2,-8 /* predec pointer */
781: 1:
782: mtctr 1 /* load counter */
783: 2:
784: lwzu 1,8(2) /* get next pte */
785: cmpl 0,1,3 /* see if found pte */
786: bdneq 2b /* loop if not eq */
787: bne 3f /* not found */
788: lwz 1,4(2) /* load tlb entry lower word */
789: mtctr 0 /* restore counter */
790: mfspr 0,DMISS /* get the miss address for the tlbld */
791: mfsrr1 3 /* get the saved cr0 bits */
792: mtcrf 0x80,3 /* and restore */
793: ori 1,1,0x100 /* set the reference bit */
794: mtspr RPA,1 /* set the pte */
795: srwi 1,1,8 /* get byte 7 of pte */
796: tlbld 0 /* load the dtlb */
797: stb 1,6(2) /* update page table */
798: rfi
799:
800: 3: /* not found in pteg */
801: andi. 1,3,0x40 /* have we already done second hash? */
802: bne 5f
803: mfspr 2,HASH2 /* get the second pointer */
804: ori 3,3,0x40 /* change the compare value */
805: li 1,8
806: addi 2,2,-8 /* predec pointer */
807: b 1b
808: 5: /* not found anywhere */
809: mfsrr1 3
810: lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */
811: mtctr 0 /* restore counter */
812: andi. 2,3,0xffff /* clean upper srr1 */
813: mtsrr1 2
814: mtdsisr 1 /* load the dsisr */
815: mfspr 1,DMISS /* get the miss address */
816: mtdar 1 /* put in dar */
817: mfmsr 0
818: xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */
819: mtcrf 0x80,3 /* restore cr0 */
820: mtmsr 0 /* now with native gprs */
821: isync
822: ba EXC_DSI
823: _C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss)
824:
825: .globl _C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize)
826: _C_LABEL(tlbdsmiss):
827: mfspr 2,HASH1 /* get first pointer */
828: li 1,8
829: mfctr 0 /* save counter */
830: mfspr 3,DCMP /* get first compare value */
831: addi 2,2,-8 /* predec pointer */
832: 1:
833: mtctr 1 /* load counter */
834: 2:
835: lwzu 1,8(2) /* get next pte */
836: cmpl 0,1,3 /* see if found pte */
837: bdneq 2b /* loop if not eq */
838: bne 3f /* not found */
839: lwz 1,4(2) /* load tlb entry lower word */
840: andi. 3,1,0x80 /* check the C-bit */
841: beq 4f
842: 5:
843: mtctr 0 /* restore counter */
844: mfspr 0,DMISS /* get the miss address for the tlbld */
845: mfsrr1 3 /* get the saved cr0 bits */
846: mtcrf 0x80,3 /* and restore */
847: mtspr RPA,1 /* set the pte */
848: tlbld 0 /* load the dtlb */
849: rfi
850:
851: 3: /* not found in pteg */
852: andi. 1,3,0x40 /* have we already done second hash? */
853: bne 5f
854: mfspr 2,HASH2 /* get the second pointer */
855: ori 3,3,0x40 /* change the compare value */
856: li 1,8
857: addi 2,2,-8 /* predec pointer */
858: b 1b
859: 4: /* found, but C-bit = 0 */
860: rlwinm. 3,1,30,0,1 /* test PP */
861: bge- 7f
862: andi. 3,1,1
863: beq+ 8f
864: 9: /* found, but protection violation (PP==00)*/
865: mfsrr1 3
866: lis 1,0xa000000@h /* indicate protection violation
867: on store */
868: b 1f
869: 7: /* found, PP=1x */
870: mfspr 3,DMISS /* get the miss address */
871: mfsrin 1,3 /* get the segment register */
872: mfsrr1 3
873: rlwinm 3,3,18,31,31 /* get PR-bit */
874: rlwnm. 2,2,3,1,1 /* get the key */
875: bne- 9b /* protection violation */
876: 8: /* found, set reference/change bits */
877: lwz 1,4(2) /* reload tlb entry */
878: ori 1,1,0x180
879: sth 1,6(2)
880: b 5b
881: 5: /* not found anywhere */
882: mfsrr1 3
883: lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */
884: /* dsisr<6> to flag store */
885: 1:
886: mtctr 0 /* restore counter */
887: andi. 2,3,0xffff /* clean upper srr1 */
888: mtsrr1 2
889: mtdsisr 1 /* load the dsisr */
890: mfspr 1,DMISS /* get the miss address */
891: mtdar 1 /* put in dar */
892: mfmsr 0
893: xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */
894: mtcrf 0x80,3 /* restore cr0 */
895: mtmsr 0 /* now with native gprs */
896: isync
897: ba EXC_DSI
898: _C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss)
899:
900: #ifdef DDB
901: #define ddbsave 0xde0 /* primary save area for DDB */
902: /*
903: * In case of DDB we want a separate trap catcher for it
904: */
905: .local ddbstk
906: .comm ddbstk,INTSTK,8 /* ddb stack */
907:
908: .globl _C_LABEL(ddblow),_C_LABEL(ddbsize)
909: _C_LABEL(ddblow):
910: mtsprg 1,1 /* save SP */
911: stmw 28,ddbsave(0) /* free r28-r31 */
912: mflr 28 /* save LR */
913: mfcr 29 /* save CR */
914: lis 1,ddbstk+INTSTK@ha /* get new SP */
915: addi 1,1,ddbstk+INTSTK@l
916: bla ddbtrap
917: _C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
918: #endif /* DDB */
919:
1.21 ws 920: #ifdef IPKDB
1.1 tsubai 921: #define ipkdbsave 0xde0 /* primary save area for IPKDB */
922: /*
923: * In case of IPKDB we want a separate trap catcher for it
924: */
925:
926: .local ipkdbstk
927: .comm ipkdbstk,INTSTK,8 /* ipkdb stack */
928:
929: .globl _C_LABEL(ipkdblow),_C_LABEL(ipkdbsize)
930: _C_LABEL(ipkdblow):
931: mtsprg 1,1 /* save SP */
932: stmw 28,ipkdbsave(0) /* free r28-r31 */
933: mflr 28 /* save LR */
934: mfcr 29 /* save CR */
935: lis 1,ipkdbstk+INTSTK@ha /* get new SP */
936: addi 1,1,ipkdbstk+INTSTK@l
937: bla ipkdbtrap
938: _C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow)
1.21 ws 939: #endif /* IPKDB */
1.1 tsubai 940:
941: /*
942: * FRAME_SETUP assumes:
943: * SPRG1 SP (1)
944: * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps)
945: * 28 LR
946: * 29 CR
947: * 1 kernel stack
948: * LR trap type
949: * SRR0/1 as at start of trap
950: */
951: #define FRAME_SETUP(savearea) \
952: /* Have to enable translation to allow access of kernel stack: */ \
953: mfsrr0 30; \
954: mfsrr1 31; \
955: stmw 30,savearea+24(0); \
956: mfmsr 30; \
957: ori 30,30,(PSL_DR|PSL_IR); \
958: mtmsr 30; \
959: isync; \
960: mfsprg 31,1; \
961: stwu 31,-FRAMELEN(1); \
962: stw 0,FRAME_0+8(1); \
963: stw 31,FRAME_1+8(1); \
964: stw 28,FRAME_LR+8(1); \
965: stw 29,FRAME_CR+8(1); \
966: lmw 28,savearea(0); \
967: stmw 2,FRAME_2+8(1); \
968: lmw 28,savearea+16(0); \
969: mfxer 3; \
970: mfctr 4; \
971: mflr 5; \
972: andi. 5,5,0xff00; \
973: stw 3,FRAME_XER+8(1); \
974: stw 4,FRAME_CTR+8(1); \
975: stw 5,FRAME_EXC+8(1); \
976: stw 28,FRAME_DAR+8(1); \
977: stw 29,FRAME_DSISR+8(1); \
978: stw 30,FRAME_SRR0+8(1); \
979: stw 31,FRAME_SRR1+8(1)
980:
981: #define FRAME_LEAVE(savearea) \
982: /* Now restore regs: */ \
983: lwz 2,FRAME_SRR0+8(1); \
984: lwz 3,FRAME_SRR1+8(1); \
985: lwz 4,FRAME_CTR+8(1); \
986: lwz 5,FRAME_XER+8(1); \
987: lwz 6,FRAME_LR+8(1); \
988: lwz 7,FRAME_CR+8(1); \
989: stw 2,savearea(0); \
990: stw 3,savearea+4(0); \
991: mtctr 4; \
992: mtxer 5; \
993: mtlr 6; \
994: mtsprg 1,7; /* save cr */ \
995: lmw 2,FRAME_2+8(1); \
996: lwz 0,FRAME_0+8(1); \
997: lwz 1,FRAME_1+8(1); \
998: mtsprg 2,2; /* save r2 & r3 */ \
999: mtsprg 3,3; \
1000: /* Disable translation, machine check and recoverability: */ \
1001: mfmsr 2; \
1002: andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \
1003: mtmsr 2; \
1004: isync; \
1005: /* Decide whether we return to user mode: */ \
1006: lwz 3,savearea+4(0); \
1007: mtcr 3; \
1008: bc 4,17,1f; /* branch if PSL_PR is false */ \
1009: /* Restore user & kernel access SR: */ \
1010: lis 2,_C_LABEL(curpm)@ha; /* get real address of pmap */ \
1011: lwz 2,_C_LABEL(curpm)@l(2); \
1012: lwz 3,PM_USRSR(2); \
1013: mtsr USER_SR,3; \
1014: lwz 3,PM_KERNELSR(2); \
1015: mtsr KERNEL_SR,3; \
1016: 1: mfsprg 2,1; /* restore cr */ \
1017: mtcr 2; \
1018: lwz 2,savearea(0); \
1019: lwz 3,savearea+4(0); \
1020: mtsrr0 2; \
1021: mtsrr1 3; \
1022: mfsprg 2,2; /* restore r2 & r3 */ \
1023: mfsprg 3,3
1024:
1025: /*
1026: * Preamble code for DSI/ISI traps
1027: */
1028: disitrap:
1029: lmw 30,disisave(0)
1030: stmw 30,tempsave(0)
1031: lmw 30,disisave+8(0)
1032: stmw 30,tempsave+8(0)
1033: mfdar 30
1034: mfdsisr 31
1035: stmw 30,tempsave+16(0)
1036: realtrap:
1037: /* Test whether we already had PR set */
1038: mfsrr1 1
1039: mtcr 1
1040: mfsprg 1,1 /* restore SP (might have been
1041: overwritten) */
1042: bc 4,17,s_trap /* branch if PSL_PR is false */
1043: lis 1,_C_LABEL(curpcb)@ha
1044: lwz 1,_C_LABEL(curpcb)@l(1)
1045: addi 1,1,USPACE /* stack is top of user struct */
1046:
1047: /*
1048: * Now the common trap catching code.
1049: */
1050: s_trap:
1051: /* First have to enable KERNEL mapping */
1052: lis 31,KERNEL_SEGMENT@h
1053: ori 31,31,KERNEL_SEGMENT@l
1054: mtsr KERNEL_SR,31
1055: FRAME_SETUP(tempsave)
1056: /* Now we can recover interrupts again: */
1057: mfmsr 7
1058: ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l
1059: mtmsr 7
1060: isync
1061: /* Call C trap code: */
1062: trapagain:
1063: addi 3,1,8
1064: bl _C_LABEL(trap)
1065: trapexit:
1066: /* Disable interrupts: */
1067: mfmsr 3
1068: andi. 3,3,~PSL_EE@l
1069: mtmsr 3
1070: /* Test AST pending: */
1071: lwz 5,FRAME_SRR1+8(1)
1072: mtcr 5
1073: bc 4,17,1f /* branch if PSL_PR is false */
1074: lis 3,_C_LABEL(astpending)@ha
1075: lwz 4,_C_LABEL(astpending)@l(3)
1076: andi. 4,4,1
1077: beq 1f
1078: li 6,EXC_AST
1079: stw 6,FRAME_EXC+8(1)
1080: b trapagain
1081: 1:
1082: FRAME_LEAVE(tempsave)
1083: rfi
1084:
1085: /*
1086: * Child comes here at the end of a fork.
1087: * Mostly similar to the above.
1088: */
1089: .globl _C_LABEL(fork_trampoline)
1090: _C_LABEL(fork_trampoline):
1091: xor 3,3,3
1092: bl _C_LABEL(lcsplx)
1093: mtlr 31
1094: mr 3,30
1095: blrl /* jump indirect to r31 */
1096: b trapexit
1097:
1098: /*
1099: * DSI second stage fault handler
1100: */
1101: s_dsitrap:
1102: mfdsisr 31 /* test whether this may be a
1103: spill fault */
1104: mtcr 31
1105: mtsprg 1,1 /* save SP */
1106: bc 4,1,disitrap /* branch if table miss is false */
1107: lis 1,spillstk+SPILLSTK@ha
1108: addi 1,1,spillstk+SPILLSTK@l /* get spill stack */
1109: stwu 1,-52(1)
1110: stw 0,48(1) /* save non-volatile registers */
1111: stw 3,44(1)
1112: stw 4,40(1)
1113: stw 5,36(1)
1114: stw 6,32(1)
1115: stw 7,28(1)
1116: stw 8,24(1)
1117: stw 9,20(1)
1118: stw 10,16(1)
1119: stw 11,12(1)
1120: stw 12,8(1)
1121: mflr 30 /* save trap type */
1122: mfctr 31 /* & CTR */
1123: mfdar 3
1124: s_pte_spill:
1125: bl _C_LABEL(pte_spill) /* try a spill */
1126: or. 3,3,3
1127: mtctr 31 /* restore CTR */
1128: mtlr 30 /* and trap type */
1129: mfsprg 31,2 /* get saved XER */
1130: mtxer 31 /* restore XER */
1131: lwz 12,8(1) /* restore non-volatile registers */
1132: lwz 11,12(1)
1133: lwz 10,16(1)
1134: lwz 9,20(1)
1135: lwz 8,24(1)
1136: lwz 7,28(1)
1137: lwz 6,32(1)
1138: lwz 5,36(1)
1139: lwz 4,40(1)
1140: lwz 3,44(1)
1141: lwz 0,48(1)
1142: beq disitrap
1143: mfsprg 1,1 /* restore SP */
1144: mtcr 29 /* restore CR */
1145: mtlr 28 /* restore LR */
1146: lmw 28,disisave(0) /* restore r28-r31 */
1147: rfi /* return to trapped code */
1148:
1149: /*
1150: * ISI second stage fault handler
1151: */
1152: s_isitrap:
1153: mfsrr1 31 /* test whether this may be a
1154: spill fault */
1155: mtcr 31
1156: mtsprg 1,1 /* save SP */
1157: bc 4,1,disitrap /* branch if table miss is false */
1158: lis 1,spillstk+SPILLSTK@ha
1159: addi 1,1,spillstk+SPILLSTK@l /* get spill stack */
1160: stwu 1,-52(1)
1161: stw 0,48(1) /* save non-volatile registers */
1162: stw 3,44(1)
1163: stw 4,40(1)
1164: stw 5,36(1)
1165: stw 6,32(1)
1166: stw 7,28(1)
1167: stw 8,24(1)
1168: stw 9,20(1)
1169: stw 10,16(1)
1170: stw 11,12(1)
1171: stw 12,8(1)
1172: mfxer 30 /* save XER */
1173: mtsprg 2,30
1174: mflr 30 /* save trap type */
1175: mfctr 31 /* & ctr */
1176: mfsrr0 3
1177: b s_pte_spill /* above */
1178:
1179: /*
1180: * External interrupt second level handler
1181: */
1182: #define INTRENTER \
1183: /* Save non-volatile registers: */ \
1184: stwu 1,-88(1); /* temporarily */ \
1185: stw 0,84(1); \
1186: mfsprg 0,1; /* get original SP */ \
1187: stw 0,0(1); /* and store it */ \
1188: stw 3,80(1); \
1189: stw 4,76(1); \
1190: stw 5,72(1); \
1191: stw 6,68(1); \
1192: stw 7,64(1); \
1193: stw 8,60(1); \
1194: stw 9,56(1); \
1195: stw 10,52(1); \
1196: stw 11,48(1); \
1197: stw 12,44(1); \
1198: stw 28,40(1); /* saved LR */ \
1199: stw 29,36(1); /* saved CR */ \
1200: stw 30,32(1); /* saved XER */ \
1201: lmw 28,tempsave(0); /* restore r28-r31 */ \
1202: mfctr 6; \
1203: lis 5,_C_LABEL(intr_depth)@ha; \
1204: lwz 5,_C_LABEL(intr_depth)@l(5); \
1205: mfsrr0 4; \
1206: mfsrr1 3; \
1207: stw 6,28(1); \
1208: stw 5,20(1); \
1209: stw 4,12(1); \
1210: stw 3,8(1); \
1211: /* interrupts are recoverable here, and enable translation */ \
1212: lis 3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h; \
1213: ori 3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \
1214: mtsr KERNEL_SR,3; \
1215: mfmsr 5; \
1216: ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \
1217: mtmsr 5; \
1218: isync
1219:
1220: .globl _C_LABEL(extint_call)
1221: extintr:
1222: INTRENTER
1223: _C_LABEL(extint_call):
1224: bl _C_LABEL(extint_call) /* to be filled in later */
1225:
1226: intr_exit:
1227: /* Disable interrupts (should already be disabled) and MMU here: */
1228: mfmsr 3
1229: andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
1230: mtmsr 3
1231: isync
1232: /* restore possibly overwritten registers: */
1233: lwz 12,44(1)
1234: lwz 11,48(1)
1235: lwz 10,52(1)
1236: lwz 9,56(1)
1237: lwz 8,60(1)
1238: lwz 7,64(1)
1239: lwz 6,8(1)
1240: lwz 5,12(1)
1241: lwz 4,28(1)
1242: lwz 3,32(1)
1243: mtsrr1 6
1244: mtsrr0 5
1245: mtctr 4
1246: mtxer 3
1247: /* Returning to user mode? */
1248: mtcr 6 /* saved SRR1 */
1249: bc 4,17,1f /* branch if PSL_PR is false */
1.18 danw 1250: lis 3,_C_LABEL(curpm)@ha /* get current pmap real address */
1.1 tsubai 1251: lwz 3,_C_LABEL(curpm)@l(3)
1252: lwz 3,PM_KERNELSR(3)
1253: mtsr KERNEL_SR,3 /* Restore kernel SR */
1254: lis 3,_C_LABEL(astpending)@ha /* Test AST pending */
1255: lwz 4,_C_LABEL(astpending)@l(3)
1256: andi. 4,4,1
1257: beq 1f
1258: /* Setup for entry to realtrap: */
1259: lwz 3,0(1) /* get saved SP */
1260: mtsprg 1,3
1261: li 6,EXC_AST
1262: stmw 28,tempsave(0) /* establish tempsave again */
1263: mtlr 6
1264: lwz 28,40(1) /* saved LR */
1265: lwz 29,36(1) /* saved CR */
1266: lwz 6,68(1)
1267: lwz 5,72(1)
1268: lwz 4,76(1)
1269: lwz 3,80(1)
1270: lwz 0,84(1)
1271: lis 30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
1272: lwz 31,_C_LABEL(intr_depth)@l(30)
1273: addi 31,31,-1
1274: stw 31,_C_LABEL(intr_depth)@l(30)
1275: b realtrap
1276: 1:
1277: /* Here is the normal exit of extintr: */
1278: lwz 5,36(1)
1279: lwz 6,40(1)
1280: mtcr 5
1281: mtlr 6
1282: lwz 6,68(1)
1283: lwz 5,72(1)
1284: lis 3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
1285: lwz 4,_C_LABEL(intr_depth)@l(3)
1286: addi 4,4,-1
1287: stw 4,_C_LABEL(intr_depth)@l(3)
1288: lwz 4,76(1)
1289: lwz 3,80(1)
1290: lwz 0,84(1)
1291: lwz 1,0(1)
1292: rfi
1293:
1294: /*
1295: * Decrementer interrupt second level handler
1296: */
1297: decrintr:
1298: INTRENTER
1299: addi 3,1,8 /* intr frame */
1300: bl _C_LABEL(decr_intr)
1301: b intr_exit
1302:
1303: #ifdef DDB
1304: /*
1305: * Deliberate entry to ddbtrap
1306: */
1307: .globl _C_LABEL(ddb_trap)
1308: _C_LABEL(ddb_trap):
1309: mtsprg 1,1
1310: mfmsr 3
1311: mtsrr1 3
1312: andi. 3,3,~(PSL_EE|PSL_ME)@l
1313: mtmsr 3 /* disable interrupts */
1314: isync
1315: stmw 28,ddbsave(0)
1316: mflr 28
1317: li 29,EXC_BPT
1318: mtlr 29
1319: mfcr 29
1320: mtsrr0 28
1321:
1322: /*
1323: * Now the ddb trap catching code.
1324: */
1325: ddbtrap:
1326: FRAME_SETUP(ddbsave)
1327: /* Call C trap code: */
1328: addi 3,1,8
1329: bl _C_LABEL(ddb_trap_glue)
1330: or. 3,3,3
1331: bne ddbleave
1332: /* This wasn't for DDB, so switch to real trap: */
1333: lwz 3,FRAME_EXC+8(1) /* save exception */
1334: stw 3,ddbsave+8(0)
1335: FRAME_LEAVE(ddbsave)
1336: mtsprg 1,1 /* prepare for entrance to realtrap */
1337: stmw 28,tempsave(0)
1338: mflr 28
1339: mfcr 29
1340: lwz 31,ddbsave+8(0)
1341: mtlr 31
1342: b realtrap
1343: ddbleave:
1344: FRAME_LEAVE(ddbsave)
1345: rfi
1346: #endif /* DDB */
1347:
1.21 ws 1348: #ifdef IPKDB
1.1 tsubai 1349: /*
1350: * Deliberate entry to ipkdbtrap
1351: */
1352: .globl _C_LABEL(ipkdb_trap)
1353: _C_LABEL(ipkdb_trap):
1354: mtsprg 1,1
1355: mfmsr 3
1356: mtsrr1 3
1357: andi. 3,3,~(PSL_EE|PSL_ME)@l
1358: mtmsr 3 /* disable interrupts */
1359: isync
1360: stmw 28,ipkdbsave(0)
1361: mflr 28
1362: li 29,EXC_BPT
1363: mtlr 29
1364: mfcr 29
1365: mtsrr0 28
1366:
1367: /*
1368: * Now the ipkdb trap catching code.
1369: */
1370: ipkdbtrap:
1371: FRAME_SETUP(ipkdbsave)
1372: /* Call C trap code: */
1373: addi 3,1,8
1374: bl _C_LABEL(ipkdb_trap_glue)
1375: or. 3,3,3
1376: bne ipkdbleave
1377: /* This wasn't for IPKDB, so switch to real trap: */
1378: lwz 3,FRAME_EXC+8(1) /* save exception */
1379: stw 3,ipkdbsave+8(0)
1380: FRAME_LEAVE(ipkdbsave)
1381: mtsprg 1,1 /* prepare for entrance to realtrap */
1382: stmw 28,tempsave(0)
1383: mflr 28
1384: mfcr 29
1385: lwz 31,ipkdbsave+8(0)
1386: mtlr 31
1387: b realtrap
1388: ipkdbleave:
1389: FRAME_LEAVE(ipkdbsave)
1390: rfi
1391:
1392: ipkdbfault:
1393: ba _ipkdbfault
1394: _ipkdbfault:
1395: mfsrr0 3
1396: addi 3,3,4
1397: mtsrr0 3
1398: li 3,-1
1399: rfi
1400:
1401: /*
1402: * int ipkdbfbyte(unsigned char *p)
1403: */
1404: .globl _C_LABEL(ipkdbfbyte)
1405: _C_LABEL(ipkdbfbyte):
1406: li 9,EXC_DSI /* establish new fault routine */
1407: lwz 5,0(9)
1408: lis 6,ipkdbfault@ha
1409: lwz 6,ipkdbfault@l(6)
1410: stw 6,0(9)
1411: #ifdef IPKDBUSERHACK
1412: lis 8,_C_LABEL(ipkdbsr)@ha
1413: lwz 8,_C_LABEL(ipkdbsr)@l(8)
1414: mtsr USER_SR,8
1415: isync
1416: #endif
1417: dcbst 0,9 /* flush data... */
1418: sync
1419: icbi 0,9 /* and instruction caches */
1420: lbz 3,0(3) /* fetch data */
1421: stw 5,0(9) /* restore previous fault handler */
1422: dcbst 0,9 /* and flush data... */
1423: sync
1424: icbi 0,9 /* and instruction caches */
1425: blr
1426:
1427: /*
1428: * int ipkdbsbyte(unsigned char *p, int c)
1429: */
1430: .globl _C_LABEL(ipkdbsbyte)
1431: _C_LABEL(ipkdbsbyte):
1432: li 9,EXC_DSI /* establish new fault routine */
1433: lwz 5,0(9)
1434: lis 6,ipkdbfault@ha
1435: lwz 6,ipkdbfault@l(6)
1436: stw 6,0(9)
1437: #ifdef IPKDBUSERHACK
1438: lis 8,_C_LABEL(ipkdbsr)@ha
1439: lwz 8,_C_LABEL(ipkdbsr)@l(8)
1440: mtsr USER_SR,8
1441: isync
1442: #endif
1443: dcbst 0,9 /* flush data... */
1444: sync
1445: icbi 0,9 /* and instruction caches */
1446: mr 6,3
1447: xor 3,3,3
1448: stb 4,0(6)
1449: dcbst 0,6 /* Now do appropriate flushes
1450: to data... */
1451: sync
1452: icbi 0,6 /* and instruction caches */
1453: stw 5,0(9) /* restore previous fault handler */
1454: dcbst 0,9 /* and flush data... */
1455: sync
1456: icbi 0,9 /* and instruction caches */
1457: blr
1.21 ws 1458: #endif /* IPKDB */
1.1 tsubai 1459:
1460: /*
1461: * int setfault()
1462: *
1463: * Similar to setjmp to setup for handling faults on accesses to user memory.
1464: * Any routine using this may only call bcopy, either the form below,
1465: * or the (currently used) C code optimized, so it doesn't use any non-volatile
1466: * registers.
1467: */
1468: .globl _C_LABEL(setfault)
1469: _C_LABEL(setfault):
1470: mflr 0
1471: mfcr 12
1472: lis 4,_C_LABEL(curpcb)@ha
1473: lwz 4,_C_LABEL(curpcb)@l(4)
1474: stw 3,PCB_FAULT(4)
1475: stw 0,0(3)
1476: stw 1,4(3)
1477: stw 2,8(3)
1478: stmw 12,12(3)
1479: xor 3,3,3
1480: blr
CVSweb <webmaster@jp.NetBSD.org>