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