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