|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25:
26: /*
27: * Low-memory exception vector code for PowerPC MACH
28: *
29: * These are the only routines that are ever run with
30: * VM instruction translation switched off.
31: *
32: * The PowerPC is quite strange in that rather than having a set
33: * of exception vectors, the exception handlers are installed
34: * in well-known addresses in low memory. This code must be loaded
35: * at ZERO in physical memory. The simplest way of doing this is
36: * to load the kernel at zero, and specify this as the first file
37: * on the linker command line.
38: *
39: * When this code is loaded into place, it is loaded at virtual
40: * address KERNELBASE, which is mapped to zero (physical).
41: *
42: * This code handles all powerpc exceptions and is always entered
43: * in supervisor mode with translation off. It saves the minimum
44: * processor state before switching back on translation and
45: * jumping to the approprate routine.
46: *
47: * Vectors from 0x100 to 0x3fff occupy 0x100 bytes each (64 instructions)
48: *
49: * We use some of this space to decide which stack to use, and where to
50: * save the context etc, before jumping to a generic handler.
51: */
52:
53: #include <assym.s>
54: #include <debug.h>
55: #include <cpus.h>
56: #include <db_machine_commands.h>
57: #include <mach_rt.h>
58:
59: #include <mach_debug.h>
60: #include <ppc/asm.h>
61: #include <ppc/proc_reg.h>
62: #include <ppc/exception.h>
63: #include <ppc/Performance.h>
64: #include <mach/ppc/vm_param.h>
65: #include <ppc/POWERMAC/mp/MPPlugIn.h>
66:
67: #define RUPTTRC 0
68: #define CHECKSAVE 0
69: #define PERFTIMES 0
70: #define ESPDEBUG 0
71:
72: #define VECTOR_SEGMENT .section __VECTORS, __interrupts
73:
74: VECTOR_SEGMENT
75:
76:
77: .globl EXT(ExceptionVectorsStart)
78:
79: EXT(ExceptionVectorsStart): /* Used if relocating the exception vectors */
80: baseR: /* Used so we have more readable code */
81:
82: /*
83: * System reset - call debugger
84: */
85: . = 0xf0
86: .globl EXT(ResetHandler)
87: EXT(ResetHandler):
88: .long 0x0
89: .long 0x0
90: .long 0x0
91:
92: . = 0x100
93: .L_handler100:
94: mtsprg 2,r13 /* Save R13 */
95: mtsprg 3,r11 /* Save R11 */
96: lwz r13,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Get reset type
97: mfcr r11
98: cmpi cr0,r13,RESET_HANDLER_START
99: bne resetexc
100:
101: li r11,RESET_HANDLER_NULL
102: stw r11,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Clear reset type
103:
104: lwz r4,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_CALL)(br0)
105: lwz r3,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_ARG)(br0)
106: mtlr r4
107: blr
108:
109: resetexc:
110: mtcr r11
111: mfsprg r13,1 /* Get the exception save area */
112: li r11,T_RESET /* Set 'rupt code */
113: b .L_exception_entry /* Join common... */
114:
115: /*
116: * This is the data used by the exception trace code
117: */
118:
119: . = 0x180
120: .L_TraceData:
121:
122: .globl traceMask
123: traceMask: /* Allowable trace types indexed by vector >> 8 */
124: #if DEBUG
125: /* .long 0x02000000 */ /* Only alignment exceptions enabled */
126: .long 0xFFFFFFFF /* All enabled */
127: /* .long 0xFBBFFFFF */ /* EXT and DEC disabled */
128: /* .long 0xFFBFFFFF */ /* DEC disabled */
129: #else
130: .long 0x00000000 ; All disabled on non-debug systems
131: #endif
132:
133: .globl EXT(traceCurr)
134: EXT(traceCurr): .long traceTableBeg-EXT(ExceptionVectorsStart) /* The next trace entry to use */
135:
136: .globl EXT(traceStart)
137: EXT(traceStart): .long traceTableBeg-EXT(ExceptionVectorsStart) /* Start of the trace table */
138:
139: .globl EXT(traceEnd)
140: EXT(traceEnd):
141: .long traceTableEnd-EXT(ExceptionVectorsStart) /* End (wrap point) of the trace */
142:
143: .globl traceMsnd
144:
145: traceMsnd: .long 0 /* Saved mask while in debugger */
146:
147: /*
148: * Machine check (physical bus error) - call debugger
149: */
150:
151: . = 0x200
152: .L_handler200:
153: mtsprg 2,r13 /* Save R13 */
154: mtsprg 3,r11 /* Save R11 */
155: mfsprg r13,1 /* Get the exception save area */
156: li r11,T_MACHINE_CHECK /* Set 'rupt code */
157: b .L_exception_entry /* Join common... */
158:
159: /*
160: * Data access - page fault, invalid memory rights for operation
161: */
162:
163: . = 0x300
164: .L_handler300:
165: mtsprg 2,r13 /* Save R13 */
166: mtsprg 3,r11 /* Save R11 */
167: mfsprg r13,1 /* Get the exception save area */
168: li r11,T_DATA_ACCESS /* Set 'rupt code */
169: b .L_exception_entry /* Join common... */
170:
171: /*
172: * Instruction access - as for data access
173: */
174:
175: . = 0x400
176: .L_handler400:
177: mtsprg 2,r13 /* Save R13 */
178: mtsprg 3,r11 /* Save R11 */
179: mfsprg r13,1 /* Get the exception save area */
180: li r11,T_INSTRUCTION_ACCESS /* Set 'rupt code */
181: b .L_exception_entry /* Join common... */
182:
183: /*
184: * External interrupt
185: */
186:
187: . = 0x500
188: .L_handler500:
189: mtsprg 2,r13 /* Save R13 */
190: mtsprg 3,r11 /* Save R11 */
191: mfsprg r13,1 /* Get the exception save area */
192: li r11,T_INTERRUPT /* Set 'rupt code */
193: b .L_exception_entry /* Join common... */
194:
195: /*
196: * Alignment - many reasons
197: */
198:
199: . = 0x600
200: .L_handler600:
201: mtsprg 2,r13 /* Save R13 */
202: mtsprg 3,r11 /* Save R11 */
203: mfsprg r13,1 /* Get the exception save area */
204: li r11,T_ALIGNMENT /* Set 'rupt code */
205: b .L_exception_entry /* Join common... */
206:
207: /*
208: * Program - floating point exception, illegal inst, priv inst, user trap
209: */
210:
211: . = 0x700
212: .L_handler700:
213: mtsprg 2,r13 /* Save R13 */
214: mtsprg 3,r11 /* Save R11 */
215: mfsprg r13,1 /* Get the exception save area */
216: li r11,T_PROGRAM /* Set 'rupt code */
217: b .L_exception_entry /* Join common... */
218:
219: /*
220: * Floating point disabled
221: */
222:
223: . = 0x800
224: .L_handler800:
225: mtsprg 2,r13 /* Save R13 */
226: mtsprg 3,r11 /* Save R11 */
227: mfsprg r13,1 /* Get the exception save area */
228: li r11,T_FP_UNAVAILABLE /* Set 'rupt code */
229: b .L_exception_entry /* Join common... */
230:
231:
232: /*
233: * Decrementer - DEC register has passed zero.
234: */
235:
236: . = 0x900
237: .L_handler900:
238: mtsprg 2,r13 /* Save R13 */
239: mtsprg 3,r11 /* Save R11 */
240: mfsprg r13,1 /* Get the exception save area */
241: li r11,T_DECREMENTER /* Set 'rupt code */
242: b .L_exception_entry /* Join common... */
243:
244: /*
245: * I/O controller interface error - MACH does not use this
246: */
247:
248: . = 0xA00
249: .L_handlerA00:
250: mtsprg 2,r13 /* Save R13 */
251: mtsprg 3,r11 /* Save R11 */
252: mfsprg r13,1 /* Get the exception save area */
253: li r11,T_IO_ERROR /* Set 'rupt code */
254: b .L_exception_entry /* Join common... */
255:
256: /*
257: * Reserved
258: */
259:
260: . = 0xB00
261: .L_handlerB00:
262: mtsprg 2,r13 /* Save R13 */
263: mtsprg 3,r11 /* Save R11 */
264: mfsprg r13,1 /* Get the exception save area */
265: li r11,T_RESERVED /* Set 'rupt code */
266: b .L_exception_entry /* Join common... */
267:
268: /*
269: * System call - generated by the sc instruction
270: */
271:
272: . = 0xC00
273: .L_handlerC00:
274: cmplwi r0,0x7FF2 ; Ultra fast path cthread info call?
275: blt+ notufp ; Not ultra fast...
276: cmplwi r0,0x7FF3 ; Ultra fast path fp/vec facility state?
277: bgt+ notufp ; Not ultra fast...
278: mfsprg r3,0 ; Get the per_proc_area
279: beq- isvecfp ; This is the facility stat call
280: lwz r3,UAW(r3) ; Get the assist word
281: rfi ; All done, scream back... (no need to restore CR or R11, they are volatile)
282: ;
283: isvecfp: lwz r3,spcFlags(r3) ; Get the facility status
284: rfi ; Bail back...
285: ;
286: .align 5
287: notufp: mtsprg 3,r11 /* Save R11 */
288: mtsprg 2,r13 /* Save R13 */
289: li r11,T_SYSTEM_CALL /* Set 'rupt code */
290: mfsprg r13,1 /* Get the exception save area */
291: b .L_exception_entry /* Join common... */
292:
293: /*
294: * Trace - generated by single stepping
295: */
296:
297: . = 0xD00
298: .L_handlerD00:
299: mtsprg 2,r13 /* Save R13 */
300: mtsprg 3,r11 /* Save R11 */
301: mfsprg r13,1 /* Get the exception save area */
302: li r11,T_TRACE /* Set 'rupt code */
303: b .L_exception_entry /* Join common... */
304:
305: /*
306: * Floating point assist
307: */
308:
309: . = 0xe00
310: .L_handlerE00:
311: mtsprg 2,r13 /* Save R13 */
312: mtsprg 3,r11 /* Save R11 */
313: mfsprg r13,1 /* Get the exception save area */
314: li r11,T_FP_ASSIST /* Set 'rupt code */
315: b .L_exception_entry /* Join common... */
316:
317:
318: /*
319: * Performance monitor interruption
320: */
321:
322: . = 0xF00
323: PMIhandler:
324: mtsprg 2,r13 /* Save R13 */
325: mtsprg 3,r11 /* Save R11 */
326: mfsprg r13,1 /* Get the exception save area */
327: li r11,T_PERF_MON /* Set 'rupt code */
328: b .L_exception_entry /* Join common... */
329:
330:
331: /*
332: * VMX exception
333: */
334:
335: . = 0xF20
336: VMXhandler:
337: mtsprg 2,r13 /* Save R13 */
338: mtsprg 3,r11 /* Save R11 */
339: mfsprg r13,1 /* Get the exception save area */
340: li r11,T_VMX /* Set 'rupt code */
341: b .L_exception_entry /* Join common... */
342:
343:
344:
345: /*
346: * Instruction translation miss - we inline this code.
347: * Upon entry (done for us by the machine):
348: * srr0 : addr of instruction that missed
349: * srr1 : bits 0-3 = saved CR0
350: * 4 = lru way bit
351: * 16-31 = saved msr
352: * msr[tgpr] = 1 (so gpr0-3 become our temporary variables)
353: * imiss: ea that missed
354: * icmp : the compare value for the va that missed
355: * hash1: pointer to first hash pteg
356: * hash2: pointer to 2nd hash pteg
357: *
358: * Register usage:
359: * tmp0: saved counter
360: * tmp1: junk
361: * tmp2: pointer to pteg
362: * tmp3: current compare value
363: *
364: * This code is taken from the 603e User's Manual with
365: * some bugfixes and minor improvements to save bytes and cycles
366: */
367:
368: . = 0x1000
369: .L_handler1000:
370: mfspr tmp2, hash1
371: mfctr tmp0 /* use tmp0 to save ctr */
372: mfspr tmp3, icmp
373:
374: .L_imiss_find_pte_in_pteg:
375: li tmp1, 8 /* count */
376: subi tmp2, tmp2, 8 /* offset for lwzu */
377: mtctr tmp1 /* count... */
378:
379: .L_imiss_pteg_loop:
380: lwz tmp1, 8(tmp2) /* check pte0 for match... */
381: addi tmp2, tmp2, 8
382: cmpw cr0, tmp1, tmp3
383: #if 0
384: bdnzf+ cr0, .L_imiss_pteg_loop
385: #else
386: bc 0,2, .L_imiss_pteg_loop
387: #endif
388: beq+ cr0, .L_imiss_found_pte
389:
390: /* Not found in PTEG, we must scan 2nd then give up */
391:
392: andi. tmp1, tmp3, MASK(PTE0_HASH_ID)
393: bne- .L_imiss_do_no_hash_exception /* give up */
394:
395: mfspr tmp2, hash2
396: ori tmp3, tmp3, MASK(PTE0_HASH_ID)
397: b .L_imiss_find_pte_in_pteg
398:
399: .L_imiss_found_pte:
400:
401: lwz tmp1, 4(tmp2) /* get pte1_t */
402: andi. tmp3, tmp1, MASK(PTE1_WIMG_GUARD) /* Fault? */
403: bne- .L_imiss_do_prot_exception /* Guarded - illegal */
404:
405: /* Ok, we've found what we need to, restore and rfi! */
406:
407: mtctr tmp0 /* restore ctr */
408: mfsrr1 tmp3
409: mfspr tmp0, imiss
410: mtcrf 0x80, tmp3 /* Restore CR0 */
411: mtspr rpa, tmp1 /* set the pte */
412: ori tmp1, tmp1, MASK(PTE1_REFERENCED) /* set referenced */
413: tlbli tmp0
414: sth tmp1, 6(tmp2)
415: rfi
416:
417: .L_imiss_do_prot_exception:
418: /* set up srr1 to indicate protection exception... */
419: mfsrr1 tmp3
420: andi. tmp2, tmp3, 0xffff
421: addis tmp2, tmp2, MASK(SRR1_TRANS_PROT) >> 16
422: b .L_imiss_do_exception
423:
424: .L_imiss_do_no_hash_exception:
425: /* clean up registers for protection exception... */
426: mfsrr1 tmp3
427: andi. tmp2, tmp3, 0xffff
428: addis tmp2, tmp2, MASK(SRR1_TRANS_HASH) >> 16
429:
430: /* And the entry into the usual instruction fault handler ... */
431: .L_imiss_do_exception:
432:
433: mtctr tmp0 /* Restore ctr */
434: mtsrr1 tmp2 /* Set up srr1 */
435: mfmsr tmp0
436: xoris tmp0, tmp0, MASK(MSR_TGPR)>>16 /* no TGPR */
437: mtcrf 0x80, tmp3 /* Restore CR0 */
438: mtmsr tmp0 /* reset MSR[TGPR] */
439: b .L_handler400 /* Instr Access */
440:
441: /*
442: * Data load translation miss
443: *
444: * Upon entry (done for us by the machine):
445: * srr0 : addr of instruction that missed
446: * srr1 : bits 0-3 = saved CR0
447: * 4 = lru way bit
448: * 5 = 1 if store
449: * 16-31 = saved msr
450: * msr[tgpr] = 1 (so gpr0-3 become our temporary variables)
451: * dmiss: ea that missed
452: * dcmp : the compare value for the va that missed
453: * hash1: pointer to first hash pteg
454: * hash2: pointer to 2nd hash pteg
455: *
456: * Register usage:
457: * tmp0: saved counter
458: * tmp1: junk
459: * tmp2: pointer to pteg
460: * tmp3: current compare value
461: *
462: * This code is taken from the 603e User's Manual with
463: * some bugfixes and minor improvements to save bytes and cycles
464: */
465:
466: . = 0x1100
467: .L_handler1100:
468: mfspr tmp2, hash1
469: mfctr tmp0 /* use tmp0 to save ctr */
470: mfspr tmp3, dcmp
471:
472: .L_dlmiss_find_pte_in_pteg:
473: li tmp1, 8 /* count */
474: subi tmp2, tmp2, 8 /* offset for lwzu */
475: mtctr tmp1 /* count... */
476:
477: .L_dlmiss_pteg_loop:
478: lwz tmp1, 8(tmp2) /* check pte0 for match... */
479: addi tmp2, tmp2, 8
480: cmpw cr0, tmp1, tmp3
481: #if 0 /* How to write this correctly? */
482: bdnzf+ cr0, .L_dlmiss_pteg_loop
483: #else
484: bc 0,2, .L_dlmiss_pteg_loop
485: #endif
486: beq+ cr0, .L_dmiss_found_pte
487:
488: /* Not found in PTEG, we must scan 2nd then give up */
489:
490: andi. tmp1, tmp3, MASK(PTE0_HASH_ID) /* already at 2nd? */
491: bne- .L_dmiss_do_no_hash_exception /* give up */
492:
493: mfspr tmp2, hash2
494: ori tmp3, tmp3, MASK(PTE0_HASH_ID)
495: b .L_dlmiss_find_pte_in_pteg
496:
497: .L_dmiss_found_pte:
498:
499: lwz tmp1, 4(tmp2) /* get pte1_t */
500:
501: /* Ok, we've found what we need to, restore and rfi! */
502:
503: mtctr tmp0 /* restore ctr */
504: mfsrr1 tmp3
505: mfspr tmp0, dmiss
506: mtcrf 0x80, tmp3 /* Restore CR0 */
507: mtspr rpa, tmp1 /* set the pte */
508: ori tmp1, tmp1, MASK(PTE1_REFERENCED) /* set referenced */
509: tlbld tmp0 /* load up tlb */
510: sth tmp1, 6(tmp2) /* sth is faster? */
511: rfi
512:
513: /* This code is shared with data store translation miss */
514:
515: .L_dmiss_do_no_hash_exception:
516: /* clean up registers for protection exception... */
517: mfsrr1 tmp3
518: /* prepare to set DSISR_WRITE_BIT correctly from srr1 info */
519: rlwinm tmp1, tmp3, 9, 6, 6
520: addis tmp1, tmp1, MASK(DSISR_HASH) >> 16
521:
522: /* And the entry into the usual data fault handler ... */
523:
524: mtctr tmp0 /* Restore ctr */
525: andi. tmp2, tmp3, 0xffff /* Clean up srr1 */
526: mtsrr1 tmp2 /* Set srr1 */
527: mtdsisr tmp1
528: mfspr tmp2, dmiss
529: mtdar tmp2
530: mfmsr tmp0
531: xoris tmp0, tmp0, MASK(MSR_TGPR)>>16 /* no TGPR */
532: mtcrf 0x80, tmp3 /* Restore CR0 */
533: sync /* Needed on some */
534: mtmsr tmp0 /* reset MSR[TGPR] */
535: b .L_handler300 /* Data Access */
536:
537: /*
538: * Data store translation miss (similar to data load)
539: *
540: * Upon entry (done for us by the machine):
541: * srr0 : addr of instruction that missed
542: * srr1 : bits 0-3 = saved CR0
543: * 4 = lru way bit
544: * 5 = 1 if store
545: * 16-31 = saved msr
546: * msr[tgpr] = 1 (so gpr0-3 become our temporary variables)
547: * dmiss: ea that missed
548: * dcmp : the compare value for the va that missed
549: * hash1: pointer to first hash pteg
550: * hash2: pointer to 2nd hash pteg
551: *
552: * Register usage:
553: * tmp0: saved counter
554: * tmp1: junk
555: * tmp2: pointer to pteg
556: * tmp3: current compare value
557: *
558: * This code is taken from the 603e User's Manual with
559: * some bugfixes and minor improvements to save bytes and cycles
560: */
561:
562: . = 0x1200
563: .L_handler1200:
564: mfspr tmp2, hash1
565: mfctr tmp0 /* use tmp0 to save ctr */
566: mfspr tmp3, dcmp
567:
568: .L_dsmiss_find_pte_in_pteg:
569: li tmp1, 8 /* count */
570: subi tmp2, tmp2, 8 /* offset for lwzu */
571: mtctr tmp1 /* count... */
572:
573: .L_dsmiss_pteg_loop:
574: lwz tmp1, 8(tmp2) /* check pte0 for match... */
575: addi tmp2, tmp2, 8
576:
577: cmpw cr0, tmp1, tmp3
578: #if 0 /* I don't know how to write this properly */
579: bdnzf+ cr0, .L_dsmiss_pteg_loop
580: #else
581: bc 0,2, .L_dsmiss_pteg_loop
582: #endif
583: beq+ cr0, .L_dsmiss_found_pte
584:
585: /* Not found in PTEG, we must scan 2nd then give up */
586:
587: andi. tmp1, tmp3, MASK(PTE0_HASH_ID) /* already at 2nd? */
588: bne- .L_dmiss_do_no_hash_exception /* give up */
589:
590: mfspr tmp2, hash2
591: ori tmp3, tmp3, MASK(PTE0_HASH_ID)
592: b .L_dsmiss_find_pte_in_pteg
593:
594: .L_dsmiss_found_pte:
595:
596: lwz tmp1, 4(tmp2) /* get pte1_t */
597: andi. tmp3, tmp1, MASK(PTE1_CHANGED) /* unchanged, check? */
598: beq- .L_dsmiss_check_prot /* yes, check prot */
599:
600: .L_dsmiss_resolved:
601: /* Ok, we've found what we need to, restore and rfi! */
602:
603: mtctr tmp0 /* restore ctr */
604: mfsrr1 tmp3
605: mfspr tmp0, dmiss
606: mtcrf 0x80, tmp3 /* Restore CR0 */
607: mtspr rpa, tmp1 /* set the pte */
608: tlbld tmp0 /* load up tlb */
609: rfi
610:
611: .L_dsmiss_check_prot:
612: /* PTE is unchanged, we must check that we can write */
613: rlwinm. tmp3, tmp1, 30, 0, 1 /* check PP[1] */
614: bge- .L_dsmiss_check_prot_user_kern
615: andi. tmp3, tmp1, 1 /* check PP[0] */
616: beq+ .L_dsmiss_check_prot_ok
617:
618: .L_dmiss_do_prot_exception:
619: /* clean up registers for protection exception... */
620: mfsrr1 tmp3
621: /* prepare to set DSISR_WRITE_BIT correctly from srr1 info */
622: rlwinm tmp1, tmp3, 9, 6, 6
623: addis tmp1, tmp1, MASK(DSISR_PROT) >> 16
624:
625: /* And the entry into the usual data fault handler ... */
626:
627: mtctr tmp0 /* Restore ctr */
628: andi. tmp2, tmp3, 0xffff /* Clean up srr1 */
629: mtsrr1 tmp2 /* Set srr1 */
630: mtdsisr tmp1
631: mfspr tmp2, dmiss
632: mtdar tmp2
633: mfmsr tmp0
634: xoris tmp0, tmp0, MASK(MSR_TGPR)>>16 /* no TGPR */
635: mtcrf 0x80, tmp3 /* Restore CR0 */
636: sync /* Needed on some */
637: mtmsr tmp0 /* reset MSR[TGPR] */
638: b .L_handler300 /* Data Access */
639:
640: /* NB - if we knew we were on a 603e we could test just the MSR_KEY bit */
641: .L_dsmiss_check_prot_user_kern:
642: mfsrr1 tmp3
643: andi. tmp3, tmp3, MASK(MSR_PR)
644: beq+ .L_dsmiss_check_prot_kern
645: mfspr tmp3, dmiss /* check user privs */
646: mfsrin tmp3, tmp3 /* get excepting SR */
647: andis. tmp3, tmp3, 0x2000 /* Test SR ku bit */
648: beq+ .L_dsmiss_check_prot_ok
649: b .L_dmiss_do_prot_exception
650:
651: .L_dsmiss_check_prot_kern:
652: mfspr tmp3, dmiss /* check kern privs */
653: mfsrin tmp3, tmp3
654: andis. tmp3, tmp3, 0x4000 /* Test SR Ks bit */
655: bne- .L_dmiss_do_prot_exception
656:
657: .L_dsmiss_check_prot_ok:
658: /* Ok, mark as referenced and changed before resolving the fault */
659: ori tmp1, tmp1, (MASK(PTE1_REFERENCED)|MASK(PTE1_CHANGED))
660: sth tmp1, 6(tmp2)
661: b .L_dsmiss_resolved
662:
663: /*
664: * Instruction address breakpoint
665: */
666:
667: . = 0x1300
668: .L_handler1300:
669: mtsprg 2,r13 /* Save R13 */
670: mtsprg 3,r11 /* Save R11 */
671: mfsprg r13,1 /* Get the exception save area */
672: li r11,T_INSTRUCTION_BKPT /* Set 'rupt code */
673: b .L_exception_entry /* Join common... */
674:
675: /*
676: * System management interrupt
677: */
678:
679: . = 0x1400
680: .L_handler1400:
681: mtsprg 2,r13 /* Save R13 */
682: mtsprg 3,r11 /* Save R11 */
683: mfsprg r13,1 /* Get the exception save area */
684: li r11,T_SYSTEM_MANAGEMENT /* Set 'rupt code */
685: b .L_exception_entry /* Join common... */
686:
687: ;
688: ; Altivec Java Mode Assist interrupt
689: ;
690:
691: . = 0x1600
692: .L_handler1600:
693: mtsprg 2,r13 /* Save R13 */
694: mtsprg 3,r11 /* Save R11 */
695: mfsprg r13,1 /* Get the exception save area */
696: li r11,T_ALTIVEC_ASSIST /* Set 'rupt code */
697: b .L_exception_entry /* Join common... */
698:
699: /*
700: * There is now a large gap of reserved traps
701: */
702:
703: /*
704: * Run mode/ trace exception - single stepping on 601 processors
705: */
706:
707: . = 0x2000
708: .L_handler2000:
709: mtsprg 2,r13 /* Save R13 */
710: mtsprg 3,r11 /* Save R11 */
711: mfsprg r13,1 /* Get the exception save area */
712: li r11,T_RUNMODE_TRACE /* Set 'rupt code */
713: b .L_exception_entry /* Join common... */
714:
715: /*
716: * .L_exception_entry(type)
717: *
718: * This is the common exception handling routine called by any
719: * type of system exception.
720: *
721: * ENTRY: via a system exception handler, thus interrupts off, VM off.
722: * r3 has been saved in sprg3 and now contains a number
723: * representing the exception's origins
724: *
725: */
726:
727: .data
728: .align ALIGN
729: #ifdef __ELF__
730: .type EXT(exception_entry),@object
731: .size EXT(exception_entry), 4
732: #endif
733: .globl EXT(exception_entry)
734: EXT(exception_entry):
735: .long .L_exception_entry-EXT(ExceptionVectorsStart) /* phys addr of fn */
736:
737: VECTOR_SEGMENT
738: .align 2
739:
740: .L_exception_entry:
741:
742: /*
743: *
744: * Here we will save off a mess of registers, the special ones and R0-R12. We use the DCBZ
745: * instruction to clear and allcoate a line in the cache. This way we won't take any cache
746: * misses, so these stores won't take all that long.
747: *
748: *
749: */
750:
751: dcbz 0,r13 /* Allocate the first line of the savearea in the cache */
752:
753: stw r1,saver1(r13) /* Save this one */
754: li r1,32 /* Point to the second line */
755: stw r0,saver0(r13) /* Save this one */
756: dcbz r1,r13 /* Reserve our line in cache */
757:
758: #if PERFTIMES && DEBUG
759: mftb r1 ; Get the time of interruption
760: stw r1,0x17C(br0) ; Save the time of interruption
761: #endif
762:
763: stw r2,saver2(r13) /* Save this one */
764: stw r3,saver3(r13) /* Save this one */
765: stw r6,saver6(r13) /* Save this one */
766: stw r4,saver4(r13) /* Save this one */
767:
768: stw r8,saver8(r13) /* Save this one */
769: mfsrr0 r6 /* Get the interruption SRR0 */
770: stw r7,saver7(r13) /* Save this one */
771: mfsrr1 r7 /* Get the interrupt SRR1 */
772: stw r6,savesrr0(r13) /* Save the SRR0 */
773: stw r5,saver5(r13) /* Save this one */
774: mfsprg r6,2 /* Get interrupt time R13 */
775: stw r7,savesrr1(r13) /* Save SRR1 */
776: mfsprg r8,3 /* Get 'rupt time R11 */
777: stw r6,saver13(r13) /* Save 'rupt R1 */
778: la r6,saver14(r13) /* Point to the next cache line */
779: stw r8,saver11(r13) /* Save 'rupt time R11 */
780:
781: dcbz 0,r6 /* Allocate in cache */
782:
783: stw r9,saver9(r13) /* Save this one */
784: mfcr r7 /* Get the CR */
785: #if 0
786: cmplwi r13,0x1000 ; (TEST/DEBUG)
787: bgt+ notpage0yy ; (TEST/DEBUG)
788: li r9,1 ; (TEST/DEBUG)
789: lwz r9,0(br0) ; (TEST/DEBUG)
790: dcbst br0,r9 ; (TEST/DEBUG)
791: notpage0aa: b notpage0aa ; (TEST/DEBUG)
792:
793: notpage0yy: lwz r9,0(br0) ; (TEST/DEBUG)
794: mr. r9,r9 ; (TEST/DEBUG)
795: notpage0bb: bne- notpage0bb ; (TEST/DEBUG)
796: #endif
797:
798: la r9,saver30(r13) /* Point to the trailing end */
799: stw r10,saver10(r13) /* Save this one */
800: mflr r8 /* Get the LR */
801: stw r12,saver12(r13) /* Save this one */
802:
803: dcbz 0,r9 /* Allocate the last in the area */
804:
805: stw r14,saver14(r13) /* Save this one */
806: la r10,saver22(r13) /* Point to the next block to save into */
807: stw r15,saver15(r13) /* Save this one */
808: stw r7,savecr(r13) /* Save 'rupt CR */
809: mfctr r6 /* Get the CTR */
810: stw r16,saver16(r13) /* Save this one */
811: stw r8,savelr(r13) /* Save 'rupt LR */
812:
813: dcbz 0,r10 /* Allocate next save area line */
814:
815: stw r17,saver17(r13) /* Save this one */
816: stw r18,saver18(r13) /* Save this one */
817: stw r6,savectr(r13) /* Save 'rupt CTR */
818: mfxer r7 /* Get the XER */
819: stw r19,saver19(r13) /* Save this one */
820: lis r12,HIGH_ADDR(KERNEL_SEG_REG0_VALUE) /* Get the high half of the kernel SR0 value */
821: mfdar r6 /* Get the 'rupt DAR */
822: stw r20,saver20(r13) /* Save this one */
823: #if 0
824: mfsr r10,sr0 ; (TEST/DEBUG)
825: mfsr r20,sr1 ; (TEST/DEBUG)
826: stw r10,savesr0(r13) ; (TEST/DEBUG)
827: mfsr r10,sr2 ; (TEST/DEBUG)
828: mfsr r19,sr3 ; (TEST/DEBUG)
829: stw r20,savesr1(r13) ; (TEST/DEBUG)
830: mfsr r14,sr4 ; (TEST/DEBUG)
831: mfsr r15,sr5 ; (TEST/DEBUG)
832: stw r10,savesr2(r13) ; (TEST/DEBUG)
833: mfsr r16,sr6 ; (TEST/DEBUG)
834: mfsr r17,sr7 ; (TEST/DEBUG)
835: stw r19,savesr3(r13) ; (TEST/DEBUG)
836: mfsr r10,sr8 ; (TEST/DEBUG)
837: mfsr r20,sr9 ; (TEST/DEBUG)
838: stw r14,savesr4(r13) ; (TEST/DEBUG)
839: mfsr r14,sr10 ; (TEST/DEBUG)
840: mfsr r19,sr11 ; (TEST/DEBUG)
841: stw r15,savesr5(r13) ; (TEST/DEBUG)
842: mfsr r15,sr13 ; (TEST/DEBUG)
843: stw r16,savesr6(r13) ; (TEST/DEBUG)
844: mfsr r16,sr14 ; (TEST/DEBUG)
845: stw r17,savesr7(r13) ; (TEST/DEBUG)
846: mfsr r17,sr15 ; (TEST/DEBUG)
847:
848: stw r10,savesr8(r13) ; (TEST/DEBUG)
849: stw r20,savesr9(r13) ; (TEST/DEBUG)
850: stw r14,savesr10(r13) ; (TEST/DEBUG)
851: stw r19,savesr11(r13) ; (TEST/DEBUG)
852: stw r15,savesr13(r13) ; (TEST/DEBUG)
853: stw r16,savesr14(r13) ; (TEST/DEBUG)
854: stw r17,savesr15(r13) ; (TEST/DEBUG)
855: #endif
856:
857: mtsr sr0,r12 /* Set the kernel SR0 */
858: stw r21,saver21(r13) /* Save this one */
859: addis r12,r12,0x0010 ; Point to the second segment of kernel
860: stw r7,savexer(r13) /* Save the 'rupt XER */
861: mtsr sr1,r12 /* Set the kernel SR1 */
862: stw r30,saver30(r13) /* Save this one */
863: addis r12,r12,0x0010 ; Point to the third segment of kernel
864: stw r31,saver31(r13) /* Save this one */
865: mtsr sr2,r12 /* Set the kernel SR2 */
866: stw r22,saver22(r13) /* Save this one */
867: addis r12,r12,0x0010 ; Point to the third segment of kernel
868: la r10,savedar(r13) /* Point to exception info block */
869: stw r23,saver23(r13) /* Save this one */
870: mtsr sr3,r12 /* Set the kernel SR3 */
871: stw r24,saver24(r13) /* Save this one */
872: stw r25,saver25(r13) /* Save this one */
873: mfdsisr r7 /* Get the 'rupt DSISR */
874: stw r26,saver26(r13) /* Save this one */
875:
876: dcbz 0,r10 /* Allocate exception info line */
877:
878: stw r27,saver27(r13) /* Save this one */
879: stw r28,saver28(r13) /* Save this one */
880: stw r29,saver29(r13) /* Save this one */
881: mfsr r14,sr14 ; Get the copyin/out segment register
882: stw r6,savedar(r13) /* Save the 'rupt DAR */
883: stw r7,savedsisr(r13) /* Save the 'rupt code DSISR */
884: stw r11,saveexception(r13) /* Save the exception code */
885: stw r14,savesr14(r13) ; Save copyin/copyout
886:
887: lis r8,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
888: mfpvr r20 /* Get the PVR */
889: ori r8,r8,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
890: li r21,0x3612 /* Mask of processors with a PIR */
891: rlwinm r20,r20,16,16,31 /* Isolate the CPU type */
892: srw r21,r21,r20 /* Isolate the PIR valid bit */
893: cmplwi cr1,r20,PROCESSOR_VERSION_Max ; Do we have Altivec?
894: rlwinm r21,r21,0,31,31 /* Isolate the PIR valid */
895:
896: li r19,0 ; Assume no Altivec
897: blt cr1,noavec ; No possible AltiVec here...
898: mfspr r19,vrsave ; Get the VRSAVE register
899:
900: noavec: cmplwi cr6,r21,1 /* Check if PIR is valid */
901: stw r19,savevrsave(r13) ; Save the vector register usage flags
902:
903: #if 0
904: lwz r14,savesrr0(r13) /* (TEST/DEBUG) */
905: cmplw cr7,r5,r5 /* (TEST/DEBUG) */
906: rlwinm. r14,r14,0,0,15 /* (TEST/DEBUG) */
907: cmplwi cr2,r11,T_INTERRUPT /* (TEST/DEBUG) */
908: beq- noeattrace2 /* (TEST/DEBUG) */
909: cmplwi r11,T_SYSTEM_CALL /* (TEST/DEBUG) */
910: rlwinm r14,r0,1,0,31 /* (TEST/DEBUG) */
911: beq cr2,eatatjoes /* (TEST/DEBUG) */
912: bne+ noeattrace2 /* (TEST/DEBUG) */
913: cmplwi r14,0x001B /* (TEST/DEBUG) */
914: bne+ noeattrace2 /* (TEST/DEBUG) */
915:
916: eatatjoes: cmplwi cr7,r13,0 /* (TEST/DEBUG) */
917:
918: noeattrace2:
919: #else
920: cmplw cr7,r13,r13 /* (TEST/DEBUG) */
921: #endif
922: #if RUPTTRC
923: lwz r9,0(br0) /* (TEST/DEBUG) */
924: lis r14,0x7FFF /* (TEST/DEBUG) */
925: mr. r9,r9 /* (TEST/DEBUG) */
926: beq+ nono1 /* (TEST/DEBUG) */
927: bne cr7,nono1 /* (TEST/DEBUG) */
928:
929: mfdec r9 /* (TEST/DEBUG) */
930: or r14,r14,r9 /* (TEST/DEBUG) */
931: mtdec r14 /* (TEST/DEBUG) */
932: li r14,0x20 /* (TEST/DEBUG) */
933:
934: lwarx r15,0,r14 ; ?
935:
936: mpwait0: lwarx r15,0,r14 /* (TEST/DEBUG) */
937: mr. r15,r15 /* (TEST/DEBUG) */
938: bne- mpwait0 /* (TEST/DEBUG) */
939: stwcx. r14,0,r14 /* (TEST/DEBUG) */
940: bne- mpwait0 /* (TEST/DEBUG) */
941:
942: stw r0,0x280(br0) /* (TEST/DEBUG) */
943: stmw r1,0x284(br0) /* (TEST/DEBUG) */
944: bne cr6,nopir0 /* (TEST/DEBUG) */
945: mfspr r4,pir /* (TEST/DEBUG) */
946: b gotpir0 /* (TEST/DEBUG) */
947: nopir0: li r4,0 /* (TEST/DEBUG) */
948: gotpir0: /* (TEST/DEBUG) */
949: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
950: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
951: li r3,0 /* (TEST/DEBUG) */
952: rlwimi r4,r11,30,8,31 /* (TEST/DEBUG) */
953: mfsrr0 r5 /* (TEST/DEBUG) */
954: oris r4,r4,0x3030 /* (TEST/DEBUG) */
955: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
956: ori r4,r4,0x3030 /* (TEST/DEBUG) */
957: mtlr r31 /* (TEST/DEBUG) */
958: blrl /* (TEST/DEBUG) */
959:
960: bne cr6,nopir1 /* (TEST/DEBUG) */
961: mfspr r4,pir /* (TEST/DEBUG) */
962: b gotpir1 /* (TEST/DEBUG) */
963: nopir1: li r4,0 /* (TEST/DEBUG) */
964: gotpir1: /* (TEST/DEBUG) */
965: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
966: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
967: lwz r5,savelr(r13) /* (TEST/DEBUG) */
968: li r3,0 /* (TEST/DEBUG) */
969: oris r4,r4,0x3030 /* (TEST/DEBUG) */
970: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
971: ori r4,r4,0x3130 /* (TEST/DEBUG) */
972: mtlr r31 /* (TEST/DEBUG) */
973: blrl /* (TEST/DEBUG) */
974:
975: bne cr6,nopir2 /* (TEST/DEBUG) */
976: mfspr r4,pir /* (TEST/DEBUG) */
977: b gotpir2 /* (TEST/DEBUG) */
978: nopir2: li r4,0 /* (TEST/DEBUG) */
979: gotpir2: /* (TEST/DEBUG) */
980: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
981: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
982: li r3,0 /* (TEST/DEBUG) */
983: mr r5,r13 /* (TEST/DEBUG) */
984: oris r4,r4,0x3030 /* (TEST/DEBUG) */
985: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
986: ori r4,r4,0x3131 /* (TEST/DEBUG) */
987: mtlr r31 /* (TEST/DEBUG) */
988: blrl /* (TEST/DEBUG) */
989: lmw r1,0x284(br0) /* (TEST/DEBUG) */
990: lwz r0,0x280(br0) /* (TEST/DEBUG) */
991:
992: li r15,0 /* (TEST/DEBUG) */
993: stw r15,0x20(br0) /* (TEST/DEBUG) */
994: mtdec r9 /* (TEST/DEBUG) */
995: nono1:
996: #endif
997:
998:
999: /*
1000: * Everything is saved at this point, except for FPRs, and VMX registers
1001: *
1002: * Time for a new save area. Allocate the trace table entry now also
1003: * Note that we haven't touched R0-R5 yet. Except for R1, that's in the save
1004: */
1005:
1006: #if 0
1007: mfsrr1 r20 ; (TEST/DEBUG)
1008: mfsrr0 r7 ; (TEST/DEBUG)
1009: lis r9,0x8000 ; (TEST/DEBUG)
1010: mfmsr r25 ; (TEST/DEBUG)
1011: ori r15,r25,0x10 ; (TEST/DEBUG)
1012: mtmsr r15 ; (TEST/DEBUG)
1013: isync ; (TEST/DEBUG)
1014: ori r9,r9,lo16(0x870C) ; (TEST/DEBUG)
1015: stw r11,0(r9) ; (TEST/DEBUG)
1016: stw r7,0(r9) ; (TEST/DEBUG)
1017: mtmsr r25 ; (TEST/DEBUG)
1018: isync ; (TEST/DEBUG)
1019: mtsrr1 r20 ; (TEST/DEBUG)
1020: mtsrr0 r7 ; (TEST/DEBUG)
1021: #endif
1022:
1023:
1024: lwarx r9,0,r8 ; ?
1025:
1026: lllck: lwarx r9,0,r8 /* Grab the lock value */
1027: li r7,1 /* Use part of the delay time */
1028: mr. r9,r9 /* Is it locked? */
1029: bne- lllcks /* Yeah, wait for it to clear... */
1030: stwcx. r7,0,r8 /* Try to seize that there durn lock */
1031: beq+ lllckd /* Got it... */
1032: b lllck /* Collision, try again... */
1033:
1034: lllcks: lwz r9,SVlock(r8) /* Get that lock in here */
1035: mr. r9,r9 /* Is it free yet? */
1036: beq+ lllck /* Yeah, try for it again... */
1037: b lllcks /* Sniff away... */
1038:
1039: lllckd: isync /* Purge any speculative executions here */
1040: rlwinm r7,r11,30,0,31 /* Save 'rupt code shifted right 2 */
1041: #if 1
1042: lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) /* Get the trace mask */
1043: #else
1044: li r14,-1 /* (TEST/DEBUG) */
1045: #endif
1046: addi r7,r7,10 /* Adjust for CR5_EQ position */
1047: lwz r15,SVfree(r8) /* Get the head of the save area list */
1048: lwz r25,SVinuse(r8) /* Get the in use count */
1049: rlwnm r7,r14,r7,22,22 /* Set CR5_EQ bit position to 0 if tracing allowed */
1050: lwz r20,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) /* Pick up the current trace entry */
1051: mtcrf 0x04,r7 /* Set CR5 to show trace or not */
1052:
1053: lwz r14,SACalloc(r15) /* Pick up the allocation bits */
1054: addi r25,r25,1 /* Bump up the in use count for the new savearea */
1055: lwz r21,LOW_ADDR(EXT(traceEnd)-EXT(ExceptionVectorsStart))(br0) /* Grab up the end of it all */
1056: mr. r14,r14 /* Can we use the first one? */
1057: blt use1st /* Yeah... */
1058:
1059: andis. r14,r14,0x8000 /* Show we used the second and remember if it was the last */
1060: addi r10,r15,0x0800 /* Point to the first one */
1061: b gotsave /* We have the area now... */
1062:
1063: use1st: andis. r14,r14,0x4000 /* Mark first gone and remember if empty */
1064: mr r10,r15 /* Set the save area */
1065:
1066: gotsave: stw r14,SACalloc(r15) /* Put back the allocation bits */
1067: bne nodqsave /* There's still an empty slot, don't dequeue... */
1068:
1069: lwz r16,SACnext(r15) /* Get the next in line */
1070: stw r16,SVfree(r8) /* Dequeue our now empty save area block */
1071:
1072: nodqsave: addi r22,r20,LTR_size /* Point to the next trace entry */
1073: stw r25,SVinuse(r8) /* Set the in use count */
1074: li r17,0 /* Clear this for the lock */
1075: cmplw r22,r21 /* Do we need to wrap the trace table? */
1076: stw r17,SAVprev(r10) /* Clear back pointer for the newly allocated guy */
1077: mtsprg 1,r10 /* Get set for the next 'rupt */
1078: bne+ gotTrcEnt /* We got a trace entry... */
1079:
1080: lwz r22,LOW_ADDR(EXT(traceStart)-EXT(ExceptionVectorsStart))(br0) /* Wrap back to the top */
1081:
1082: gotTrcEnt: bne- cr5,skipTrace1 /* Don't want to trace this kind... */
1083:
1084: stw r22,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) /* Set the next entry for the next guy */
1085:
1086: #if ESPDEBUG
1087: li r22,0x180 ; (TEST/DEBUG)
1088: dcbst br0,r22 ; (TEST/DEBUG)
1089: sync ; (TEST/DEBUG)
1090: #endif
1091:
1092: dcbz 0,r20 /* Allocate cache for the entry */
1093:
1094: skipTrace1: sync /* Make sure all stores are done */
1095: stw r17,SVlock(r8) /* Unlock both save and trace areas */
1096:
1097: #if RUPTTRC
1098: lis r14,0x7FFF /* (TEST/DEBUG) */
1099: mfdec r17 /* (TEST/DEBUG) */
1100: or r14,r14,r17 /* (TEST/DEBUG) */
1101: mtdec r14 /* (TEST/DEBUG) */
1102: li r14,0x20 /* (TEST/DEBUG) */
1103:
1104: lwarx r16,0,r14 ; ?
1105:
1106: mpwait1: lwarx r16,0,r14 /* (TEST/DEBUG) */
1107: mr. r16,r16 /* (TEST/DEBUG) */
1108: bne- mpwait1 /* (TEST/DEBUG) */
1109: stwcx. r14,0,r14 /* (TEST/DEBUG) */
1110: bne- mpwait1 /* (TEST/DEBUG) */
1111:
1112: stw r0,0x280(br0) /* (TEST/DEBUG) */
1113: stmw r1,0x284(br0) /* (TEST/DEBUG) */
1114: bne cr7,nono2 /* (TEST/DEBUG) */
1115: lwz r0,0(br0) /* (TEST/DEBUG) */
1116: mr. r0,r0 /* (TEST/DEBUG) */
1117: beq+ nono2 /* (TEST/DEBUG) */
1118: bne cr6,nopir3 /* (TEST/DEBUG) */
1119: mfspr r4,pir /* (TEST/DEBUG) */
1120: b gotpir3 /* (TEST/DEBUG) */
1121: nopir3: li r4,0 /* (TEST/DEBUG) */
1122: gotpir3: /* (TEST/DEBUG) */
1123: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1124: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
1125: li r3,0 /* (TEST/DEBUG) */
1126: mr r5,r10 /* (TEST/DEBUG) */
1127: oris r4,r4,0x3030 /* (TEST/DEBUG) */
1128: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1129: ori r4,r4,0x3230 /* (TEST/DEBUG) */
1130: mtlr r31 /* (TEST/DEBUG) */
1131: blrl /* (TEST/DEBUG) */
1132: nono2:
1133: lmw r1,0x284(br0) /* (TEST/DEBUG) */
1134: lwz r0,0x280(br0) /* (TEST/DEBUG) */
1135: li r16,0 /* (TEST/DEBUG) */
1136: stw r16,0x20(br0) /* (TEST/DEBUG) */
1137: mtdec r17 /* (TEST/DEBUG) */
1138:
1139: #endif
1140:
1141:
1142:
1143: /*
1144: * At this point, we can take another exception and lose nothing.
1145: *
1146: * We still have the current savearea pointed to by R13, the next by R10 and
1147: * sprg1. R20 contains the pointer to a trace entry and CR5_eq says
1148: * to do the trace or not.
1149: *
1150: * Note that R13 was chosen as the save area pointer because the SIGP,
1151: * firmware, and DSI/ISI handlers aren't supposed to touch anything
1152: * over R12. But, actually, the DSI/ISI stuff does.
1153: *
1154: *
1155: * Let's cut that trace entry now.
1156: */
1157:
1158: bne- cr5,skipTrace2 /* Don't want to trace this kind... */
1159:
1160: li r14,32 /* Second line of entry */
1161:
1162: getTB: mftbu r16 /* Get the upper timebase */
1163: mftb r17 /* Get the lower timebase */
1164: mftbu r18 /* Get the upper one again */
1165: cmplw r16,r18 /* Did the top tick? */
1166: bne- getTB /* Yeah, need to get it again... */
1167:
1168: dcbz r14,r20 /* Zap the second half */
1169:
1170: stw r16,LTR_timeHi(r20) /* Set the upper part of TB */
1171: bne cr6,nopir4 /* Is there a processor ID number on this guy? */
1172: mfspr r19,pir /* Get the processor address */
1173: b gotpir4 /* Got it... */
1174: nopir4: li r19,0 /* Assume processor 0 for those underprivileged folks */
1175: gotpir4:
1176: lwz r1,saver1(r13) /* Get back interrupt time R1 */
1177: stw r17,LTR_timeLo(r20) /* Set the lower part of TB */
1178: rlwinm r19,r19,0,27,31 /* Cut the junk */
1179: stw r0,LTR_r0(r20) /* Save off register 0 */
1180: sth r19,LTR_cpu(r20) /* Stash the cpu address */
1181: stw r1,LTR_r1(r20) /* Save off register 1 */
1182: stw r2,LTR_r2(r20) /* Save off register 2 */
1183: stw r3,LTR_r3(r20) /* Save off register 3 */
1184: lwz r16,savecr(r13) /* We don't remember the CR anymore, get it */
1185: stw r4,LTR_r4(r20) /* Save off register 4 */
1186: mfsrr0 r17 /* Get this back, it's still good */
1187: stw r5,LTR_r5(r20) /* Save off register 5 */
1188: mfsrr1 r18 /* This is still good in here also */
1189:
1190: stw r16,LTR_cr(r20) /* Save the CR (or dec) */
1191: stw r17,LTR_srr0(r20) /* Save the SSR0 */
1192: stw r18,LTR_srr1(r20) /* Save the SRR1 */
1193: mfdar r17 /* Get this back */
1194:
1195: mflr r16 /* Get the LR */
1196: stw r17,LTR_dar(r20) /* Save the DAR */
1197: mfctr r17 /* Get the CTR */
1198: stw r16,LTR_lr(r20) /* Save the LR */
1199: #if 0
1200: lis r17,HIGH_ADDR(EXT(saveanchor)) ; (TEST/DEBUG)
1201: ori r17,r17,LOW_ADDR(EXT(saveanchor)) ; (TEST/DEBUG)
1202: lwz r16,SVcount(r17) ; (TEST/DEBUG)
1203: lwz r17,SVinuse(r17) ; (TEST/DEBUG)
1204: rlwimi r17,r16,16,0,15 ; (TEST/DEBUG)
1205: #endif
1206: stw r17,LTR_ctr(r20) /* Save off the CTR */
1207: stw r13,LTR_save(r20) /* Save the savearea */
1208: sth r11,LTR_excpt(r20) /* Save the exception type */
1209: #if ESPDEBUG
1210: addi r17,r20,32 ; (TEST/DEBUG)
1211: dcbst br0,r20 ; (TEST/DEBUG)
1212: dcbst br0,r17 ; (TEST/DEBUG)
1213: sync ; (TEST/DEBUG)
1214: #endif
1215:
1216: /*
1217: * We're done with the trace, except for maybe modifying the exception
1218: * code later on. So, that means that we need to save R20 and CR5, but
1219: * R0 to R5 are clear now.
1220: *
1221: * So, let's finish setting up the kernel registers now.
1222: */
1223:
1224: skipTrace2:
1225:
1226: #if PERFTIMES && DEBUG
1227: li r3,68 ; Indicate interrupt
1228: mr r4,r11 ; Get code to log
1229: mr r5,r13 ; Get savearea to log
1230: mr r8,r0 ; Save R0
1231: bl EXT(dbgLog2) ; Cut log entry
1232: mr r0,r8 ; Restore R0
1233: #endif
1234:
1235: mfsprg r2,0 /* Get the per processor block */
1236:
1237: #if 0
1238: lis r19,0xF300 /* (TEST/DEBUG) */
1239: ori r19,r19,0x0020 /* (TEST/DEBUG) */
1240: dcbi 0,r19 /* (TEST/DEBUG) */
1241: sync /* (TEST/DEBUG) */
1242: eieio /* (TEST/DEBUG) */
1243: lwz r18,0x000C(r19) /* (TEST/DEBUG) */
1244: eieio /* (TEST/DEBUG) */
1245: dcbi 0,r19 /* (TEST/DEBUG) */
1246: rlwinm. r4,r18,0,19,19 /* (TEST/DEBUG) */
1247: rlwinm r18,r18,0,20,18 /* (TEST/DEBUG) */
1248: sync /* (TEST/DEBUG) */
1249: eieio /* (TEST/DEBUG) */
1250: beq+ nonmi /* (TEST/DEBUG) */
1251:
1252: stw r18,0x0008(r19) /* (TEST/DEBUG) */
1253: dcbi 0,r19 /* (TEST/DEBUG) */
1254: sync /* (TEST/DEBUG) */
1255: eieio /* (TEST/DEBUG) */
1256: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1257:
1258: nonmi: /* (TEST/DEBUG) */
1259: #endif
1260:
1261: #if 0
1262: lis r4,hi16(EXT(hash_table_base)) ; (TEST/DEBUG)
1263: ori r4,r4,lo16(EXT(hash_table_base)) ; (TEST/DEBUG)
1264: lwz r8,0(r4) ; (TEST/DEBUG)
1265: lwz r4,4(r4) ; (TEST/DEBUG)
1266: add r8,r4,r8 ; (TEST/DEBUG)
1267:
1268: yyyck: lwz r12,4(r8) ; (TEST/DEBUG)
1269: rlwimn. r12,r12,0,24,31 ; (TEST/DEBUG)
1270: bne+ yyyok ; (TEST/DEBUG)
1271: BREAKPOINT_TRAP ; (TEST/DEBUG)
1272:
1273: yyyok: addi r8,r8,0x40 ; (TEST/DEBUG)
1274: subic r4,r4,0x40 ; (TEST/DEBUG)
1275: bgt+ yyyck ; (TEST/DEBUG)
1276: #endif
1277:
1278: #if CHECKSAVE
1279:
1280: lis r4,0x7FFF /* (TEST/DEBUG) */
1281: mfdec r12 /* (TEST/DEBUG) */
1282: or r4,r4,r12 /* (TEST/DEBUG) */
1283: mtdec r4 /* (TEST/DEBUG) */
1284: li r4,0x20 /* (TEST/DEBUG) */
1285:
1286: lwarx r8,0,r4 ; ?
1287:
1288: mpwait2: lwarx r8,0,r4 /* (TEST/DEBUG) */
1289: mr. r8,r8 /* (TEST/DEBUG) */
1290: bne- mpwait2 /* (TEST/DEBUG) */
1291: stwcx. r4,0,r4 /* (TEST/DEBUG) */
1292: bne- mpwait2 /* (TEST/DEBUG) */
1293:
1294: isync /* (TEST/DEBUG) */
1295: lwz r4,0xD80(br0) /* (TEST/DEBUG) */
1296: mr. r4,r4 /* (TEST/DEBUG) */
1297: li r4,1 /* (TEST/DEBUG) */
1298: bne- doncheksv /* (TEST/DEBUG) */
1299:
1300: lis r8,HIGH_ADDR(EXT(saveanchor)) /* (TEST/DEBUG) */
1301: ori r8,r8,LOW_ADDR(EXT(saveanchor)) /* (TEST/DEBUG) */
1302:
1303: stw r4,0xD80(br0) /* (TEST/DEBUG) */
1304:
1305: lwarx r4,0,r8 ; ?
1306:
1307: mpwait2x: lwarx r4,0,r8 /* (TEST/DEBUG) */
1308: mr. r4,r4 /* (TEST/DEBUG) */
1309: bne- mpwait2x /* (TEST/DEBUG) */
1310: stwcx. r8,0,r8 /* (TEST/DEBUG) */
1311: bne- mpwait2x /* (TEST/DEBUG) */
1312:
1313: isync /* (TEST/DEBUG) */
1314:
1315: #if 0
1316: rlwinm r4,r13,0,0,19 /* (TEST/DEBUG) */
1317: lwz r21,SACflags(r4) /* (TEST/DEBUG) */
1318: rlwinm r22,r21,24,24,31 /* (TEST/DEBUG) */
1319: cmplwi r22,0x00EE /* (TEST/DEBUG) */
1320: lwz r22,SACvrswap(r4) /* (TEST/DEBUG) */
1321: bne- currbad /* (TEST/DEBUG) */
1322: andis. r21,r21,hi16(sac_perm) /* (TEST/DEBUG) */
1323: bne- currnotbad /* (TEST/DEBUG) */
1324: mr. r22,r22 /* (TEST/DEBUG) */
1325: bne+ currnotbad /* (TEST/DEBUG) */
1326:
1327: currbad: lis r23,hi16(EXT(debugbackpocket)) /* (TEST/DEBUG) */
1328: ori r23,r23,lo16(EXT(debugbackpocket)) /* (TEST/DEBUG) */
1329: stw r23,SVfree(r8) /* (TEST/DEBUG) */
1330:
1331: mfsprg r25,1 /* (TEST/DEBUG) */
1332: mtsprg 1,r23 /* (TEST/DEBUG) */
1333: lwz r26,SACalloc(r23) /* (TEST/DEBUG) */
1334: rlwinm r26,r26,0,1,31 /* (TEST/DEBUG) */
1335: stw r26,SACalloc(r23) /* (TEST/DEBUG) */
1336:
1337: sync /* (TEST/DEBUG) */
1338: li r28,0 /* (TEST/DEBUG) */
1339: stw r28,0x20(br0) /* (TEST/DEBUG) */
1340: stw r28,0(r8) /* (TEST/DEBUG) */
1341: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1342:
1343: currnotbad:
1344: #endif
1345:
1346: lwz r28,SVcount(r8) /* (TEST/DEBUG) */
1347: #if RUPTTRC
1348: stw r0,0x280(br0) /* (TEST/DEBUG) */
1349: stmw r1,0x284(br0) /* (TEST/DEBUG) */
1350: bne cr7,nono90 /* (TEST/DEBUG) */
1351: lwz r0,0(br0) /* (TEST/DEBUG) */
1352: mr. r0,r0 /* (TEST/DEBUG) */
1353: beq+ nono90 /* (TEST/DEBUG) */
1354: bne cr6,nopir5 /* (TEST/DEBUG) */
1355: mfspr r4,pir /* (TEST/DEBUG) */
1356: b gotpir0 /* (TEST/DEBUG) */
1357: nopir5: li r4,0 /* (TEST/DEBUG) */
1358: gotpir5: /* (TEST/DEBUG) */
1359: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1360: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
1361: li r3,0 /* (TEST/DEBUG) */
1362: mr r5,r28 /* (TEST/DEBUG) */
1363: oris r4,r4,0x3036 /* (TEST/DEBUG) */
1364: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1365: ori r4,r4,0x3636 /* (TEST/DEBUG) */
1366: mtlr r31 /* (TEST/DEBUG) */
1367: blrl /* (TEST/DEBUG) */
1368: nono90:
1369: lmw r1,0x284(br0) /* (TEST/DEBUG) */
1370: lwz r0,0x280(br0) /* (TEST/DEBUG) */
1371: #endif
1372: lwz r21,SVinuse(r8) /* (TEST/DEBUG) */
1373: lwz r23,SVmin(r8) /* (TEST/DEBUG) */
1374: sub r22,r28,r21 /* (TEST/DEBUG) */
1375: cmpw r22,r23 /* (TEST/DEBUG) */
1376: bge+ cksave0 /* (TEST/DEBUG) */
1377:
1378: li r4,0 /* (TEST/DEBUG) */
1379: stw r4,0x20(br0) /* (TEST/DEBUG) */
1380: stw r4,0(r8) /* (TEST/DEBUG) */
1381: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1382:
1383: cksave0: lwz r28,SVfree(r8) /* (TEST/DEBUG) */
1384: li r24,0 /* (TEST/DEBUG) */
1385: li r29,1 /* (TEST/SAVE) */
1386:
1387: cksave0a: mr. r28,r28 /* (TEST/DEBUG) */
1388: beq- cksave3 /* (TEST/DEBUG) */
1389:
1390: rlwinm. r21,r28,0,4,19 /* (TEST/DEBUG) */
1391: bne+ cksave1 /* (TEST/DEBUG) */
1392:
1393: li r4,0 /* (TEST/DEBUG) */
1394: stw r4,0x20(br0) /* (TEST/DEBUG) */
1395: stw r4,0(r8) /* (TEST/DEBUG) */
1396: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1397:
1398: cksave1: rlwinm. r21,r28,0,21,3 /* (TEST/DEBUG) */
1399: beq+ cksave2 /* (TEST/DEBUG) */
1400:
1401: li r4,0 /* (TEST/DEBUG) */
1402: stw r4,0x20(br0) /* (TEST/DEBUG) */
1403: stw r4,0(r8) /* (TEST/DEBUG) */
1404: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1405:
1406: cksave2: lwz r25,SACalloc(r28) /* (TEST/DEBUG) */
1407: lbz r26,SACflags+2(r28) /* (TEST/DEBUG) */
1408: lbz r21,SACflags+3(r28) /* (TEST/DEBUG) */
1409: cmplwi r26,0x00EE /* (TEST/DEBUG) */
1410: stb r29,SACflags+3(r28) /* (TEST/DEBUG) */
1411: beq+ cksave2z
1412:
1413: li r4,0 /* (TEST/DEBUG) */
1414: stw r4,0x20(br0) /* (TEST/DEBUG) */
1415: stw r4,0(r8) /* (TEST/DEBUG) */
1416: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1417:
1418: cksave2z: mr. r21,r21 /* (TEST/DEBUG) */
1419: beq+ cksave2a /* (TEST/DEBUG) */
1420:
1421: li r4,0 /* (TEST/DEBUG) */
1422: stw r4,0x20(br0) /* (TEST/DEBUG) */
1423: stw r4,0(r8) /* (TEST/DEBUG) */
1424: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1425:
1426: cksave2a: rlwinm r26,r25,1,31,31 /* (TEST/DEBUG) */
1427: rlwinm r27,r25,2,31,31 /* (TEST/DEBUG) */
1428: add r24,r24,r26 /* (TEST/DEBUG) */
1429: add r24,r24,r27 /* (TEST/DEBUG) */
1430: lwz r28,SACnext(r28) /* (TEST/DEBUG) */
1431: b cksave0a /* (TEST/DEBUG) */
1432:
1433: cksave3: cmplw r24,r22 /* (TEST/DEBUG) */
1434: beq+ cksave4 /* (TEST/DEBUG) */
1435:
1436: li r4,0 /* (TEST/DEBUG) */
1437: stw r4,0x20(br0) /* (TEST/DEBUG) */
1438: stw r4,0(r8) /* (TEST/DEBUG) */
1439: BREAKPOINT_TRAP /* (TEST/DEBUG) */
1440:
1441: cksave4: lwz r28,SVfree(r8) /* (TEST/DEBUG) */
1442: li r24,0 /* (TEST/DEBUG) */
1443:
1444: cksave5: mr. r28,r28 /* (TEST/DEBUG) */
1445: beq- cksave6 /* (TEST/DEBUG) */
1446: stb r24,SACflags+3(r28) /* (TEST/DEBUG) */
1447: lwz r28,SACnext(r28) /* (TEST/DEBUG) */
1448: b cksave5 /* (TEST/DEBUG) */
1449:
1450: cksave6:
1451:
1452: li r4,0 /* (TEST/DEBUG) */
1453: stw r4,0xD80(br0) /* (TEST/DEBUG) */
1454: stw r4,0(r8) /* (TEST/DEBUG) */
1455:
1456: doncheksv:
1457: li r4,0 /* (TEST/DEBUG) */
1458: stw r4,0x20(br0) /* (TEST/DEBUG) */
1459: mtdec r12 /* (TEST/DEBUG) */
1460: #endif
1461:
1462: #if 0
1463: lhz r4,0x980(br0) ; (TEST/DEBUG)
1464: xoris r4,r4,lo16(0xFFF8) ; (TEST/DEBUG)
1465: mr. r4,r4 ; (TEST/DEBUG)
1466: beq- dontkillmedead ; (TEST/DEBUG)
1467: mfmsr r12 ; (TEST/DEBUG)
1468: ori r4,r12,0x2000 ; (TEST/DEBUG)
1469: mtmsr r4 ; (TEST/DEBUG)
1470: isync ; (TEST/DEBUG)
1471: stfd f13,0x980(br0) ; (TEST/DEBUG)
1472: mtmsr r12 ; (TEST/DEBUG)
1473: isync ; (TEST/DEBUG)
1474: lhz r4,0x980(br0) ; (TEST/DEBUG)
1475: xoris r4,r4,lo16(0xFFF8) ; (TEST/DEBUG)
1476: mr. r4,r4 ; (TEST/DEBUG)
1477: bne+ dontkillmedead ; (TEST/DEBUG)
1478: BREAKPOINT_TRAP ; (TEST/DEBUG)
1479:
1480: dontkillmedead: ; (TEST/DEBUG)
1481: #endif
1482:
1483: lis r4,HIGH_ADDR(EXT(MPspec)) /* Get the MP control block */
1484: dcbt 0,r2 /* We'll need the per_proc in a sec */
1485: cmplwi cr0,r11,T_INTERRUPT /* Do we have an external interrupt? */
1486: ori r4,r4,LOW_ADDR(EXT(MPspec)) /* Get the bottom half of the MP control block */
1487: bne+ notracex /* Not an external... */
1488:
1489: /*
1490: * Here we check to see if there was a interprocessor signal
1491: */
1492:
1493: lwz r4,MPSSIGPhandler(r4) /* Get the address of the SIGP interrupt filter */
1494: lhz r3,PP_CPU_FLAGS(r2) /* Get the CPU flags */
1495: cmplwi cr1,r4,0 /* Check if signal filter is initialized yet */
1496: andi. r3,r3,LOW_ADDR(SIGPactive) /* See if this processor has started up */
1497: mtlr r4 /* Load up filter address */
1498: beq- cr1,notracex /* We don't have a filter yet... */
1499: beq- notracex /* This processor hasn't started filtering yet... */
1500:
1501: blrl /* Filter the interrupt */
1502:
1503: mfsprg r2,0 /* Make sure we have the per processor block */
1504: cmplwi cr0,r3,kMPIOInterruptPending /* See what the filter says */
1505: li r11,T_INTERRUPT /* Assume we have a regular external 'rupt */
1506: beq+ modRupt /* Yeah, we figured it would be... */
1507: li r11,T_SIGP /* Assume we had a signal processor interrupt */
1508: bgt+ modRupt /* Yeah, at this point we would assume so... */
1509: li r11,T_IN_VAIN /* Nothing there actually, so eat it */
1510:
1511: modRupt: stw r11,PP_SAVE_EXCEPTION_TYPE(r2) /* Set that it was either in vain or a SIGP */
1512: stw r11,saveexception(r13) /* Save the exception code here also */
1513: bne- cr5,notracex /* Jump if no tracing... */
1514: sth r11,LTR_excpt(r20) /* Save the exception type */
1515:
1516: notracex:
1517:
1518: #if 0
1519: bne cr6,nopir6 /* (TEST/DEBUG) */
1520: mfspr r7,pir /* (TEST/DEBUG) */
1521: b gotpir6 /* (TEST/DEBUG) */
1522: nopir6: li r7,0 /* (TEST/DEBUG) */
1523: gotpir6: /* (TEST/DEBUG) */
1524: lis r6,HIGH_ADDR(EXT(RuptCtrs)) /* (TEST/DEBUG) */
1525: rlwinm r7,r7,8,23,23 /* (TEST/DEBUG) */
1526: lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1527: rlwimi r7,r7,1,22,22 /* (TEST/DEBUG) */
1528: ori r6,r6,LOW_ADDR(EXT(RuptCtrs)) /* (TEST/DEBUG) */
1529: rlwinm r1,r11,2,0,29 /* (TEST/DEBUG) */
1530: add r6,r6,r7 /* (TEST/DEBUG) */
1531: ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1532: lwz r21,(47*16)+8(r6) /* (TEST/DEBUG) */
1533: lwz r22,(47*16)+12(r6) /* (TEST/DEBUG) */
1534: add r1,r1,r6 /* (TEST/DEBUG) */
1535: mftb r24 /* (TEST/DEBUG) */
1536: sub r22,r24,r22 /* (TEST/DEBUG) */
1537: lwz r4,4(r6) /* (TEST/DEBUG) */
1538: cmplw cr2,r22,r21 /* (TEST/DEBUG) */
1539: lwz r7,4(r1) /* (TEST/DEBUG) */
1540: lwz r21,8(r6) /* (TEST/DEBUG) */
1541: blt+ cr2,nottime /* (TEST/DEBUG) */
1542: stw r24,(47*16)+12(r6) /* (TEST/DEBUG) */
1543:
1544: nottime: addi r4,r4,1 /* (TEST/DEBUG) */
1545: lwz r22,8(r1) /* (TEST/DEBUG) */
1546: addi r7,r7,1 /* (TEST/DEBUG) */
1547: stw r4,4(r6) /* (TEST/DEBUG) */
1548: lwz r3,0(r6) /* (TEST/DEBUG) */
1549: mr. r21,r21 /* (TEST/DEBUG) */
1550: stw r7,4(r1) /* (TEST/DEBUG) */
1551: mtlr r12 /* (TEST/DEBUG) */
1552: lwz r1,0(r1) /* (TEST/DEBUG) */
1553: beq- nottimed1 /* (TEST/DEBUG) */
1554: blt+ cr2,isnttime1 /* (TEST/DEBUG) */
1555:
1556: nottimed1: mr. r3,r3 /* (TEST/DEBUG) */
1557: bgelrl+ /* (TEST/DEBUG) */
1558:
1559: isnttime1: mr. r22,r22 /* (TEST/DEBUG) */
1560: beq- nottimed2 /* (TEST/DEBUG) */
1561: blt+ cr2,isnttime2 /* (TEST/DEBUG) */
1562:
1563: nottimed2: mr. r3,r1 /* (TEST/DEBUG) */
1564: mtlr r12 /* (TEST/DEBUG) */
1565: mr r4,r7 /* (TEST/DEBUG) */
1566: bgelrl+ /* (TEST/DEBUG) */
1567: mr r3,r11 /* (TEST/DEBUG) */
1568:
1569: isnttime2: cmplwi r11,T_DATA_ACCESS /* (TEST/DEBUG) */
1570: lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1571: bne+ nodsidisp /* (TEST/DEBUG) */
1572: mr. r22,r22 /* (TEST/DEBUG) */
1573: beq- nottimed3 /* (TEST/DEBUG) */
1574: blt+ cr2,nodsidisp /* (TEST/DEBUG) */
1575:
1576: nottimed3: li r3,5 /* (TEST/DEBUG) */
1577: ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1578: lwz r4,savesrr0(r13) /* (TEST/DEBUG) */
1579: mtlr r12 /* (TEST/DEBUG) */
1580: blrl /* (TEST/DEBUG) */
1581:
1582: lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1583: ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1584: lis r3,9 /* (TEST/DEBUG) */
1585: ori r3,r3,5 /* (TEST/DEBUG) */
1586: mtlr r12 /* (TEST/DEBUG) */
1587: lwz r4,savedar(r13) /* (TEST/DEBUG) */
1588: blrl /* (TEST/DEBUG) */
1589:
1590: nodsidisp: cmplwi r11,T_INSTRUCTION_ACCESS /* (TEST/DEBUG) */
1591: lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1592: bne+ noisidisp /* (TEST/DEBUG) */
1593: mr. r22,r22 /* (TEST/DEBUG) */
1594: beq- nottimed4 /* (TEST/DEBUG) */
1595: blt+ cr2,noisidisp /* (TEST/DEBUG) */
1596:
1597: nottimed4: li r3,6 /* (TEST/DEBUG) */
1598: ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1599: lwz r4,savesrr0(r13) /* (TEST/DEBUG) */
1600: mtlr r12 /* (TEST/DEBUG) */
1601: blrl /* (TEST/DEBUG) */
1602:
1603: noisidisp: mr r3,r11 /* (TEST/DEBUG) */
1604: #endif
1605:
1606: #if 0
1607: cmplwi r11,T_PROGRAM /* (TEST/DEBUG) */
1608: lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1609: bne+ nopgmdisp /* (TEST/DEBUG) */
1610: li r3,7 /* (TEST/DEBUG) */
1611: ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
1612: lwz r4,savesrr0(r13) /* (TEST/DEBUG) */
1613: mtlr r12 /* (TEST/DEBUG) */
1614: blrl /* (TEST/DEBUG) */
1615:
1616: nopgmdisp: mr r3,r11 /* (TEST/DEBUG) */
1617: #endif
1618:
1619: #if RUPTTRC
1620:
1621: lis r6,0x7FFF /* (TEST/DEBUG) */
1622: mfdec r7 /* (TEST/DEBUG) */
1623: or r6,r6,r7 /* (TEST/DEBUG) */
1624: mtdec r6 /* (TEST/DEBUG) */
1625: li r6,0x20 /* (TEST/DEBUG) */
1626:
1627: lwarx r1,0,r6 ; ?
1628:
1629: mpwait3: lwarx r1,0,r6 /* (TEST/DEBUG) */
1630: mr. r1,r1 /* (TEST/DEBUG) */
1631: bne- mpwait3 /* (TEST/DEBUG) */
1632: stwcx. r6,0,r6 /* (TEST/DEBUG) */
1633: bne- mpwait3 /* (TEST/DEBUG) */
1634:
1635: stw r0,0x280(br0) /* (TEST/DEBUG) */
1636: stmw r1,0x284(br0) /* (TEST/DEBUG) */
1637: bne cr7,nono3 /* (TEST/DEBUG) */
1638: lwz r0,0(br0) /* (TEST/DEBUG) */
1639: mr. r0,r0 /* (TEST/DEBUG) */
1640: beq+ nono3 /* (TEST/DEBUG) */
1641: bne cr6,nopir7 /* (TEST/DEBUG) */
1642: mfspr r4,pir /* (TEST/DEBUG) */
1643: b gotpir7 /* (TEST/DEBUG) */
1644: nopir7: li r4,0 /* (TEST/DEBUG) */
1645: gotpir7: /* (TEST/DEBUG) */
1646: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1647: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
1648: li r3,0 /* (TEST/DEBUG) */
1649: mr r5,r11 /* (TEST/DEBUG) */
1650: oris r4,r4,0x3030 /* (TEST/DEBUG) */
1651: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1652: ori r4,r4,0x3330 /* (TEST/DEBUG) */
1653: mtlr r31 /* (TEST/DEBUG) */
1654: blrl /* (TEST/DEBUG) */
1655:
1656: bne cr6,nopir8 /* (TEST/DEBUG) */
1657: mfspr r4,pir /* (TEST/DEBUG) */
1658: b gotpir8 /* (TEST/DEBUG) */
1659: nopir8: li r4,0 /* (TEST/DEBUG) */
1660: gotpir8: /* (TEST/DEBUG) */
1661: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1662: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
1663: li r3,0 /* (TEST/DEBUG) */
1664: lwz r5,0x280(br0) /* (TEST/DEBUG) */
1665: oris r4,r4,0x3030 /* (TEST/DEBUG) */
1666: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1667: ori r4,r4,0x3430 /* (TEST/DEBUG) */
1668: mtlr r31 /* (TEST/DEBUG) */
1669: blrl /* (TEST/DEBUG) */
1670: nono3:
1671: lmw r1,0x284(br0) /* (TEST/DEBUG) */
1672: lwz r0,0x280(br0) /* (TEST/DEBUG) */
1673: li r6,0 /* (TEST/DEBUG) */
1674: stw r6,0x20(br0) /* (TEST/DEBUG) */
1675: mtdec r7 /* (TEST/DEBUG) */
1676:
1677: #endif
1678:
1679: li r21,0 ; Assume no processor register for now
1680: lis r12,hi16(EXT(hw_counts)) ; Get the high part of the interrupt counters
1681: bne- cr6,nopirhere ; Jump if this processor does not have a PIR...
1682: mfspr r21,pir ; Get the PIR
1683:
1684: nopirhere: ori r12,r12,lo16(EXT(hw_counts)) ; Get the low part of the interrupt counters
1685: rlwinm r21,r21,8,20,23 ; Get index to processor counts
1686: mtcrf 0x80,r0 /* Set our CR0 to the high nybble of the request code */
1687: rlwinm r6,r0,1,0,31 /* Move sign bit to the end */
1688: cmplwi cr1,r11,T_SYSTEM_CALL /* Did we get a system call? */
1689: crandc cr0_lt,cr0_lt,cr0_gt /* See if we have R0 equal to 0b10xx...x */
1690: add r12,r12,r21 ; Point to the processor count area
1691: cmplwi cr3,r11,T_IN_VAIN /* Was this all in vain? All for nothing? */
1692: lwzx r22,r12,r11 ; Get the old value
1693: cmplwi cr2,r6,1 /* See if original R0 had the CutTrace request code in it */
1694: addi r22,r22,1 ; Count this one
1695: cmplwi cr4,r11,T_SIGP /* Indicate if we had a SIGP 'rupt */
1696: stwx r22,r12,r11 ; Store it back
1697:
1698: beq- cr3,EatRupt /* Interrupt was all for nothing... */
1699: cmplwi cr3,r11,T_MACHINE_CHECK ; Did we get a machine check?
1700: bne+ cr1,noCutT /* Not a system call... */
1701: bnl+ cr0,noCutT /* R0 not 0b10xxx...x, can't be any kind of magical system call... */
1702: beq- cr2,isCutTrace /* This is a CutTrace system call */
1703:
1704: /*
1705: * Here's where we call the firmware. If it returns T_IN_VAIN, that means
1706: * that it has handled the interruption. Remember: thou shalt not trash R13
1707: * or R20 while you are away. Anything else is ok.
1708: */
1709:
1710:
1711: lis r1,HIGH_ADDR(EXT(FirmwareCall)) /* Top half of firmware call handler */
1712: ori r1,r1,LOW_ADDR(EXT(FirmwareCall)) /* Bottom half of it */
1713: lwz r3,saver3(r13) /* Restore the first parameter, the rest are ok already */
1714: mtlr r1 /* Get it in the link register */
1715: blrl /* Call the handler */
1716:
1717: #if RUPTTRC
1718: lis r7,0x7FFF /* (TEST/DEBUG) */
1719: mfdec r6 /* (TEST/DEBUG) */
1720: or r7,r7,r6 /* (TEST/DEBUG) */
1721: mtdec r7 /* (TEST/DEBUG) */
1722: li r7,0x20 /* (TEST/DEBUG) */
1723:
1724: lwarx r1,0,r7 ; ?
1725:
1726: mpwait4: lwarx r1,0,r7 /* (TEST/DEBUG) */
1727: mr. r1,r1 /* (TEST/DEBUG) */
1728: bne- mpwait4 /* (TEST/DEBUG) */
1729: stwcx. r7,0,r7 /* (TEST/DEBUG) */
1730: bne- mpwait4 /* (TEST/DEBUG) */
1731:
1732: stw r0,0x280(br0) /* (TEST/DEBUG) */
1733: stmw r1,0x284(br0) /* (TEST/DEBUG) */
1734: bne cr7,nono4 /* (TEST/DEBUG) */
1735: lwz r0,0(br0) /* (TEST/DEBUG) */
1736: mr. r0,r0 /* (TEST/DEBUG) */
1737: beq+ nono4 /* (TEST/DEBUG) */
1738:
1739: bne cr6,nopir9 /* (TEST/DEBUG) */
1740: mfspr r4,pir /* (TEST/DEBUG) */
1741: b gotpir9 /* (TEST/DEBUG) */
1742: nopir9: li r4,0 /* (TEST/DEBUG) */
1743: gotpir9: /* (TEST/DEBUG) */
1744: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1745: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
1746: mr r5,r3 /* (TEST/DEBUG) */
1747: li r3,0 /* (TEST/DEBUG) */
1748: oris r4,r4,0x3030 /* (TEST/DEBUG) */
1749: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1750: ori r4,r4,0x3530 /* (TEST/DEBUG) */
1751: mtlr r31 /* (TEST/DEBUG) */
1752: blrl /* (TEST/DEBUG) */
1753: mtdec r25 /* (TEST/DEBUG) */
1754: nono4:
1755: lmw r1,0x284(br0) /* (TEST/DEBUG) */
1756: lwz r0,0x280(br0) /* (TEST/DEBUG) */
1757: li r7,0 /* (TEST/DEBUG) */
1758: stw r7,0x20(br0) /* (TEST/DEBUG) */
1759: mtdec r6 /* (TEST/DEBUG) */
1760: #endif
1761:
1762: cmplwi r3,T_IN_VAIN /* Was it handled? */
1763: mfsprg r2,0 /* Restore the per_processor area */
1764: beq+ EatRupt /* Interrupt was handled... */
1765: mr r11,r3 /* Put the 'rupt code in the right register */
1766: b noSIGP /* Go to the normal system call handler */
1767:
1768: isCutTrace:
1769: li r7,-32768 /* Get a 0x8000 for the exception code */
1770: bne- cr5,EatRupt /* Tracing is disabled... */
1771: sth r7,LTR_excpt(r20) /* Modify the exception type to a CutTrace */
1772: b EatRupt /* Time to go home... */
1773:
1774: /* We are here 'cause we didn't have a CutTrace system call */
1775:
1776: noCutT: beq- cr3,MachineCheck ; Whoa... Machine check...
1777: bne+ cr4,noSIGP /* Skip away if we didn't get a SIGP... */
1778:
1779: lis r6,HIGH_ADDR(EXT(MPsignalFW)) /* Top half of SIGP handler */
1780: ori r6,r6,LOW_ADDR(EXT(MPsignalFW)) /* Bottom half of it */
1781: mtlr r6 /* Get it in the link register */
1782:
1783: blrl /* Call the handler - we'll only come back if this is an AST, */
1784: /* 'cause FW can't handle that */
1785: mfsprg r2,0 /* Restore the per_processor area */
1786: ;
1787: ; The following interrupts are the only ones that can be redriven
1788: ; by the higher level code or emulation routines.
1789: ;
1790:
1791: Redrive: cmplwi cr0,r3,T_IN_VAIN /* Did the signal handler eat the signal? */
1792: mr r11,r3 /* Move it to the right place */
1793: beq+ cr0,EatRupt /* Bail now if the signal handler processed the signal... */
1794:
1795:
1796: /*
1797: * Here's where we check for the other fast-path exceptions: translation exceptions,
1798: * emulated instructions, etc.
1799: */
1800:
1801: noSIGP: cmplwi cr3,r11,T_ALTIVEC_ASSIST ; Check for an Altivec denorm assist
1802: cmplwi cr1,r11,T_PROGRAM /* See if we got a program exception */
1803: cmplwi cr2,r11,T_INSTRUCTION_ACCESS /* Check on an ISI */
1804: bne+ cr3,noAltivecAssist ; It is not an assist...
1805: b EXT(AltivecAssist) ; It is an assist...
1806:
1807: noAltivecAssist:
1808: bne+ cr1,noEmulate ; No emulation here...
1809: b EXT(Emulate) ; Go try to emulate...
1810:
1811: noEmulate: cmplwi cr3,r11,T_CSWITCH /* Are we context switching */
1812: cmplwi r11,T_DATA_ACCESS /* Check on a DSI */
1813: beq- cr2,DSIorISI /* It's a PTE fault... */
1814: beq- cr3,conswtch /* It's a context switch... */
1815: bne+ PassUp /* It's not a PTE fault... */
1816:
1817: /*
1818: * This call will either handle the fault, in which case it will not
1819: * return, or return to pass the fault up the line.
1820: */
1821:
1822: DSIorISI:
1823: lis r7,HIGH_ADDR(EXT(handlePF)) /* Top half of DSI handler */
1824: ori r7,r7,LOW_ADDR(EXT(handlePF)) /* Bottom half of it */
1825: mtlr r7 /* Get it in the link register */
1826: mr r3,r11 /* Move the 'rupt code */
1827:
1828: blrl /* See if we can handle this fault */
1829:
1830: #if RUPTTRC
1831: bne cr7,nononono2 /* (TEST/DEBUG) */
1832: lwz r7,0(br0) /* (TEST/DEBUG) */
1833: mr. r7,r7 /* (TEST/DEBUG) */
1834: beq+ nononono2 /* (TEST/DEBUG) */
1835: #if 0
1836: lis r7,0x7FFF /* (TEST/DEBUG) */
1837: mfdec r2 /* (TEST/DEBUG) */
1838: or r7,r7,r2 /* (TEST/DEBUG) */
1839: mtdec r7 /* (TEST/DEBUG) */
1840: li r7,0x20 /* (TEST/DEBUG) */
1841:
1842: lwarx r0,0,r7 ; ?
1843:
1844: yesyesyes2: lwarx r0,0,r7 /* (TEST/DEBUG) */
1845: mr. r0,r0 /* (TEST/DEBUG) */
1846: li r0,1 /* (TEST/DEBUG) */
1847: bne- yesyesyes2 /* (TEST/DEBUG) */
1848: stwcx. r0,0,r7 /* (TEST/DEBUG) */
1849: bne- yesyesyes2 /* (TEST/DEBUG) */
1850: #endif
1851: stw r0,0x280(br0) /* (TEST/DEBUG) */
1852: stmw r1,0x284(br0) /* (TEST/DEBUG) */
1853: mr r20,r3
1854: bne cr6,nopir10 /* (TEST/DEBUG) */
1855: mfspr r4,pir /* (TEST/DEBUG) */
1856: b gotpir10 /* (TEST/DEBUG) */
1857: nopir10: li r4,0 /* (TEST/DEBUG) */
1858: gotpir10: /* (TEST/DEBUG) */
1859: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1860: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
1861: li r3,0 /* (TEST/DEBUG) */
1862: or r4,r4,r20 /* (TEST/DEBUG) */
1863: lwz r5,savedar(r13) /* (TEST/DEBUG) */
1864: oris r4,r4,0x3030 /* (TEST/DEBUG) */
1865: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
1866: ori r4,r4,0x3630 /* (TEST/DEBUG) */
1867: mtlr r31 /* (TEST/DEBUG) */
1868: blrl /* (TEST/DEBUG) */
1869:
1870: #if 0
1871: lis r31,HIGH_ADDR(EXT(dbgRegs)) /* (TEST/DEBUG) */
1872: ori r31,r31,LOW_ADDR(EXT(dbgRegs)) /* (TEST/DEBUG) */
1873: mtlr r31 /* (TEST/DEBUG) */
1874: li r3,0 /* (TEST/DEBUG) */
1875: blrl /* (TEST/DEBUG) */
1876: #endif
1877: lmw r1,0x284(br0) /* (TEST/DEBUG) */
1878: lwz r0,0x280(br0) /* (TEST/DEBUG) */
1879: li r0,0 /* (TEST/DEBUG) */
1880: stw r0,0x20(br0) /* (TEST/DEBUG) */
1881: mtdec r2 /* (TEST/DEBUG) */
1882: nononono2: /* (TEST/DEBUG) */
1883: #endif
1884:
1885: lwz r0,savesrr1(r13) ; Get the MSR in use at exception time
1886: mfsprg r2, 0 /* Get back per_proc */
1887: cmplwi cr1,r3,T_IN_VAIN ; Was it handled?
1888: andi. r4,r0,lo16(MASK(MSR_RI)) ; See if the recover bit is on
1889: mr r11,r3 /* Make sure we can find this later */
1890: beq+ cr1,EatRupt ; Yeah, just blast back to the user...
1891: andc r0,r0,r4 ; Remove the recover bit
1892: beq+ PassUp ; Not on, normal case...
1893: lwz r4,savesrr0(r13) ; Get the failing instruction address
1894: lwz r5,savecr(r13) ; Get the condition register
1895: stw r0,savesrr1(r13) ; Save the result MSR
1896: addi r4,r4,4 ; Skip failing instruction
1897: rlwinm r5,r5,0,3,1 ; Clear CR0_EQ to let emulation code know we failed
1898: stw r4,savesrr0(r13) ; Save instruction address
1899: stw r4,savecr(r13) ; And the resume CR
1900: b EatRupt ; Resume emulated code
1901:
1902: /*
1903: * Here is where we handle the context switch firmware call. The old
1904: * context has been saved, and the new savearea in in saver3. We'll just
1905: * muck around with the savearea pointers, and then join the exit routine
1906: */
1907: conswtch: lwz r28,SAVflags(r13) /* The the flags of the current */
1908: mr r29,r13 /* Save the save */
1909: rlwinm r30,r13,0,0,19 /* Get the start of the savearea block */
1910: lwz r5,saver3(r13) /* Switch to the new savearea */
1911: oris r28,r28,HIGH_ADDR(SAVattach) /* Turn on the attached flag */
1912: lwz r30,SACvrswap(r30) /* get real to virtual translation */
1913: mr r13,r5 /* Switch saveareas */
1914: xor r27,r29,r30 /* Flip to virtual */
1915: stw r28,SAVflags(r29) /* Stash it back */
1916: stw r27,saver3(r5) /* Push the new savearea to the switch to routine */
1917: b EatRupt /* Start 'er up... */
1918:
1919: ;
1920: ; Handle machine check here.
1921: ;
1922: ; ?
1923: ;
1924: MachineCheck:
1925: lwz r27,savesrr1(r13) ; ?
1926: rlwinm. r11,r27,0,dcmck,dcmck ; ?
1927: beq+ notDCache ; ?
1928:
1929: mfspr r11,msscr0 ; ?
1930: dssall ; ?
1931: sync
1932:
1933: lwz r27,savesrr1(r13) ; ?
1934:
1935: hiccup: cmplw r27,r27 ; ?
1936: bne- hiccup ; ?
1937: isync ; ?
1938:
1939: oris r11,r11,hi16(dl1hwfm) ; ?
1940: mtspr msscr0,r11 ; ?
1941:
1942: rstbsy: mfspr r11,msscr0 ; ?
1943:
1944: rlwinm. r11,r11,0,dl1hwf,dl1hwf ; ?
1945: bne rstbsy ; ?
1946:
1947: sync ; ?
1948:
1949: li r11,T_IN_VAIN ; ?
1950: b EatRupt ; ?
1951:
1952:
1953: notDCache:
1954: ;
1955: ; Check if the failure was in
1956: ; ml_probe_read. If so, this is expected, so modify the PC to
1957: ; ml_proble_read_mck and then eat the exception.
1958: ;
1959: lwz r30,savesrr0(r13) ; Get the failing PC
1960: lis r28,hi16(EXT(ml_probe_read_mck)) ; High order part
1961: lis r27,hi16(EXT(ml_probe_read)) ; High order part
1962: ori r28,r28,lo16(EXT(ml_probe_read_mck)) ; Get the low part
1963: ori r27,r27,lo16(EXT(ml_probe_read)) ; Get the low part
1964: cmplw r30,r28 ; Check highest possible
1965: cmplw cr1,r30,r27 ; Check lowest
1966: bge- PassUp ; Outside of range
1967: blt- cr1,PassUp ; Outside of range
1968: ;
1969: ; We need to fix up the BATs here because the probe
1970: ; routine messed them all up... As long as we are at it,
1971: ; fix up to return directly to caller of probe.
1972: ;
1973:
1974: lwz r30,saver5(r13) ; Get proper DBAT values
1975: lwz r28,saver6(r13)
1976: lwz r27,saver7(r13)
1977: lwz r11,saver8(r13)
1978: lwz r18,saver9(r13)
1979:
1980: sync
1981: mtdbatu 0,r30 ; Restore DBAT 0 high
1982: mtdbatl 0,r28 ; Restore DBAT 0 low
1983: mtdbatu 1,r27 ; Restore DBAT 1 high
1984: mtdbatu 2,r11 ; Restore DBAT 2 high
1985: mtdbatu 3,r18 ; Restore DBAT 3 high
1986: sync
1987:
1988: lwz r28,savelr(r13) ; Get return point
1989: lwz r27,saver0(r13) ; Get the saved MSR
1990: li r30,0 ; Get a failure RC
1991: stw r28,savesrr0(r13) ; Set the return point
1992: stw r27,savesrr1(r13) ; Set the continued MSR
1993: stw r30,saver3(r13) ; Set return code
1994: li r11,T_IN_VAIN ; Set new interrupt code
1995: b EatRupt ; Yum, yum, eat it all up...
1996:
1997: /*
1998: * Here's where we come back from some instruction emulator. If we come back with
1999: * T_IN_VAIN, the emulation is done and we should just reload state and directly
2000: * go back to the interrupted code. Otherwise, we'll check to see if
2001: * we need to redrive with a different interrupt, i.e., DSI.
2002: */
2003:
2004: .align 5
2005: .globl EXT(EmulExit)
2006:
2007: LEXT(EmulExit)
2008:
2009: cmplwi r11,T_IN_VAIN /* Was it emulated? */
2010: lis r1,hi16(SAVredrive) ; Get redrive request
2011: mfsprg r2,0 ; Restore the per_proc area
2012: beq+ EatRupt /* Yeah, just blast back to the user... */
2013: lwz r4,SAVflags(r13) ; Pick up the flags
2014:
2015: and. r0,r4,r1 ; Check if redrive requested
2016: andc r4,r4,r1 ; Clear redrive
2017:
2018: beq+ PassUp ; No redrive, just keep on going...
2019:
2020: lwz r3,saveexception(r13) ; Restore exception code
2021: stw r4,SAVflags(r13) ; Set the flags
2022: b Redrive ; Redrive the exception...
2023:
2024: /* Jump into main handler code switching on VM at the same time */
2025:
2026: /* We assume kernel data is mapped contiguously in physical
2027: * memory, otherwise we'd need to switch on (at least) virtual data.
2028: * SRs are already set up.
2029: */
2030: PassUp: lwz r2,PP_PHYS_EXCEPTION_HANDLERS(r2) /* Pick up the exception handler base */
2031: lwzx r6,r2,r11 /* Get the actual exception handler address */
2032:
2033: PassUpDeb: lwz r8,SAVflags(r13) /* Get the flags */
2034: mtsrr0 r6 /* Set up the handler address */
2035: oris r8,r8,HIGH_ADDR(SAVattach) /* Since we're passing it up, attach it */
2036: rlwinm r5,r13,0,0,19 /* Back off to the start of savearea block */
2037:
2038: mfmsr r3 /* Get our MSR */
2039: stw r8,SAVflags(r13) /* Pass up the flags */
2040: rlwinm r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1 /* Clear all but the trace bits */
2041: li r2,MSR_SUPERVISOR_INT_OFF /* Get our normal MSR value */
2042: lwz r5,SACvrswap(r5) /* Get real to virtual conversion */
2043: or r2,r2,r3 /* Keep the trace bits if they're on */
2044: mr r3,r11 /* Pass the exception code in the paramter reg */
2045: mtsrr1 r2 /* Set up our normal MSR value */
2046: xor r4,r13,r5 /* Pass up the virtual address of context savearea */
2047:
2048: #if RUPTTRC
2049: lis r20,0x7FFF /* (TEST/DEBUG) */
2050: mfdec r25 /* (TEST/DEBUG) */
2051: or r20,r20,r25 /* (TEST/DEBUG) */
2052: mtdec r20 /* (TEST/DEBUG) */
2053: li r20,0x20 /* (TEST/DEBUG) */
2054:
2055: lwarx r21,0,r20 ; ?
2056:
2057: mpwait5: lwarx r21,0,r20 /* (TEST/DEBUG) */
2058: mr. r21,r21 /* (TEST/DEBUG) */
2059: bne- mpwait5 /* (TEST/DEBUG) */
2060: stwcx. r20,0,r20 /* (TEST/DEBUG) */
2061: bne- mpwait5 /* (TEST/DEBUG) */
2062:
2063: stw r0,0x280(br0) /* (TEST/DEBUG) */
2064: stmw r1,0x284(br0) /* (TEST/DEBUG) */
2065: bne cr7,nono9 /* (TEST/DEBUG) */
2066: lwz r0,0(br0) /* (TEST/DEBUG) */
2067: mr. r0,r0 /* (TEST/DEBUG) */
2068: beq+ nono9 /* (TEST/DEBUG) */
2069: mr r30,r4 /* (TEST/DEBUG) */
2070: mr r24,r5 /* (TEST/DEBUG) */
2071:
2072: bne cr6,nopir11 /* (TEST/DEBUG) */
2073: mfspr r4,pir /* (TEST/DEBUG) */
2074: b gotpir11 /* (TEST/DEBUG) */
2075: nopir11: li r4,0 /* (TEST/DEBUG) */
2076: gotpir11: /* (TEST/DEBUG) */
2077: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2078: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2079: li r3,0 /* (TEST/DEBUG) */
2080: mr r5,r6 /* (TEST/DEBUG) */
2081: oris r4,r4,0x3030 /* (TEST/DEBUG) */
2082: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2083: ori r4,r4,0x3930 /* (TEST/DEBUG) */
2084: mtlr r31 /* (TEST/DEBUG) */
2085: blrl /* (TEST/DEBUG) */
2086:
2087: bne cr6,nopir12 /* (TEST/DEBUG) */
2088: mfspr r4,pir /* (TEST/DEBUG) */
2089: b gotpir12 /* (TEST/DEBUG) */
2090: nopir12: li r4,0 /* (TEST/DEBUG) */
2091: gotpir12: /* (TEST/DEBUG) */
2092: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2093: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2094: li r3,0 /* (TEST/DEBUG) */
2095: mr r5,r30 /* (TEST/DEBUG) */
2096: oris r4,r4,0x3031 /* (TEST/DEBUG) */
2097: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2098: ori r4,r4,0x3130 /* (TEST/DEBUG) */
2099: mtlr r31 /* (TEST/DEBUG) */
2100: blrl /* (TEST/DEBUG) */
2101:
2102: bne cr6,nopir13 /* (TEST/DEBUG) */
2103: mfspr r4,pir /* (TEST/DEBUG) */
2104: b gotpir13 /* (TEST/DEBUG) */
2105: nopir13: li r4,0 /* (TEST/DEBUG) */
2106: gotpir13: /* (TEST/DEBUG) */
2107: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2108: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2109: li r3,0 /* (TEST/DEBUG) */
2110: xor r5,r30,r24 /* (TEST/DEBUG) */
2111: oris r4,r4,0x3031 /* (TEST/DEBUG) */
2112: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2113: ori r4,r4,0x3131 /* (TEST/DEBUG) */
2114: mtlr r31 /* (TEST/DEBUG) */
2115: blrl /* (TEST/DEBUG) */
2116:
2117: bne cr6,nopir14 /* (TEST/DEBUG) */
2118: mfspr r4,pir /* (TEST/DEBUG) */
2119: b gotpir14 /* (TEST/DEBUG) */
2120: nopir14: li r4,0 /* (TEST/DEBUG) */
2121: gotpir14: /* (TEST/DEBUG) */
2122: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2123: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2124: li r3,0 /* (TEST/DEBUG) */
2125: mr r5,r25 /* (TEST/DEBUG) */
2126: oris r4,r4,0x3031 /* (TEST/DEBUG) */
2127: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2128: ori r4,r4,0x3132 /* (TEST/DEBUG) */
2129: mtlr r31 /* (TEST/DEBUG) */
2130: blrl /* (TEST/DEBUG) */
2131:
2132: bne cr6,nopir15 /* (TEST/DEBUG) */
2133: mfspr r4,pir /* (TEST/DEBUG) */
2134: b gotpir15 /* (TEST/DEBUG) */
2135: nopir15: li r4,0 /* (TEST/DEBUG) */
2136: gotpir15: /* (TEST/DEBUG) */
2137: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2138: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2139: li r3,0 /* (TEST/DEBUG) */
2140: mfsrr0 r5 /* (TEST/DEBUG) */
2141: oris r4,r4,0x3031 /* (TEST/DEBUG) */
2142: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2143: ori r4,r4,0x3133 /* (TEST/DEBUG) */
2144: mtlr r31 /* (TEST/DEBUG) */
2145: blrl /* (TEST/DEBUG) */
2146: nono9:
2147: lmw r1,0x284(br0) /* (TEST/DEBUG) */
2148: lwz r0,0x280(br0) /* (TEST/DEBUG) */
2149: li r20,0 /* (TEST/DEBUG) */
2150: stw r20,0x20(br0) /* (TEST/DEBUG) */
2151: mtdec r25 /* (TEST/DEBUG) */
2152: #endif
2153:
2154: rfi /* Launch the exception handler */
2155:
2156: .long 0 /* Leave these here gol durn it! */
2157: .long 0
2158: .long 0
2159: .long 0
2160: .long 0
2161: .long 0
2162: .long 0
2163: .long 0
2164:
2165: /*
2166: * This routine is the only place where we return from an interruption.
2167: * Anyplace else is wrong. Even if I write the code, it's still wrong
2168: * Feel free to come by and slap me if I do do it. Even though I may
2169: * have had a good reason to do it.
2170: *
2171: * All we need to remember here is that R13 must point to the savearea
2172: * that has the context we need to load up. Translation and interruptions
2173: * must be disabled.
2174: *
2175: * This code always loads the context in the savearea pointed to
2176: * by R13. In the process, it throws away the savearea. If there
2177: * is any tomfoolery with savearea stacks, it must be taken care of
2178: * before we get here.
2179: */
2180:
2181: EatRupt: mr r31,r13 /* Move the savearea pointer to the far end of the register set */
2182:
2183: EatRupt2: mfsprg r2,0 /* Get the per_proc block */
2184:
2185: /*
2186: * First we see if we are able to free the new savearea.
2187: * If it is not attached to anything, put it on the free list.
2188: * This is real dangerous, we haven't restored context yet...
2189: * So, the free savearea chain lock must stay until the bitter end!
2190: */
2191:
2192: #if RUPTTRC
2193: lis r18,0x7FFF /* (TEST/DEBUG) */
2194: mfdec r25 /* (TEST/DEBUG) */
2195: or r18,r18,r25 /* (TEST/DEBUG) */
2196: mtdec r18 /* (TEST/DEBUG) */
2197: li r18,0x20 /* (TEST/DEBUG) */
2198:
2199: lwarx r19,0,r18 ; ?
2200:
2201: mpwait6: lwarx r19,0,r18 /* (TEST/DEBUG) */
2202: mr. r19,r19 /* (TEST/DEBUG) */
2203: bne- mpwait6 /* (TEST/DEBUG) */
2204: stwcx. r18,0,r18 /* (TEST/DEBUG) */
2205: bne- mpwait6 /* (TEST/DEBUG) */
2206:
2207: stw r0,0x280(br0) /* (TEST/DEBUG) */
2208: stmw r1,0x284(br0) /* (TEST/DEBUG) */
2209: bne cr7,nono5 /* (TEST/DEBUG) */
2210: lwz r0,0(br0) /* (TEST/DEBUG) */
2211: mr. r0,r0 /* (TEST/DEBUG) */
2212: beq+ nono5 /* (TEST/DEBUG) */
2213:
2214: bne cr6,nopir16 /* (TEST/DEBUG) */
2215: mfspr r4,pir /* (TEST/DEBUG) */
2216: b gotpir16 /* (TEST/DEBUG) */
2217: nopir16: li r4,0 /* (TEST/DEBUG) */
2218: gotpir16: /* (TEST/DEBUG) */
2219: rlwinm r24,r31,0,0,19 /* (TEST/DEBUG) */
2220: mr r5,r31 /* (TEST/DEBUG) */
2221: mr r30,r31 /* (TEST/DEBUG) */
2222: lwz r24,SACvrswap(r24) /* (TEST/DEBUG) */
2223: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2224: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2225: li r3,0 /* (TEST/DEBUG) */
2226: oris r4,r4,0x3030 /* (TEST/DEBUG) */
2227: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2228: ori r4,r4,0x3730 /* (TEST/DEBUG) */
2229: mtlr r31 /* (TEST/DEBUG) */
2230: blrl /* (TEST/DEBUG) */
2231:
2232:
2233: bne cr6,nopir17 /* (TEST/DEBUG) */
2234: mfspr r4,pir /* (TEST/DEBUG) */
2235: b gotpir17 /* (TEST/DEBUG) */
2236: nopir17: li r4,0 /* (TEST/DEBUG) */
2237: gotpir17: /* (TEST/DEBUG) */
2238: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2239: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2240: li r3,0 /* (TEST/DEBUG) */
2241: xor r5,r30,r24 /* (TEST/DEBUG) */
2242: oris r4,r4,0x3030 /* (TEST/DEBUG) */
2243: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2244: ori r4,r4,0x3731 /* (TEST/DEBUG) */
2245: mtlr r31 /* (TEST/DEBUG) */
2246: blrl /* (TEST/DEBUG) */
2247:
2248: bne cr6,nopir18 /* (TEST/DEBUG) */
2249: mfspr r4,pir /* (TEST/DEBUG) */
2250: b gotpir18 /* (TEST/DEBUG) */
2251: nopir18: li r4,0 /* (TEST/DEBUG) */
2252: gotpir18: /* (TEST/DEBUG) */
2253: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2254: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2255: li r3,0 /* (TEST/DEBUG) */
2256: mfsprg r5,1 /* (TEST/DEBUG) */
2257: oris r4,r4,0x3030 /* (TEST/DEBUG) */
2258: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2259: ori r4,r4,0x3830 /* (TEST/DEBUG) */
2260: mtlr r31 /* (TEST/DEBUG) */
2261: blrl /* (TEST/DEBUG) */
2262:
2263: bne cr6,nopir19 /* (TEST/DEBUG) */
2264: mfspr r4,pir /* (TEST/DEBUG) */
2265: b gotpir19 /* (TEST/DEBUG) */
2266: nopir19: li r4,0 /* (TEST/DEBUG) */
2267: gotpir19: /* (TEST/DEBUG) */
2268: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2269: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2270: li r3,0 /* (TEST/DEBUG) */
2271: lwz r5,savesrr0(r30) /* (TEST/DEBUG) */
2272: oris r4,r4,0x3031 /* (TEST/DEBUG) */
2273: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2274: ori r4,r4,0x3130 /* (TEST/DEBUG) */
2275: mtlr r31 /* (TEST/DEBUG) */
2276: blrl /* (TEST/DEBUG) */
2277:
2278: bne cr6,nopir20 /* (TEST/DEBUG) */
2279: mfspr r4,pir /* (TEST/DEBUG) */
2280: b gotpir20 /* (TEST/DEBUG) */
2281: nopir20: li r4,0 /* (TEST/DEBUG) */
2282: gotpir20: /* (TEST/DEBUG) */
2283: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2284: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2285: li r3,0 /* (TEST/DEBUG) */
2286: lwz r5,savesrr1(r30) /* (TEST/DEBUG) */
2287: oris r4,r4,0x3031 /* (TEST/DEBUG) */
2288: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2289: ori r4,r4,0x3131 /* (TEST/DEBUG) */
2290: mtlr r31 /* (TEST/DEBUG) */
2291: blrl /* (TEST/DEBUG) */
2292:
2293: bne cr6,nopir21 /* (TEST/DEBUG) */
2294: mfspr r4,pir /* (TEST/DEBUG) */
2295: b gotpir21 /* (TEST/DEBUG) */
2296: nopir21: li r4,0 /* (TEST/DEBUG) */
2297: gotpir21: /* (TEST/DEBUG) */
2298: lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2299: rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */
2300: li r3,0 /* (TEST/DEBUG) */
2301: lwz r5,savelr(r30) /* (TEST/DEBUG) */
2302: oris r4,r4,0x3031 /* (TEST/DEBUG) */
2303: ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */
2304: ori r4,r4,0x3132 /* (TEST/DEBUG) */
2305: mtlr r31 /* (TEST/DEBUG) */
2306: blrl /* (TEST/DEBUG) */
2307: nono5:
2308: lmw r1,0x284(br0) /* (TEST/DEBUG) */
2309: lwz r0,0x280(br0) /* (TEST/DEBUG) */
2310: li r19,0 /* (TEST/DEBUG) */
2311: stw r19,0x20(br0) /* (TEST/DEBUG) */
2312: mtdec r25 /* (TEST/DEBUG) */
2313:
2314: #endif
2315:
2316:
2317: /*
2318: * It's dangerous here. We haven't restored anything from the current savearea yet.
2319: * And, we mark it the active one. So, if we get an exception in here, it is
2320: * unrecoverable. Unless we mess up, we can't get any kind of exception. So,
2321: * it is important to assay this code as only the purest of gold.
2322: *
2323: * But first, see if there is a savearea hanging off of quickfret. If so,
2324: * we release that one first and then come back for the other. We should rarely
2325: * see one, they appear when FPU or VMX context is discarded by either returning
2326: * to a higher exception level, or explicitly.
2327: *
2328: * A word about QUICKFRET: Multiple saveareas may be queued for release. It is
2329: * the responsibility of the queuer to insure that the savearea is not multiply
2330: * queued and that the appropriate inuse bits are reset.
2331: */
2332:
2333: #define TRCSAVE 0
2334:
2335: #if TRCSAVE
2336: lwz r30,saver0(r31) ; (TEST/DEBUG) Get users R0
2337: lwz r20,saveexception(r31) ; (TEST/DEBUG) Returning from trace?
2338: xor r30,r20,r30 ; (TEST/DEBUG) Make code
2339: rlwinm r30,r30,1,0,31 ; (TEST/DEBUG) Make an easy test
2340: cmplwi cr5,r30,0x61 ; (TEST/DEBUG) See if this is a trace
2341: #endif
2342:
2343: mr r18,r31 /* Save the savearea pointer */
2344: lwz r19,PP_QUICKFRET(r2) /* Get the quick release savearea */
2345:
2346: la r20,savesrr0(r18) /* Point to the first thing we look at */
2347: li r0,0 /* Get a zero */
2348: dcbt 0,r20 /* Touch in the first thing in the real savearea */
2349: la r21,savesr0(r18) /* Point to the first thing we restore */
2350: lis r30,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
2351: stw r0,PP_QUICKFRET(r2) /* Clear quickfret pointer */
2352: ori r30,r30,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
2353: dcbt 0,r21 /* Touch in the first thing */
2354:
2355: #if TRCSAVE
2356: beq- cr5,trkill0 ; (TEST/DEBUG) Do not trace this type
2357: lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
2358: mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
2359: beq- trkill0 ; (TEST/DEBUG) yes...
2360: bl cte ; (TEST/DEBUG) Trace this
2361: stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
2362: stw r19,LTR_r2(r20) ; (TEST/DEBUG) Quickfret savearea
2363: trkill0:
2364: #endif
2365:
2366: lwarx r22,0,r30 ; ?
2367:
2368: rtlck: lwarx r22,0,r30 /* Grab the lock value */
2369: li r23,1 /* Use part of the delay time */
2370: mr. r22,r22 /* Is it locked? */
2371: bne- rtlcks /* Yeah, wait for it to clear... */
2372: stwcx. r23,0,r30 /* Try to seize that there durn lock */
2373: beq+ fretagain ; Got it...
2374: b rtlck /* Collision, try again... */
2375:
2376: rtlcks: lwz r22,SVlock(r30) /* Get that lock in here */
2377: mr. r22,r22 /* Is it free yet? */
2378: beq+ rtlck /* Yeah, try for it again... */
2379: b rtlcks /* Sniff away... */
2380:
2381: ;
2382: ; Lock gotten, toss the saveareas
2383: ;
2384: fretagain:
2385: #if TRCSAVE
2386: beq- cr5,trkill1 ; (TEST/DEBUG) Do not trace this type
2387: lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
2388: mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
2389: beq- trkill1 ; (TEST/DEBUG) yes...
2390: li r0,1 ; (TEST/DEBUG) ID number
2391: bl cte ; (TEST/DEBUG) Trace this
2392: stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
2393: stw r19,LTR_r2(r20) ; (TEST/DEBUG) Quickfret savearea
2394: trkill1:
2395: #endif
2396:
2397: mr. r18,r18 ; Are we actually done here?
2398: beq- donefret ; Yeah...
2399: mr. r31,r19 ; Is there a quickfret to do?
2400: beq+ noqfrt ; Nope...
2401: lwz r19,SAVqfret(r19) ; Yes, get the next in line
2402: #if TRCSAVE
2403: beq- cr5,trkill2 ; (TEST/DEBUG) Do not trace this type
2404: lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
2405: mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
2406: beq- trkill2 ; (TEST/DEBUG) yes...
2407: li r0,2 ; (TEST/DEBUG) ID number
2408: bl cte ; (TEST/DEBUG) Trace this
2409: stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
2410: stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea
2411: stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
2412: trkill2:
2413: #endif
2414: b doqfrt ; Go do it...
2415:
2416: noqfrt: mr r31,r18 ; Set the area to release
2417: li r18,0 ; Show we have done it
2418: #if TRCSAVE
2419: beq- cr5,trkill3 ; (TEST/DEBUG) Do not trace this type
2420: lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
2421: mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
2422: beq- trkill3 ; (TEST/DEBUG) yes...
2423: li r0,3 ; (TEST/DEBUG) ID number
2424: bl cte ; (TEST/DEBUG) Trace this
2425: stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
2426: stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea
2427: stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
2428: trkill3:
2429: #endif
2430:
2431: doqfrt: li r0,0 ; Get a constant 0
2432: lis r26,0x8000 /* Build a bit mask and assume first savearea */
2433: stw r0,SAVqfret(r31) ; Make sure back chain is unlinked
2434: lwz r28,SAVflags(r31) ; Get the flags for the old active one
2435: #if TRCSAVE
2436: beq- cr5,trkill4 ; (TEST/DEBUG) Do not trace this type
2437: lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
2438: mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
2439: beq- trkill4 ; (TEST/DEBUG) yes...
2440: li r0,4 ; (TEST/DEBUG) ID number
2441: bl cte ; (TEST/DEBUG) Trace this
2442: stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
2443: stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea
2444: stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
2445: stw r28,LTR_r4(r20) ; (TEST/DEBUG) Save current flags
2446: trkill4:
2447: #endif
2448: rlwinm r25,r31,21,31,31 /* Get position of savearea in block */
2449: andis. r28,r28,HIGH_ADDR(SAVinuse) /* See if we need to free it */
2450: srw r26,r26,r25 /* Get bit position to deallocate */
2451: rlwinm r29,r31,0,0,19 /* Round savearea pointer to even page address */
2452:
2453: bne- fretagain /* Still in use, we can't free this one... */
2454:
2455: lwz r23,SACalloc(r29) /* Get the allocation for this block */
2456: lwz r24,SVinuse(r30) /* Get the in use count */
2457: mr r28,r23 ; (TEST/DEBUG) save for trace
2458: or r23,r23,r26 /* Turn on our bit */
2459: subi r24,r24,1 /* Show that this one is free */
2460: cmplw r23,r26 /* Is our's the only one free? */
2461: stw r23,SACalloc(r29) /* Save it out */
2462: bne+ rstrest /* Nope, then the block is already on the free list */
2463:
2464: lwz r22,SVfree(r30) /* Get the old head of the free list */
2465: stw r29,SVfree(r30) /* Point the head at us now */
2466: stw r22,SACnext(r29) ; Point us to the old last
2467:
2468: rstrest: stw r24,SVinuse(r30) /* Set the in use count */
2469: #if TRCSAVE
2470: beq- cr5,trkill5 ; (TEST/DEBUG) Do not trace this type
2471: lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
2472: mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
2473: beq- trkill5 ; (TEST/DEBUG) yes...
2474: li r0,5 ; (TEST/DEBUG) ID number
2475: bl cte ; (TEST/DEBUG) Trace this
2476: stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
2477: stw r19,LTR_r2(r20) ; (TEST/DEBUG) Next quickfret savearea
2478: stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
2479: stw r28,LTR_srr1(r20) ; (TEST/DEBUG) Save the original allocation
2480: stw r23,LTR_dar(r20) ; (TEST/DEBUG) Save the new allocation
2481: stw r24,LTR_save(r20) ; (TEST/DEBUG) Save the new in use count
2482: stw r22,LTR_lr(r20) ; (TEST/DEBUG) Save the old top of free list
2483: stw r29,LTR_ctr(r20) ; (TEST/DEBUG) Save the new top of free list
2484: trkill5:
2485: #endif
2486: b fretagain ; Go finish up the rest...
2487:
2488: ;
2489: ; Build the SR values depending upon destination. If we are going to the kernel,
2490: ; the SRs are almost all the way set up. SR14 (or the currently used copyin/out register)
2491: ; must be set to whatever it was at the last exception because it varies. All the rest
2492: ; have been set up already.
2493: ;
2494: ; If we are going into user space, we need to check a bit more. SR0, SR1, SR2, and
2495: ; SR14 (current implementation) must be restored always. The others must be set if
2496: ; they are different that what was loaded last time (i.e., tasks have switched).
2497: ; We check the last loaded address space ID and if the same, we skip the loads.
2498: ; This is a performance gain because SR manipulations are slow.
2499: ;
2500:
2501: donefret: lwz r26,savesrr1(r31) ; Get destination state flags
2502: lwz r15,PP_USERSPACE(r2) ; Pick up the user space ID we may launch
2503: rlwinm. r17,r26,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are going to user or system
2504: lwz r16,PP_LASTSPACE(r2) ; Pick up the last loaded SR value
2505: oris r13,r15,hi16(SEG_REG_PROT) ; Get the protection bits correct
2506:
2507: cmplw cr3,r15,r15 ; Set that we do not need to stop streams
2508: addis r14,r13,0x0010 ; Generate next SR value
2509: beq- gotokern ; We are going into kernel state, SRs all set up...
2510:
2511: mtsr sr0,r13 ; Set SR0
2512: addis r13,r14,0x0010 ; Generate next SR value
2513: cmplw cr3,r15,r16 ; See if most of the SRs are already loaded
2514: mtsr sr1,r14 ; Set SR1
2515: addis r14,r13,0x0010 ; Generate next SR value
2516: mtsr sr2,r13 ; Set SR2
2517: addis r13,r14,0x0010 ; Generate next SR value
2518: mtsr sr3,r14 ; Set SR3
2519:
2520: beq+ cr3,noloadsr ; SRs have not changed, no reload...
2521:
2522: addis r14,r13,0x0010 ; Generate next SR value
2523: mtsr sr4,r13 ; Set SR4
2524: addis r13,r14,0x0010 ; Generate next SR value
2525: mtsr sr5,r14 ; Set SR5
2526: addis r14,r13,0x0010 ; Generate next SR value
2527: mtsr sr6,r13 ; Set SR6
2528: addis r13,r14,0x0010 ; Generate next SR value
2529: mtsr sr7,r14 ; Set SR7
2530: addis r14,r13,0x0010 ; Generate next SR value
2531: mtsr sr8,r13 ; Set SR8
2532: addis r13,r14,0x0010 ; Generate next SR value
2533: mtsr sr9,r14 ; Set SR9
2534: addis r14,r13,0x0010 ; Generate next SR value
2535: mtsr sr10,r13 ; Set SR10
2536: addis r13,r14,0x0010 ; Generate next SR value
2537: mtsr sr11,r14 ; Set SR11
2538: addis r14,r13,0x0010 ; Generate next SR value
2539: mtsr sr12,r13 ; Set SR12
2540: addis r13,r14,0x0010 ; Generate next SR value
2541: mtsr sr13,r14 ; Set SR13
2542: addis r14,r13,0x0010 ; Generate next SR value
2543: mtsr sr14,r13 ; Set SR14
2544: mtsr sr15,r14 ; Set SR15
2545: stw r15,PP_LASTSPACE(r2) ; Set the last loaded SR value
2546: b ngotokern ; All done with user state SRs...
2547:
2548: noloadsr: oris r14,r15,hi16(SEG_REG_PROT|0x00E00000) ; Build SR14 (copyin/out) value
2549: b loadsr14 ; All done with user state SRs (except for SR14)...
2550:
2551: gotokern: lwz r14,savesr14(r31) ; Get the copyin/out register at interrupt time
2552:
2553: loadsr14: mtsr sr14,r14 ; Set SR14
2554:
2555: ngotokern: lwz r25,savesrr0(r31) /* Get the SRR0 to use */
2556: la r28,saver6(r31) /* Point to the next line to use */
2557: lwz r0,saver0(r31) /* Restore */
2558: dcbt 0,r28 /* Touch it in */
2559: lwz r1,saver1(r31) /* Restore */
2560: lwz r2,saver2(r31) /* Restore */
2561: la r28,saver14(r31) /* Point to the next line to get */
2562: lwz r3,saver3(r31) /* Restore */
2563: mtsrr0 r25 /* Restore the SRR0 now */
2564: lwz r4,saver4(r31) /* Restore */
2565: lwz r5,saver5(r31) /* Restore */
2566: mtsrr1 r26 /* Restore the SRR1 now */
2567: lwz r6,saver6(r31) /* Restore */
2568:
2569: dcbt 0,r28 /* Touch that next line on in */
2570:
2571: lwz r7,saver7(r31) /* Restore */
2572: lwz r8,saver8(r31) /* Restore */
2573: lwz r9,saver9(r31) /* Restore */
2574: lwz r10,saver10(r31) /* Restore */
2575: lwz r11,saver11(r31) /* Restore */
2576: lwz r12,saver12(r31) /* Restore */
2577: lwz r13,saver13(r31) /* Restore */
2578: la r28,saver22(r31) /* Point to the next line to do */
2579: lwz r14,saver14(r31) /* Restore */
2580: lwz r15,saver15(r31) /* Restore */
2581:
2582: dcbt 0,r28 /* Touch in another line of context */
2583:
2584: lwz r16,saver16(r31) /* Restore */
2585: lwz r17,saver17(r31) /* Restore */
2586: lwz r18,saver18(r31) /* Restore */
2587: lwz r19,saver19(r31) /* Restore */
2588: lwz r20,saver20(r31) /* Restore */
2589: lwz r21,saver21(r31) /* Restore */
2590: la r28,saver30(r31) /* Point to the final line */
2591: lwz r22,saver22(r31) /* Restore */
2592:
2593: dcbt 0,r28 /* Suck it in */
2594:
2595: lwz r23,saver23(r31) /* Restore */
2596: mfpvr r27 ; Get the processor version
2597: lwz r24,saver24(r31) /* Restore */
2598: rlwinm r27,r27,16,16,31 ; Get the processor type
2599: lwz r25,saver25(r31) /* Restore */
2600: cmplwi cr1,r27,PROCESSOR_VERSION_Max ; Do we have Altivec? */
2601: lwz r26,saver26(r31) /* Restore */
2602: lwz r27,saver27(r31) /* Restore */
2603:
2604: dcbt 0,r28 /* Get the final line */
2605: lwz r28,savecr(r31) /* Get CR to restore */
2606: blt cr1,noavec4 ; No vector on this machine
2607: lwz r29,savevrsave(r31) ; Get the vrsave
2608: beq+ cr3,noavec3 ; SRs have not changed, no need to stop the streams...
2609: dssall ; Kill all data streams
2610: ; The streams should be suspended
2611: ; already, and we do a bunch of
2612: ; dependent loads and a sync later
2613: ; so we should be cool.
2614:
2615: noavec3: mtspr vrsave,r29 ; Set the vrsave
2616:
2617: noavec4: lwz r29,savexer(r31) /* Get XER to restore */
2618: mtcr r28 /* Restore the CR */
2619: lwz r28,savelr(r31) /* Get LR to restore */
2620: mtxer r29 /* Restore the XER */
2621: lwz r29,savectr(r31) /* Get the CTR to restore */
2622: mtlr r28 /* Restore the LR */
2623: lwz r28,saver30(r31) /* Restore */
2624: mtctr r29 /* Restore the CTR */
2625: lwz r29,saver31(r31) /* Restore */
2626: mtsprg 2,r28 /* Save R30 */
2627: lwz r28,saver28(r31) /* Restore */
2628: mtsprg 3,r29 /* Save R31 */
2629: lwz r29,saver29(r31) /* Restore */
2630:
2631: #if PERFTIMES && DEBUG
2632: stmw r1,0x280(br0) ; Save all registers
2633: mfcr r20 ; Save the CR
2634: mflr r21 ; Save the LR
2635: mfsrr0 r9 ; Save SRR0
2636: mfsrr1 r11 ; Save SRR1
2637: mr r8,r0 ; Save R0
2638: li r3,69 ; Indicate interrupt
2639: mr r4,r11 ; Set MSR to log
2640: mr r5,r31 ; Get savearea to log
2641: bl EXT(dbgLog2) ; Cut log entry
2642: mr r0,r8 ; Restore R0
2643: mtsrr0 r9 ; Restore SRR0
2644: mtsrr1 r11 ; Restore SRR1
2645: mtlr r21 ; Restore the LR
2646: mtcr r20 ; Restore the CR
2647: lmw r1,0x280(br0) ; Restore all the rest
2648: #endif
2649:
2650: li r31,0 /* Get set to clear lock */
2651: sync /* Make sure it's all out there */
2652: stw r31,SVlock(r30) /* Unlock it */
2653: mfsprg r30,2 /* Restore R30 */
2654: mfsprg r31,3 /* Restore R31 */
2655:
2656: rfi /* Click heels three times and think very hard that there's no place like home */
2657:
2658: .long 0 /* For old 601 bug */
2659: .long 0
2660: .long 0
2661: .long 0
2662: .long 0
2663: .long 0
2664: .long 0
2665: .long 0
2666:
2667:
2668:
2669:
2670: /*
2671: * exception_exit(savearea *)
2672: *
2673: *
2674: * ENTRY : IR and/or DR and/or interruptions can be on
2675: * R3 points to the physical address of a savearea
2676: */
2677:
2678: .align 5
2679: .globl EXT(exception_exit)
2680:
2681: nop ; Align ISYNC to last line in cache
2682: nop
2683:
2684: LEXT(exception_exit)
2685:
2686: mfmsr r30 /* Get the current MSR */
2687: mr r31,r3 /* Get the savearea in the right register */
2688: andi. r30,r30,0x7FCF /* Turn off externals, IR, and DR */
2689: lis r1,hi16(SAVredrive) ; Get redrive request
2690: mtmsr r30 /* Translation and all off */
2691: isync /* Toss prefetch */
2692:
2693: mfsprg r2,0 ; Get the per_proc block
2694: lwz r4,SAVflags(r3) ; Pick up the flags
2695: mr r13,r3 ; Put savearea here also
2696:
2697: and. r0,r4,r1 ; Check if redrive requested
2698: andc r4,r4,r1 ; Clear redrive
2699:
2700: dcbt br0,r2 ; We will need this in just a sec
2701:
2702: beq+ EatRupt ; No redrive, just exit...
2703:
2704: lwz r3,saveexception(r13) ; Restore exception code
2705: stw r4,SAVflags(r13) ; Set the flags
2706: b Redrive ; Redrive the exception...
2707:
2708: ;
2709: ; Make trace entry for lowmem_vectors internal debug
2710: ;
2711: #if TRCSAVE
2712: cte:
2713: lwz r20,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) ; Pick up the current trace entry
2714: lwz r16,LOW_ADDR(EXT(traceEnd)-EXT(ExceptionVectorsStart))(br0) ; Grab up the end of it all
2715: addi r17,r20,LTR_size ; Point to the next trace entry
2716: cmplw r17,r16 ; Do we need to wrap the trace table?
2717: li r15,32 ; Second line of entry
2718: bne+ ctenwrap ; We got a trace entry...
2719: lwz r17,LOW_ADDR(EXT(traceStart)-EXT(ExceptionVectorsStart))(br0) ; Wrap back to the top
2720:
2721: ctenwrap: stw r17,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) ; Set the next entry for the next guy
2722:
2723: dcbz 0,r20 ; Allocate cache for the entry
2724: dcbz r15,r20 ; Zap the second half
2725:
2726: ctegetTB: mftbu r16 ; Get the upper timebase
2727: mftb r17 ; Get the lower timebase
2728: mftbu r15 ; Get the upper one again
2729: cmplw r16,r15 ; Did the top tick?
2730: bne- ctegetTB ; Yeah, need to get it again...
2731:
2732: li r15,0x111 ; Get the special trace ID code
2733: stw r0,LTR_r0(r20) ; Save R0 (usually used as an ID number
2734: stw r16,LTR_timeHi(r20) ; Set the upper part of TB
2735: mflr r16 ; Get the return point
2736: stw r17,LTR_timeLo(r20) ; Set the lower part of TB
2737: sth r15,LTR_excpt(r20) ; Save the exception type
2738: stw r16,LTR_srr0(r20) ; Save the return point
2739: blr ; Leave...
2740: #endif
2741:
2742: /*
2743: * Start of the trace table
2744: */
2745:
2746: .align 12 /* Align to 4k boundary */
2747:
2748: traceTableBeg: /* Start of trace table */
2749: /* .fill 2048,4,0 Make an 8k trace table for now */
2750: .fill 13760,4,0 /* Make an .trace table for now */
2751: /* .fill 240000,4,0 Make an .trace table for now */
2752: traceTableEnd: /* End of trace table */
2753:
2754: .globl EXT(ExceptionVectorsEnd)
2755: EXT(ExceptionVectorsEnd): /* Used if relocating the exception vectors */
2756: #ifndef HACKALERTHACKALERT
2757: /*
2758: * This .long needs to be here because the linker gets confused and tries to
2759: * include the final label in a section in the next section if there is nothing
2760: * after it
2761: */
2762: .long 0 /* (HACK/HACK/HACK) */
2763: #endif
2764:
2765: .data
2766: .align ALIGN
2767: .globl EXT(exception_end)
2768: EXT(exception_end):
2769: .long EXT(ExceptionVectorsEnd) -EXT(ExceptionVectorsStart) /* phys fn */
2770:
2771:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.