]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/lowmem_vectors.s
54b63596f270782f7a93803e090e1bb8c981ddf3
[apple/xnu.git] / osfmk / ppc / lowmem_vectors.s
1 /*
2 * Copyright (c) 2000-2005 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 #include <assym.s>
27 #include <debug.h>
28 #include <db_machine_commands.h>
29
30 #include <mach_debug.h>
31 #include <ppc/asm.h>
32 #include <ppc/proc_reg.h>
33 #include <ppc/exception.h>
34 #include <ppc/Performance.h>
35 #include <ppc/savearea.h>
36 #include <mach/ppc/vm_param.h>
37
38 #define ESPDEBUG 0
39 #define INSTRUMENT 0
40
41 #define featAltivec 29
42 #define wasNapping 30
43
44 #define VECTOR_SEGMENT .section __VECTORS, __interrupts
45
46 VECTOR_SEGMENT
47
48 .globl EXT(lowGlo)
49 EXT(lowGlo):
50
51 .globl EXT(ExceptionVectorsStart)
52
53 EXT(ExceptionVectorsStart): /* Used if relocating the exception vectors */
54 baseR: /* Used so we have more readable code */
55
56 ;
57 ; Handle system reset.
58 ; We do not ever expect a hard reset so we do not actually check.
59 ; When we come here, we check for a RESET_HANDLER_START (which means we are
60 ; waking up from sleep), a RESET_HANDLER_BUPOR (which is using for bring up
61 ; when starting directly from a POR), and RESET_HANDLER_IGNORE (which means
62 ; ignore the interrupt).
63 ;
64 ; Some machines (so far, 32-bit guys) will always ignore a non-START interrupt.
65 ; The ones who do take it, check if the interrupt is too be ignored. This is
66 ; always the case until the previous reset is handled (i.e., we have exited
67 ; from the debugger).
68 ;
69 . = 0xf0
70 .globl EXT(ResetHandler)
71 EXT(ResetHandler):
72 .long 0x0
73 .long 0x0
74 .long 0x0
75
76 . = 0x100
77 .L_handler100:
78 mtsprg 2,r13 /* Save R13 */
79 mtsprg 3,r11 /* Save R11 */
80 lwz r13,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Get reset type
81 mfcr r11
82 cmpi cr0,r13,RESET_HANDLER_START
83 bne resetexc
84
85 li r11,RESET_HANDLER_NULL
86 stw r11,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Clear reset type
87
88 lwz r4,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_CALL)(br0)
89 lwz r3,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_ARG)(br0)
90 mtlr r4
91 blr
92
93 resetexc: cmplwi r13,RESET_HANDLER_BUPOR ; Special bring up POR sequence?
94 bne resetexc2 ; No...
95 lis r4,hi16(EXT(resetPOR)) ; Get POR code
96 ori r4,r4,lo16(EXT(resetPOR)) ; The rest
97 mtlr r4 ; Set it
98 blr ; Jump to it....
99
100 resetexc2: cmplwi cr1,r13,RESET_HANDLER_IGNORE ; Are we ignoring these? (Software debounce)
101
102 mfsprg r13,0 ; Get per_proc
103 lwz r13,pfAvailable(r13) ; Get the features
104 rlwinm. r13,r13,0,pf64Bitb,pf64Bitb ; Is this a 64-bit machine?
105 cror cr1_eq,cr0_eq,cr1_eq ; See if we want to take this
106 bne-- cr1,rxCont ; Yes, continue...
107 bne-- rxIg64 ; 64-bit path...
108
109 mtcr r11 ; Restore the CR
110 mfsprg r13,2 ; Restore R13
111 mfsprg r11,0 ; Get per_proc
112 lwz r11,pfAvailable(r11) ; Get the features
113 mtsprg 2,r11 ; Restore sprg2
114 mfsprg r11,3 ; Restore R11
115 rfi ; Return and ignore the reset
116
117 rxIg64: mtcr r11 ; Restore the CR
118 mfsprg r11,0 ; Get per_proc
119 mtspr hsprg0,r14 ; Save a register
120 ld r14,UAW(r11) ; Get the User Assist DoubleWord
121 mfsprg r13,2 ; Restore R13
122 lwz r11,pfAvailable(r11) ; Get the features
123 mtsprg 2,r11 ; Restore sprg2
124 mfsprg r11,3 ; Restore R11
125 mtsprg 3,r14 ; Set the UAW in sprg3
126 mfspr r14,hsprg0 ; Restore R14
127 rfid ; Return and ignore the reset
128
129 rxCont: mtcr r11
130 li r11,RESET_HANDLER_IGNORE ; Get set to ignore
131 stw r11,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Start ignoring these
132 mfsprg r13,1 /* Get the exception save area */
133 li r11,T_RESET /* Set 'rupt code */
134 b .L_exception_entry /* Join common... */
135
136 /*
137 * Machine check
138 */
139
140 . = 0x200
141 .L_handler200:
142 mtsprg 2,r13 ; Save R13
143 mtsprg 3,r11 ; Save R11
144
145 .globl EXT(extPatchMCK)
146 LEXT(extPatchMCK) ; This is patched to a nop for 64-bit
147 b h200aaa ; Skip 64-bit code...
148
149 ;
150 ; Fall through here for 970 MCKs.
151 ;
152
153 li r11,1 ; ?
154 sldi r11,r11,32+3 ; ?
155 mfspr r13,hid4 ; ?
156 or r11,r11,r13 ; ?
157 sync
158 mtspr hid4,r11 ; ?
159 isync
160 li r11,1 ; ?
161 sldi r11,r11,32+8 ; ?
162 andc r13,r13,r11 ; ?
163 lis r11,0xE000 ; Get the unlikeliest ESID possible
164 sync
165 mtspr hid4,r13 ; ?
166 isync ; ?
167
168 srdi r11,r11,1 ; ?
169 slbie r11 ; ?
170 sync
171 isync
172
173 li r11,T_MACHINE_CHECK ; Set rupt code
174 b .L_exception_entry ; Join common...
175
176 ;
177 ; Preliminary checking of other MCKs
178 ;
179
180 h200aaa: mfsrr1 r11 ; Get the SRR1
181 mfcr r13 ; Save the CR
182
183 rlwinm. r11,r11,0,dcmck,dcmck ; ?
184 beq+ notDCache ; ?
185
186 sync
187 mfspr r11,msscr0 ; ?
188 dssall ; ?
189 sync
190 isync
191
192 oris r11,r11,hi16(dl1hwfm) ; ?
193 mtspr msscr0,r11 ; ?
194
195 rstbsy: mfspr r11,msscr0 ; ?
196
197 rlwinm. r11,r11,0,dl1hwf,dl1hwf ; ?
198 bne rstbsy ; ?
199
200 sync ; ?
201
202 mfsprg r11,0 ; Get the per_proc
203 mtcrf 255,r13 ; Restore CRs
204 lwz r13,hwMachineChecks(r11) ; Get old count
205 addi r13,r13,1 ; Count this one
206 stw r13,hwMachineChecks(r11) ; Set new count
207 lwz r11,pfAvailable(r11) ; Get the feature flags
208 mfsprg r13,2 ; Restore R13
209 mtsprg 2,r11 ; Set the feature flags
210 mfsprg r11,3 ; Restore R11
211 rfi ; Return
212
213 notDCache: mtcrf 255,r13 ; Restore CRs
214 li r11,T_MACHINE_CHECK ; Set rupt code
215 b .L_exception_entry ; Join common...
216
217
218 /*
219 * Data access - page fault, invalid memory rights for operation
220 */
221
222 . = 0x300
223 .L_handler300:
224 mtsprg 2,r13 /* Save R13 */
225 mtsprg 3,r11 /* Save R11 */
226 li r11,T_DATA_ACCESS /* Set 'rupt code */
227 b .L_exception_entry /* Join common... */
228
229
230 /*
231 * Data segment
232 */
233
234 . = 0x380
235 .L_handler380:
236 mtsprg 2,r13 ; Save R13
237 mtsprg 3,r11 ; Save R11
238 li r11,T_DATA_SEGMENT ; Set rupt code
239 b .L_exception_entry ; Join common...
240
241 /*
242 * Instruction access - as for data access
243 */
244
245 . = 0x400
246 .L_handler400:
247 mtsprg 2,r13 ; Save R13
248 mtsprg 3,r11 ; Save R11
249 li r11,T_INSTRUCTION_ACCESS ; Set rupt code
250 b .L_exception_entry ; Join common...
251
252 /*
253 * Instruction segment
254 */
255
256 . = 0x480
257 .L_handler480:
258 mtsprg 2,r13 ; Save R13
259 mtsprg 3,r11 ; Save R11
260 li r11,T_INSTRUCTION_SEGMENT ; Set rupt code
261 b .L_exception_entry ; Join common...
262
263 /*
264 * External interrupt
265 */
266
267 . = 0x500
268 .L_handler500:
269 mtsprg 2,r13 ; Save R13
270 mtsprg 3,r11 ; Save R11
271 li r11,T_INTERRUPT ; Set rupt code
272 b .L_exception_entry ; Join common...
273
274 /*
275 * Alignment - many reasons
276 */
277
278 . = 0x600
279 .L_handler600:
280 mtsprg 2,r13 /* Save R13 */
281 mtsprg 3,r11 /* Save R11 */
282 li r11,T_ALIGNMENT|T_FAM /* Set 'rupt code */
283 b .L_exception_entry /* Join common... */
284
285 /*
286 * Program - floating point exception, illegal inst, priv inst, user trap
287 */
288
289 . = 0x700
290 .L_handler700:
291 mtsprg 2,r13 /* Save R13 */
292 mtsprg 3,r11 /* Save R11 */
293
294 #if 0
295 mfsrr1 r13 ; (BRINGUP)
296 mfcr r11 ; (BRINGUP)
297 rlwinm. r13,r13,0,12,12 ; (BRINGUP)
298 crmove cr1_eq,cr0_eq ; (BRINGUP)
299 mfsrr1 r13 ; (BRINGUP)
300 rlwinm. r13,r13,0,MSR_PR_BIT,MSR_PR_BIT ; (BRINGUP)
301 crorc cr0_eq,cr1_eq,cr0_eq ; (BRINGUP)
302 bf-- cr0_eq,. ; (BRINGUP)
303 mtcrf 255,r11 ; (BRINGUP)
304 #endif
305
306 li r11,T_PROGRAM|T_FAM /* Set 'rupt code */
307 b .L_exception_entry /* Join common... */
308
309 /*
310 * Floating point disabled
311 */
312
313 . = 0x800
314 .L_handler800:
315 mtsprg 2,r13 /* Save R13 */
316 mtsprg 3,r11 /* Save R11 */
317 li r11,T_FP_UNAVAILABLE /* Set 'rupt code */
318 b .L_exception_entry /* Join common... */
319
320
321 /*
322 * Decrementer - DEC register has passed zero.
323 */
324
325 . = 0x900
326 .L_handler900:
327 mtsprg 2,r13 /* Save R13 */
328 mtsprg 3,r11 /* Save R11 */
329 li r11,T_DECREMENTER /* Set 'rupt code */
330 b .L_exception_entry /* Join common... */
331
332 /*
333 * I/O controller interface error - MACH does not use this
334 */
335
336 . = 0xA00
337 .L_handlerA00:
338 mtsprg 2,r13 /* Save R13 */
339 mtsprg 3,r11 /* Save R11 */
340 li r11,T_IO_ERROR /* Set 'rupt code */
341 b .L_exception_entry /* Join common... */
342
343 /*
344 * Reserved
345 */
346
347 . = 0xB00
348 .L_handlerB00:
349 mtsprg 2,r13 /* Save R13 */
350 mtsprg 3,r11 /* Save R11 */
351 li r11,T_RESERVED /* Set 'rupt code */
352 b .L_exception_entry /* Join common... */
353
354
355 ; System Calls (sc instruction)
356 ;
357 ; The syscall number is in r0. All we do here is munge the number into an
358 ; 8-bit index into the "scTable", and dispatch on it to handle the Ultra
359 ; Fast Traps (UFTs.) The index is:
360 ;
361 ; 0x80 - set if syscall number is 0x80000000 (CutTrace)
362 ; 0x40 - set if syscall number is 0x00006004
363 ; 0x20 - set if upper 29 bits of syscall number are 0xFFFFFFF8
364 ; 0x10 - set if upper 29 bits of syscall number are 0x00007FF0
365 ; 0x0E - low three bits of syscall number
366 ; 0x01 - zero, as scTable is an array of shorts
367
368 . = 0xC00
369 .L_handlerC00:
370 mtsprg 3,r11 ; Save R11
371 mtsprg 2,r13 ; Save R13
372 rlwinm r11,r0,0,0xFFFFFFF8 ; mask off low 3 bits of syscall number
373 xori r13,r11,0x7FF0 ; start to check for the 0x7FFx traps
374 addi r11,r11,8 ; make a 0 iff this is a 0xFFFFFFF8 trap
375 cntlzw r13,r13 ; set bit 0x20 iff a 0x7FFx trap
376 cntlzw r11,r11 ; set bit 0x20 iff a 0xFFFFFFF8 trap
377 xoris r0,r0,0x8000 ; Flip bit to make 0 iff 0x80000000
378 rlwimi r11,r13,31,0x10 ; move 0x7FFx bit into position
379 cntlzw r13,r0 ; Set bit 0x20 iff 0x80000000
380 xoris r0,r0,0x8000 ; Flip bit to restore R0
381 rlwimi r11,r13,2,0x80 ; Set bit 0x80 iff CutTrace
382 xori r13,r0,0x6004 ; start to check for 0x6004
383 rlwimi r11,r0,1,0xE ; move in low 3 bits of syscall number
384 cntlzw r13,r13 ; set bit 0x20 iff 0x6004
385 rlwinm r11,r11,0,0,30 ; clear out bit 31
386 rlwimi r11,r13,1,0x40 ; move 0x6004 bit into position
387 lhz r11,lo16(scTable)(r11) ; get branch address from sc table
388 mfctr r13 ; save caller's ctr in r13
389 mtctr r11 ; set up branch to syscall handler
390 mfsprg r11,0 ; get per_proc, which most UFTs use
391 bctr ; dispatch (r11 in sprg3, r13 in sprg2, ctr in r13, per_proc in r11)
392
393 /*
394 * Trace - generated by single stepping
395 * performance monitor BE branch enable tracing/logging
396 * is also done here now. while this is permanently in the
397 * system the impact is completely unnoticable as this code is
398 * only executed when (a) a single step or branch exception is
399 * hit, (b) in the single step debugger case there is so much
400 * overhead already the few extra instructions for testing for BE
401 * are not even noticable, (c) the BE logging code is *only* run
402 * when it is enabled by the tool which will not happen during
403 * normal system usage
404 *
405 * Note that this trace is available only to user state so we do not
406 * need to set sprg2 before returning.
407 */
408
409 . = 0xD00
410 .L_handlerD00:
411 mtsprg 3,r11 ; Save R11
412 mfsprg r11,2 ; Get the feature flags
413 mtsprg 2,r13 ; Save R13
414 rlwinm r11,r11,pf64Bitb-4,4,4 ; Get the 64-bit flag
415 mfcr r13 ; Get the CR
416 mtcrf 0x40,r11 ; Set the CR
417 mfsrr1 r11 ; Get the old MSR
418 rlwinm. r11,r11,0,MSR_PR_BIT,MSR_PR_BIT ; Are we in supervisor state?
419
420 mfsprg r11,0 ; Get the per_proc
421 lhz r11,PP_CPU_FLAGS(r11) ; Get the flags
422 crmove cr1_eq,cr0_eq ; Remember if we are in supervisor state
423 rlwinm. r11,r11,0,traceBEb+16,traceBEb+16 ; Special trace enabled?
424 cror cr0_eq,cr0_eq,cr1_eq ; Is trace off or supervisor state?
425 bf-- cr0_eq,specbrtr ; No, we need to trace...
426
427 notspectr: mtcr r13 ; Restore CR
428 li r11,T_TRACE|T_FAM ; Set interrupt code
429 b .L_exception_entry ; Join common...
430
431 .align 5
432
433 ;
434 ; We are doing the special branch trace
435 ;
436
437 specbrtr: mfsprg r11,0 ; Get the per_proc area
438 bt++ 4,sbxx64a ; Jump if 64-bit...
439
440 stw r1,tempr0+4(r11) ; Save in a scratch area
441 stw r2,tempr1+4(r11) ; Save in a scratch area
442 stw r3,tempr2+4(r11) ; Save in a scratch area
443 b sbxx64b ; Skip...
444
445 sbxx64a: std r1,tempr0(r11) ; Save in a scratch area
446 std r2,tempr1(r11) ; Save in a scratch area
447 std r3,tempr2(r11) ; Save in a scratch area
448
449 sbxx64b: lis r2,hi16(EXT(pc_trace_buf)) ; Get the top of the buffer
450 lwz r3,spcTRp(r11) ; Pick up buffer position
451 ori r2,r2,lo16(EXT(pc_trace_buf)) ; Get the bottom of the buffer
452 cmplwi cr2,r3,4092 ; Set cr1_eq if we should take exception
453 mfsrr0 r1 ; Get the pc
454 stwx r1,r2,r3 ; Save it in the buffer
455 addi r3,r3,4 ; Point to the next slot
456 rlwinm r3,r3,0,20,31 ; Wrap the slot at one page
457 stw r3,spcTRp(r11) ; Save the new slot
458
459 bt++ 4,sbxx64c ; Jump if 64-bit...
460
461 lwz r1,tempr0+4(r11) ; Restore work register
462 lwz r2,tempr1+4(r11) ; Restore work register
463 lwz r3,tempr2+4(r11) ; Restore work register
464 beq cr2,notspectr ; Buffer filled, make a rupt...
465 mtcr r13 ; Restore CR
466 b uftRFI ; Go restore and leave...
467
468 sbxx64c: ld r1,tempr0(r11) ; Restore work register
469 ld r2,tempr1(r11) ; Restore work register
470 ld r3,tempr2(r11) ; Restore work register
471 beq cr2,notspectr ; Buffer filled, make a rupt...
472 mtcr r13 ; Restore CR
473 b uftRFI ; Go restore and leave...
474
475 /*
476 * Floating point assist
477 */
478
479 . = 0xE00
480 .L_handlerE00:
481 mtsprg 2,r13 /* Save R13 */
482 mtsprg 3,r11 /* Save R11 */
483 li r11,T_FP_ASSIST /* Set 'rupt code */
484 b .L_exception_entry /* Join common... */
485
486
487 /*
488 * Performance monitor interruption
489 */
490
491 . = 0xF00
492 PMIhandler:
493 mtsprg 2,r13 /* Save R13 */
494 mtsprg 3,r11 /* Save R11 */
495 li r11,T_PERF_MON /* Set 'rupt code */
496 b .L_exception_entry /* Join common... */
497
498
499 /*
500 * VMX exception
501 */
502
503 . = 0xF20
504 VMXhandler:
505 mtsprg 2,r13 /* Save R13 */
506 mtsprg 3,r11 /* Save R11 */
507 li r11,T_VMX /* Set 'rupt code */
508 b .L_exception_entry /* Join common... */
509
510
511
512 ;
513 ; Instruction translation miss exception - not supported
514 ;
515
516 . = 0x1000
517 .L_handler1000:
518 mtsprg 2,r13 ; Save R13
519 mtsprg 3,r11 ; Save R11
520 li r11,T_INVALID_EXCP0 ; Set rupt code
521 b .L_exception_entry ; Join common...
522
523
524
525 ;
526 ; Data load translation miss exception - not supported
527 ;
528
529 . = 0x1100
530 .L_handler1100:
531 mtsprg 2,r13 ; Save R13
532 mtsprg 3,r11 ; Save R11
533 li r11,T_INVALID_EXCP1 ; Set rupt code
534 b .L_exception_entry ; Join common...
535
536
537
538 ;
539 ; Data store translation miss exception - not supported
540 ;
541
542 . = 0x1200
543 .L_handler1200:
544 mtsprg 2,r13 ; Save R13
545 mtsprg 3,r11 ; Save R11
546 li r11,T_INVALID_EXCP2 ; Set rupt code
547 b .L_exception_entry ; Join common...
548
549
550 /*
551 * Instruction address breakpoint
552 */
553
554 . = 0x1300
555 .L_handler1300:
556 mtsprg 2,r13 /* Save R13 */
557 mtsprg 3,r11 /* Save R11 */
558 li r11,T_INSTRUCTION_BKPT /* Set 'rupt code */
559 b .L_exception_entry /* Join common... */
560
561 /*
562 * System management interrupt
563 */
564
565 . = 0x1400
566 .L_handler1400:
567 mtsprg 2,r13 /* Save R13 */
568 mtsprg 3,r11 /* Save R11 */
569 li r11,T_SYSTEM_MANAGEMENT /* Set 'rupt code */
570 b .L_exception_entry /* Join common... */
571
572
573 /*
574 * Soft Patch
575 */
576
577 . = 0x1500
578 .L_handler1500:
579 mtsprg 2,r13 /* Save R13 */
580 mtsprg 3,r11 /* Save R11 */
581 li r11,T_SOFT_PATCH /* Set 'rupt code */
582 b .L_exception_entry /* Join common... */
583
584 ;
585 ; Altivec Java Mode Assist interrupt or Maintenace interrupt
586 ;
587
588 . = 0x1600
589 .L_handler1600:
590 mtsprg 2,r13 /* Save R13 */
591 mtsprg 3,r11 /* Save R11 */
592 li r11,T_ALTIVEC_ASSIST /* Set 'rupt code */
593 b .L_exception_entry /* Join common... */
594
595 ;
596 ; Altivec Java Mode Assist interrupt or Thermal interruption
597 ;
598
599 . = 0x1700
600 .L_handler1700:
601 mtsprg 2,r13 /* Save R13 */
602 mtsprg 3,r11 /* Save R11 */
603 li r11,T_THERMAL /* Set 'rupt code */
604 b .L_exception_entry /* Join common... */
605
606 ;
607 ; Thermal interruption - 64-bit
608 ;
609
610 . = 0x1800
611 .L_handler1800:
612 mtsprg 2,r13 /* Save R13 */
613 mtsprg 3,r11 /* Save R11 */
614 li r11,T_ARCHDEP0 /* Set 'rupt code */
615 b .L_exception_entry /* Join common... */
616
617 /*
618 * There is now a large gap of reserved traps
619 */
620
621 /*
622 * Instrumentation interruption
623 */
624
625 . = 0x2000
626 .L_handler2000:
627 mtsprg 2,r13 /* Save R13 */
628 mtsprg 3,r11 /* Save R11 */
629 li r11,T_INSTRUMENTATION /* Set 'rupt code */
630 b .L_exception_entry /* Join common... */
631
632
633
634 .data
635 .align ALIGN
636 .globl EXT(exception_entry)
637 EXT(exception_entry):
638 .long .L_exception_entry-EXT(ExceptionVectorsStart) /* phys addr of fn */
639
640 VECTOR_SEGMENT
641
642 /*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
643 *
644 * First-level syscall dispatch. The syscall vector maps r0 (the syscall number) into an
645 * index into the "scTable" (below), and then branches to one of these routines. The PPC
646 * syscalls come in several varieties, as follows:
647 *
648 * 1. If (syscall & 0xFFFFF000) == 0x00007000, then it is a PPC Fast Trap or UFT.
649 * The UFTs are dispatched here, the Fast Traps are dispatched in hw_exceptions.s.
650 *
651 * 2. If (syscall & 0xFFFFF000) == 0x00006000, then it is a PPC-only trap.
652 * One of these (0x6004) is a UFT, but most are dispatched in hw_exceptions.s. These
653 * are mostly Blue Box or VMM (Virtual Machine) calls.
654 *
655 * 3. If (syscall & 0xFFFFFFF0) == 0xFFFFFFF0, then it is also a UFT and is dispatched here.
656 *
657 * 4. If (syscall & 0xFFFFF000) == 0x80000000, then it is a "firmware" call and is dispatched in
658 * Firmware.s, though the special "Cut Trace" trap (0x80000000) is handled here as an ultra
659 * fast trap.
660 *
661 * 5. If (syscall & 0xFFFFF000) == 0xFFFFF000, and it is not one of the above, then it is a Mach
662 * syscall, which are dispatched in hw_exceptions.s via "mach_trap_table".
663 *
664 * 6. If (syscall & 0xFFFFF000) == 0x00000000, then it is a BSD syscall, which are dispatched
665 * by "unix_syscall" using the "sysent" table.
666 *
667 * What distinguishes the UFTs, aside from being ultra fast, is that they cannot rely on translation
668 * being on, and so cannot look at the activation or task control block, etc. We handle them right
669 * here, and return to the caller without turning interrupts or translation on. The UFTs are:
670 *
671 * 0xFFFFFFFF - BlueBox only - MKIsPreemptiveTask
672 * 0xFFFFFFFE - BlueBox only - MKIsPreemptiveTaskEnv
673 * 0x00007FF2 - User state only - thread info (32-bit mode)
674 * 0x00007FF3 - User state only - floating point / vector facility status
675 * 0x00007FF4 - Kernel only - loadMSR - not used on 64-bit machines
676 * 0x00006004 - vmm_dispatch (only some of which are UFTs)
677 *
678 * "scTable" is an array of 2-byte addresses, accessed using a 7-bit index derived from the syscall
679 * number as follows:
680 *
681 * 0x80 (A) - set if syscall number is 0x80000000
682 * 0x40 (B) - set if syscall number is 0x00006004
683 * 0x20 (C) - set if upper 29 bits of syscall number are 0xFFFFFFF8
684 * 0x10 (D) - set if upper 29 bits of syscall number are 0x00007FF0
685 * 0x0E (E) - low three bits of syscall number
686 *
687 * If you define another UFT, try to use a number in one of the currently decoded ranges, ie one marked
688 * "unassigned" below. The dispatch table and the UFT handlers must reside in the first 32KB of
689 * physical memory.
690 */
691
692 .align 8 ; start this table on a 256-byte boundry
693 scTable: ; ABCD E
694 .short uftNormalSyscall-baseR ; 0000 0 these syscalls are not in a reserved range
695 .short uftNormalSyscall-baseR ; 0000 1 these syscalls are not in a reserved range
696 .short uftNormalSyscall-baseR ; 0000 2 these syscalls are not in a reserved range
697 .short uftNormalSyscall-baseR ; 0000 3 these syscalls are not in a reserved range
698 .short uftNormalSyscall-baseR ; 0000 4 these syscalls are not in a reserved range
699 .short uftNormalSyscall-baseR ; 0000 5 these syscalls are not in a reserved range
700 .short uftNormalSyscall-baseR ; 0000 6 these syscalls are not in a reserved range
701 .short uftNormalSyscall-baseR ; 0000 7 these syscalls are not in a reserved range
702
703 .short uftNormalSyscall-baseR ; 0001 0 0x7FF0 is unassigned
704 .short uftNormalSyscall-baseR ; 0001 1 0x7FF1 is Set Thread Info Fast Trap (pass up)
705 .short uftThreadInfo-baseR ; 0001 2 0x7FF2 is Thread Info
706 .short uftFacilityStatus-baseR ; 0001 3 0x7FF3 is Facility Status
707 .short uftLoadMSR-baseR ; 0001 4 0x7FF4 is Load MSR
708 .short uftNormalSyscall-baseR ; 0001 5 0x7FF5 is the Null FastPath Trap (pass up)
709 .short uftNormalSyscall-baseR ; 0001 6 0x7FF6 is unassigned
710 .short uftNormalSyscall-baseR ; 0001 7 0x7FF7 is unassigned
711
712 .short uftNormalSyscall-baseR ; 0010 0 0xFFFFFFF0 is unassigned
713 .short uftNormalSyscall-baseR ; 0010 1 0xFFFFFFF1 is unassigned
714 .short uftNormalSyscall-baseR ; 0010 2 0xFFFFFFF2 is unassigned
715 .short uftNormalSyscall-baseR ; 0010 3 0xFFFFFFF3 is unassigned
716 .short uftNormalSyscall-baseR ; 0010 4 0xFFFFFFF4 is unassigned
717 .short uftNormalSyscall-baseR ; 0010 5 0xFFFFFFF5 is unassigned
718 .short uftIsPreemptiveTaskEnv-baseR ; 0010 6 0xFFFFFFFE is Blue Box uftIsPreemptiveTaskEnv
719 .short uftIsPreemptiveTask-baseR ; 0010 7 0xFFFFFFFF is Blue Box IsPreemptiveTask
720
721 .short WhoaBaby-baseR ; 0011 0 impossible combination
722 .short WhoaBaby-baseR ; 0011 1 impossible combination
723 .short WhoaBaby-baseR ; 0011 2 impossible combination
724 .short WhoaBaby-baseR ; 0011 3 impossible combination
725 .short WhoaBaby-baseR ; 0011 4 impossible combination
726 .short WhoaBaby-baseR ; 0011 5 impossible combination
727 .short WhoaBaby-baseR ; 0011 6 impossible combination
728 .short WhoaBaby-baseR ; 0011 7 impossible combination
729
730 .short WhoaBaby-baseR ; 0100 0 0x6000 is an impossible index (diagCall)
731 .short WhoaBaby-baseR ; 0100 1 0x6001 is an impossible index (vmm_get_version)
732 .short WhoaBaby-baseR ; 0100 2 0x6002 is an impossible index (vmm_get_features)
733 .short WhoaBaby-baseR ; 0100 3 0x6003 is an impossible index (vmm_init_context)
734 .short uftVMM-baseR ; 0100 4 0x6004 is vmm_dispatch (only some of which are UFTs)
735 .short WhoaBaby-baseR ; 0100 5 0x6005 is an impossible index (bb_enable_bluebox)
736 .short WhoaBaby-baseR ; 0100 6 0x6006 is an impossible index (bb_disable_bluebox)
737 .short WhoaBaby-baseR ; 0100 7 0x6007 is an impossible index (bb_settaskenv)
738
739 .short uftNormalSyscall-baseR ; 0101 0 these syscalls are not in a reserved range
740 .short uftNormalSyscall-baseR ; 0101 1 these syscalls are not in a reserved range
741 .short uftNormalSyscall-baseR ; 0101 2 these syscalls are not in a reserved range
742 .short uftNormalSyscall-baseR ; 0101 3 these syscalls are not in a reserved range
743 .short uftNormalSyscall-baseR ; 0101 4 these syscalls are not in a reserved range
744 .short uftNormalSyscall-baseR ; 0101 5 these syscalls are not in a reserved range
745 .short uftNormalSyscall-baseR ; 0101 6 these syscalls are not in a reserved range
746 .short uftNormalSyscall-baseR ; 0101 7 these syscalls are not in a reserved range
747
748 .short uftNormalSyscall-baseR ; 0110 0 these syscalls are not in a reserved range
749 .short uftNormalSyscall-baseR ; 0110 1 these syscalls are not in a reserved range
750 .short uftNormalSyscall-baseR ; 0110 2 these syscalls are not in a reserved range
751 .short uftNormalSyscall-baseR ; 0110 3 these syscalls are not in a reserved range
752 .short uftNormalSyscall-baseR ; 0110 4 these syscalls are not in a reserved range
753 .short uftNormalSyscall-baseR ; 0110 5 these syscalls are not in a reserved range
754 .short uftNormalSyscall-baseR ; 0110 6 these syscalls are not in a reserved range
755 .short uftNormalSyscall-baseR ; 0110 7 these syscalls are not in a reserved range
756
757 .short uftNormalSyscall-baseR ; 0111 0 these syscalls are not in a reserved range
758 .short uftNormalSyscall-baseR ; 0111 1 these syscalls are not in a reserved range
759 .short uftNormalSyscall-baseR ; 0111 2 these syscalls are not in a reserved range
760 .short uftNormalSyscall-baseR ; 0111 3 these syscalls are not in a reserved range
761 .short uftNormalSyscall-baseR ; 0111 4 these syscalls are not in a reserved range
762 .short uftNormalSyscall-baseR ; 0111 5 these syscalls are not in a reserved range
763 .short uftNormalSyscall-baseR ; 0111 6 these syscalls are not in a reserved range
764 .short uftNormalSyscall-baseR ; 0111 7 these syscalls are not in a reserved range
765
766 .short uftCutTrace-baseR ; 1000 0 CutTrace
767 .short uftNormalSyscall-baseR ; 1000 1 these syscalls are not in a reserved range
768 .short uftNormalSyscall-baseR ; 1000 2 these syscalls are not in a reserved range
769 .short uftNormalSyscall-baseR ; 1000 3 these syscalls are not in a reserved range
770 .short uftNormalSyscall-baseR ; 1000 4 these syscalls are not in a reserved range
771 .short uftNormalSyscall-baseR ; 1000 5 these syscalls are not in a reserved range
772 .short uftNormalSyscall-baseR ; 1000 6 these syscalls are not in a reserved range
773 .short uftNormalSyscall-baseR ; 1000 7 these syscalls are not in a reserved range
774
775 .short uftNormalSyscall-baseR ; 1001 0 these syscalls are not in a reserved range
776 .short uftNormalSyscall-baseR ; 1001 1 these syscalls are not in a reserved range
777 .short uftNormalSyscall-baseR ; 1001 2 these syscalls are not in a reserved range
778 .short uftNormalSyscall-baseR ; 1001 3 these syscalls are not in a reserved range
779 .short uftNormalSyscall-baseR ; 1001 4 these syscalls are not in a reserved range
780 .short uftNormalSyscall-baseR ; 1001 5 these syscalls are not in a reserved range
781 .short uftNormalSyscall-baseR ; 1001 6 these syscalls are not in a reserved range
782 .short uftNormalSyscall-baseR ; 1001 7 these syscalls are not in a reserved range
783
784 .short uftNormalSyscall-baseR ; 1010 0 these syscalls are not in a reserved range
785 .short uftNormalSyscall-baseR ; 1010 1 these syscalls are not in a reserved range
786 .short uftNormalSyscall-baseR ; 1010 2 these syscalls are not in a reserved range
787 .short uftNormalSyscall-baseR ; 1010 3 these syscalls are not in a reserved range
788 .short uftNormalSyscall-baseR ; 1010 4 these syscalls are not in a reserved range
789 .short uftNormalSyscall-baseR ; 1010 5 these syscalls are not in a reserved range
790 .short uftNormalSyscall-baseR ; 1010 6 these syscalls are not in a reserved range
791 .short uftNormalSyscall-baseR ; 1010 7 these syscalls are not in a reserved range
792
793 .short uftNormalSyscall-baseR ; 1011 0 these syscalls are not in a reserved range
794 .short uftNormalSyscall-baseR ; 1011 1 these syscalls are not in a reserved range
795 .short uftNormalSyscall-baseR ; 1011 2 these syscalls are not in a reserved range
796 .short uftNormalSyscall-baseR ; 1011 3 these syscalls are not in a reserved range
797 .short uftNormalSyscall-baseR ; 1011 4 these syscalls are not in a reserved range
798 .short uftNormalSyscall-baseR ; 1011 5 these syscalls are not in a reserved range
799 .short uftNormalSyscall-baseR ; 1011 6 these syscalls are not in a reserved range
800 .short uftNormalSyscall-baseR ; 1011 7 these syscalls are not in a reserved range
801
802 .short uftNormalSyscall-baseR ; 1100 0 these syscalls are not in a reserved range
803 .short uftNormalSyscall-baseR ; 1100 1 these syscalls are not in a reserved range
804 .short uftNormalSyscall-baseR ; 1100 2 these syscalls are not in a reserved range
805 .short uftNormalSyscall-baseR ; 1100 3 these syscalls are not in a reserved range
806 .short uftNormalSyscall-baseR ; 1100 4 these syscalls are not in a reserved range
807 .short uftNormalSyscall-baseR ; 1100 5 these syscalls are not in a reserved range
808 .short uftNormalSyscall-baseR ; 1100 6 these syscalls are not in a reserved range
809 .short uftNormalSyscall-baseR ; 1100 7 these syscalls are not in a reserved range
810
811 .short uftNormalSyscall-baseR ; 1101 0 these syscalls are not in a reserved range
812 .short uftNormalSyscall-baseR ; 1101 1 these syscalls are not in a reserved range
813 .short uftNormalSyscall-baseR ; 1101 2 these syscalls are not in a reserved range
814 .short uftNormalSyscall-baseR ; 1101 3 these syscalls are not in a reserved range
815 .short uftNormalSyscall-baseR ; 1101 4 these syscalls are not in a reserved range
816 .short uftNormalSyscall-baseR ; 1101 5 these syscalls are not in a reserved range
817 .short uftNormalSyscall-baseR ; 1101 6 these syscalls are not in a reserved range
818 .short uftNormalSyscall-baseR ; 1101 7 these syscalls are not in a reserved range
819
820 .short uftNormalSyscall-baseR ; 1110 0 these syscalls are not in a reserved range
821 .short uftNormalSyscall-baseR ; 1110 1 these syscalls are not in a reserved range
822 .short uftNormalSyscall-baseR ; 1110 2 these syscalls are not in a reserved range
823 .short uftNormalSyscall-baseR ; 1110 3 these syscalls are not in a reserved range
824 .short uftNormalSyscall-baseR ; 1110 4 these syscalls are not in a reserved range
825 .short uftNormalSyscall-baseR ; 1110 5 these syscalls are not in a reserved range
826 .short uftNormalSyscall-baseR ; 1110 6 these syscalls are not in a reserved range
827 .short uftNormalSyscall-baseR ; 1110 7 these syscalls are not in a reserved range
828
829 .short uftNormalSyscall-baseR ; 1111 0 these syscalls are not in a reserved range
830 .short uftNormalSyscall-baseR ; 1111 1 these syscalls are not in a reserved range
831 .short uftNormalSyscall-baseR ; 1111 2 these syscalls are not in a reserved range
832 .short uftNormalSyscall-baseR ; 1111 3 these syscalls are not in a reserved range
833 .short uftNormalSyscall-baseR ; 1111 4 these syscalls are not in a reserved range
834 .short uftNormalSyscall-baseR ; 1111 5 these syscalls are not in a reserved range
835 .short uftNormalSyscall-baseR ; 1111 6 these syscalls are not in a reserved range
836 .short uftNormalSyscall-baseR ; 1111 7 these syscalls are not in a reserved range
837
838 .align 2 ; prepare for code
839
840
841 /* Ultra Fast Trap (UFT) Handlers:
842 *
843 * We get here directly from the hw syscall vector via the "scTable" vector (above),
844 * with interrupts and VM off, in 64-bit mode if supported, and with all registers live
845 * except the following:
846 *
847 * r11 = per_proc ptr (ie, sprg0)
848 * r13 = holds caller's ctr register
849 * sprg2 = holds caller's r13
850 * sprg3 = holds caller's r11
851 */
852
853 ; Handle "vmm_dispatch" (0x6004), of which only some selectors are UFTs.
854
855 uftVMM:
856 mtctr r13 ; restore caller's ctr
857 lwz r11,spcFlags(r11) ; get the special flags word from per_proc
858 mfcr r13 ; save caller's entire cr (we use all fields below)
859 rlwinm r11,r11,16,16,31 ; Extract spcFlags upper bits
860 andi. r11,r11,hi16(runningVM|FamVMena|FamVMmode)
861 cmpwi cr0,r11,hi16(runningVM|FamVMena|FamVMmode) ; Test in VM FAM
862 bne-- uftNormal80 ; not eligible for FAM UFTs
863 cmpwi cr5,r3,kvmmResumeGuest ; Compare r3 with kvmmResumeGuest
864 cmpwi cr2,r3,kvmmSetGuestRegister ; Compare r3 with kvmmSetGuestRegister
865 cror cr1_eq,cr5_lt,cr2_gt ; Set true if out of VMM Fast syscall range
866 bt-- cr1_eq,uftNormalFF ; Exit if out of range (the others are not UFTs)
867 b EXT(vmm_ufp) ; handle UFT range of vmm_dispatch syscall
868
869
870 ; Handle blue box UFTs (syscalls -1 and -2).
871
872 uftIsPreemptiveTask:
873 uftIsPreemptiveTaskEnv:
874 mtctr r13 ; restore caller's ctr
875 lwz r11,spcFlags(r11) ; get the special flags word from per_proc
876 mfcr r13,0x80 ; save caller's cr0 so we can use it
877 andi. r11,r11,bbNoMachSC|bbPreemptive ; Clear what we do not need
878 cmplwi r11,bbNoMachSC ; See if we are trapping syscalls
879 blt-- uftNormal80 ; No...
880 cmpwi r0,-2 ; is this call IsPreemptiveTaskEnv?
881 rlwimi r13,r11,bbPreemptivebit-cr0_eq,cr0_eq,cr0_eq ; Copy preemptive task flag into user cr0_eq
882 mfsprg r11,0 ; Get the per proc once more
883 bne++ uftRestoreThenRFI ; do not load r0 if IsPreemptiveTask
884 lwz r0,ppbbTaskEnv(r11) ; Get the shadowed taskEnv (only difference)
885 b uftRestoreThenRFI ; restore modified cr0 and return
886
887
888 ; Handle "Thread Info" UFT (0x7FF2)
889
890 .globl EXT(uft_uaw_nop_if_32bit)
891 uftThreadInfo:
892 lwz r3,UAW+4(r11) ; get user assist word, assuming a 32-bit processor
893 LEXT(uft_uaw_nop_if_32bit)
894 ld r3,UAW(r11) ; get the whole doubleword if 64-bit (patched to nop if 32-bit)
895 mtctr r13 ; restore caller's ctr
896 b uftRFI ; done
897
898
899 ; Handle "Facility Status" UFT (0x7FF3)
900
901 uftFacilityStatus:
902 lwz r3,spcFlags(r11) ; get "special flags" word from per_proc
903 mtctr r13 ; restore caller's ctr
904 b uftRFI ; done
905
906
907 ; Handle "Load MSR" UFT (0x7FF4). This is not used on 64-bit processors, though it would work.
908
909 uftLoadMSR:
910 mfsrr1 r11 ; get caller's MSR
911 mtctr r13 ; restore caller's ctr
912 mfcr r13,0x80 ; save caller's cr0 so we can test PR
913 rlwinm. r11,r11,0,MSR_PR_BIT,MSR_PR_BIT ; really in the kernel?
914 bne- uftNormal80 ; do not permit from user mode
915 mfsprg r11,0 ; restore per_proc
916 mtsrr1 r3 ; Set new MSR
917
918
919 ; Return to caller after UFT. When called:
920 ; r11 = per_proc ptr
921 ; r13 = callers cr0 in upper nibble (if uftRestoreThenRFI called)
922 ; sprg2 = callers r13
923 ; sprg3 = callers r11
924
925 uftRestoreThenRFI: ; WARNING: can drop down to here
926 mtcrf 0x80,r13 ; restore caller's cr0
927 uftRFI:
928 .globl EXT(uft_nop_if_32bit)
929 LEXT(uft_nop_if_32bit)
930 b uftX64 ; patched to NOP if 32-bit processor
931
932 uftX32: lwz r11,pfAvailable(r11) ; Get the feature flags
933 mfsprg r13,2 ; Restore R13
934 mtsprg 2,r11 ; Set the feature flags
935 mfsprg r11,3 ; Restore R11
936 rfi ; Back to our guy...
937
938 uftX64: mtspr hsprg0,r14 ; Save a register in a Hypervisor SPRG
939 ld r14,UAW(r11) ; Get the User Assist DoubleWord
940 lwz r11,pfAvailable(r11) ; Get the feature flags
941 mfsprg r13,2 ; Restore R13
942 mtsprg 2,r11 ; Set the feature flags
943 mfsprg r11,3 ; Restore R11
944 mtsprg 3,r14 ; Set the UAW in sprg3
945 mfspr r14,hsprg0 ; Restore R14
946 rfid ; Back to our guy...
947
948 ;
949 ; Quickly cut a trace table entry for the CutTrace firmware call.
950 ;
951 ; All registers except R11 and R13 are unchanged.
952 ;
953 ; Note that this code cuts a trace table entry for the CutTrace call only.
954 ; An identical entry is made during normal interrupt processing. Any entry
955 ; format entry changes made must be done in both places.
956 ;
957
958 .align 5
959
960 .globl EXT(uft_cuttrace)
961 LEXT(uft_cuttrace)
962 uftCutTrace:
963 b uftct64 ; patched to NOP if 32-bit processor
964
965 stw r20,tempr0(r11) ; Save some work registers
966 lwz r20,dgFlags(0) ; Get the flags
967 stw r21,tempr1(r11) ; Save some work registers
968 mfsrr1 r21 ; Get the SRR1
969 rlwinm r20,r20,MSR_PR_BIT-enaUsrFCallb,MASK(MSR_PR) ; Shift the validity bit over to pr bit spot
970 stw r25,tempr2(r11) ; Save some work registers
971 orc r20,r20,r21 ; Get ~PR | FC
972 mfcr r25 ; Save the CR
973 stw r22,tempr3(r11) ; Save some work registers
974 lhz r22,PP_CPU_NUMBER(r11) ; Get the logical processor number
975 andi. r20,r20,MASK(MSR_PR) ; Set cr0_eq is we are in problem state and the validity bit is not set
976 stw r23,tempr4(r11) ; Save some work registers
977 lwz r23,traceMask(0) ; Get the trace mask
978 stw r24,tempr5(r11) ; Save some work registers
979 beq- ctbail32 ; Can not issue from user...
980
981
982 addi r24,r22,16 ; Get shift to move cpu mask to syscall mask
983 rlwnm r24,r23,r24,12,12 ; Shift cpu mask bit to rupt type mask
984 and. r24,r24,r23 ; See if both are on
985
986 ;
987 ; We select a trace entry using a compare and swap on the next entry field.
988 ; Since we do not lock the actual trace buffer, there is a potential that
989 ; another processor could wrap an trash our entry. Who cares?
990 ;
991
992 li r23,trcWork ; Get the trace work area address
993 lwz r21,traceStart(0) ; Get the start of trace table
994 lwz r22,traceEnd(0) ; Get end of trace table
995
996 beq-- ctdisa32 ; Leave because tracing is disabled...
997
998 ctgte32: lwarx r20,0,r23 ; Get and reserve the next slot to allocate
999 addi r24,r20,LTR_size ; Point to the next trace entry
1000 cmplw r24,r22 ; Do we need to wrap the trace table?
1001 bne+ ctgte32s ; No wrap, we got us a trace entry...
1002
1003 mr r24,r21 ; Wrap back to start
1004
1005 ctgte32s: stwcx. r24,0,r23 ; Try to update the current pointer
1006 bne- ctgte32 ; Collision, try again...
1007
1008 #if ESPDEBUG
1009 dcbf 0,r23 ; Force to memory
1010 sync
1011 #endif
1012
1013 dcbz 0,r20 ; Clear and allocate first trace line
1014 li r24,32 ; Offset to next line
1015
1016 ctgte32tb: mftbu r21 ; Get the upper time now
1017 mftb r22 ; Get the lower time now
1018 mftbu r23 ; Get upper again
1019 cmplw r21,r23 ; Has it ticked?
1020 bne- ctgte32tb ; Yes, start again...
1021
1022 dcbz r24,r20 ; Clean second line
1023
1024 ;
1025 ; Let us cut that trace entry now.
1026 ;
1027 ; Note that this code cuts a trace table entry for the CutTrace call only.
1028 ; An identical entry is made during normal interrupt processing. Any entry
1029 ; format entry changes made must be done in both places.
1030 ;
1031
1032 lhz r24,PP_CPU_NUMBER(r11) ; Get the logical processor number
1033 li r23,T_SYSTEM_CALL ; Get the system call id
1034 mtctr r13 ; Restore the caller's CTR
1035 sth r24,LTR_cpu(r20) ; Save processor number
1036 li r24,64 ; Offset to third line
1037 sth r23,LTR_excpt(r20) ; Set the exception code
1038 dcbz r24,r20 ; Clean 3rd line
1039 mfspr r23,dsisr ; Get the DSISR
1040 stw r21,LTR_timeHi(r20) ; Save top of time stamp
1041 li r24,96 ; Offset to fourth line
1042 mflr r21 ; Get the LR
1043 dcbz r24,r20 ; Clean 4th line
1044 stw r22,LTR_timeLo(r20) ; Save bottom of time stamp
1045 mfsrr0 r22 ; Get SRR0
1046 stw r25,LTR_cr(r20) ; Save CR
1047 mfsrr1 r24 ; Get the SRR1
1048 stw r23,LTR_dsisr(r20) ; Save DSISR
1049 stw r22,LTR_srr0+4(r20) ; Save SRR0
1050 mfdar r23 ; Get DAR
1051 stw r24,LTR_srr1+4(r20) ; Save SRR1
1052 stw r23,LTR_dar+4(r20) ; Save DAR
1053 stw r21,LTR_lr+4(r20) ; Save LR
1054
1055 stw r13,LTR_ctr+4(r20) ; Save CTR
1056 stw r0,LTR_r0+4(r20) ; Save register
1057 stw r1,LTR_r1+4(r20) ; Save register
1058 stw r2,LTR_r2+4(r20) ; Save register
1059 stw r3,LTR_r3+4(r20) ; Save register
1060 stw r4,LTR_r4+4(r20) ; Save register
1061 stw r5,LTR_r5+4(r20) ; Save register
1062 stw r6,LTR_r6+4(r20) ; Save register
1063
1064 #if 0
1065 lwz r21,FPUowner(r11) ; (TEST/DEBUG) Get the current floating point owner
1066 stw r21,LTR_rsvd0(r20) ; (TEST/DEBUG) Record the owner
1067 #endif
1068
1069 #if ESPDEBUG
1070 addi r21,r20,32 ; Second line
1071 addi r22,r20,64 ; Third line
1072 dcbst 0,r20 ; Force to memory
1073 dcbst 0,r21 ; Force to memory
1074 addi r21,r22,32 ; Fourth line
1075 dcbst 0,r22 ; Force to memory
1076 dcbst 0,r21 ; Force to memory
1077 sync ; Make sure it all goes
1078 #endif
1079
1080 ctdisa32: mtcrf 0x80,r25 ; Restore the used condition register field
1081 lwz r20,tempr0(r11) ; Restore work register
1082 lwz r21,tempr1(r11) ; Restore work register
1083 lwz r25,tempr2(r11) ; Restore work register
1084 mtctr r13 ; Restore the caller's CTR
1085 lwz r22,tempr3(r11) ; Restore work register
1086 lwz r23,tempr4(r11) ; Restore work register
1087 lwz r24,tempr5(r11) ; Restore work register
1088 b uftX32 ; Go restore the rest and go...
1089
1090 ctbail32: mtcrf 0x80,r25 ; Restore the used condition register field
1091 lwz r20,tempr0(r11) ; Restore work register
1092 lwz r21,tempr1(r11) ; Restore work register
1093 lwz r25,tempr2(r11) ; Restore work register
1094 mtctr r13 ; Restore the caller's CTR
1095 lwz r22,tempr3(r11) ; Restore work register
1096 lwz r23,tempr4(r11) ; Restore work register
1097 b uftNormalSyscall ; Go pass it on along...
1098
1099 ;
1100 ; This is the 64-bit version.
1101 ;
1102
1103 uftct64: std r20,tempr0(r11) ; Save some work registers
1104 lwz r20,dgFlags(0) ; Get the flags
1105 std r21,tempr1(r11) ; Save some work registers
1106 mfsrr1 r21 ; Get the SRR1
1107 rlwinm r20,r20,MSR_PR_BIT-enaUsrFCallb,MASK(MSR_PR) ; Shift the validity bit over to pr bit spot
1108 std r25,tempr2(r11) ; Save some work registers
1109 orc r20,r20,r21 ; Get ~PR | FC
1110 mfcr r25 ; Save the CR
1111 std r22,tempr3(r11) ; Save some work registers
1112 lhz r22,PP_CPU_NUMBER(r11) ; Get the logical processor number
1113 andi. r20,r20,MASK(MSR_PR) ; Set cr0_eq when we are in problem state and the validity bit is not set
1114 std r23,tempr4(r11) ; Save some work registers
1115 lwz r23,traceMask(0) ; Get the trace mask
1116 std r24,tempr5(r11) ; Save some work registers
1117 beq-- ctbail64 ; Can not issue from user...
1118
1119 addi r24,r22,16 ; Get shift to move cpu mask to syscall mask
1120 rlwnm r24,r23,r24,12,12 ; Shift cpu mask bit to rupt type mask
1121 and. r24,r24,r23 ; See if both are on
1122
1123 ;
1124 ; We select a trace entry using a compare and swap on the next entry field.
1125 ; Since we do not lock the actual trace buffer, there is a potential that
1126 ; another processor could wrap an trash our entry. Who cares?
1127 ;
1128
1129 li r23,trcWork ; Get the trace work area address
1130 lwz r21,traceStart(0) ; Get the start of trace table
1131 lwz r22,traceEnd(0) ; Get end of trace table
1132
1133 beq-- ctdisa64 ; Leave because tracing is disabled...
1134
1135 ctgte64: lwarx r20,0,r23 ; Get and reserve the next slot to allocate
1136 addi r24,r20,LTR_size ; Point to the next trace entry
1137 cmplw r24,r22 ; Do we need to wrap the trace table?
1138 bne++ ctgte64s ; No wrap, we got us a trace entry...
1139
1140 mr r24,r21 ; Wrap back to start
1141
1142 ctgte64s: stwcx. r24,0,r23 ; Try to update the current pointer
1143 bne-- ctgte64 ; Collision, try again...
1144
1145 #if ESPDEBUG
1146 dcbf 0,r23 ; Force to memory
1147 sync
1148 #endif
1149
1150 dcbz128 0,r20 ; Zap the trace entry
1151
1152 mftb r21 ; Get the time
1153
1154 ;
1155 ; Let us cut that trace entry now.
1156 ;
1157 ; Note that this code cuts a trace table entry for the CutTrace call only.
1158 ; An identical entry is made during normal interrupt processing. Any entry
1159 ; format entry changes made must be done in both places.
1160 ;
1161
1162 lhz r24,PP_CPU_NUMBER(r11) ; Get the logical processor number
1163 li r23,T_SYSTEM_CALL ; Get the system call id
1164 sth r24,LTR_cpu(r20) ; Save processor number
1165 sth r23,LTR_excpt(r20) ; Set the exception code
1166 mfspr r23,dsisr ; Get the DSISR
1167 std r21,LTR_timeHi(r20) ; Save top of time stamp
1168 mflr r21 ; Get the LR
1169 mfsrr0 r22 ; Get SRR0
1170 stw r25,LTR_cr(r20) ; Save CR
1171 mfsrr1 r24 ; Get the SRR1
1172 stw r23,LTR_dsisr(r20) ; Save DSISR
1173 std r22,LTR_srr0(r20) ; Save SRR0
1174 mfdar r23 ; Get DAR
1175 std r24,LTR_srr1(r20) ; Save SRR1
1176 std r23,LTR_dar(r20) ; Save DAR
1177 std r21,LTR_lr(r20) ; Save LR
1178
1179 std r13,LTR_ctr(r20) ; Save CTR
1180 std r0,LTR_r0(r20) ; Save register
1181 std r1,LTR_r1(r20) ; Save register
1182 std r2,LTR_r2(r20) ; Save register
1183 std r3,LTR_r3(r20) ; Save register
1184 std r4,LTR_r4(r20) ; Save register
1185 std r5,LTR_r5(r20) ; Save register
1186 std r6,LTR_r6(r20) ; Save register
1187
1188 #if 0
1189 lwz r21,FPUowner(r11) ; (TEST/DEBUG) Get the current floating point owner
1190 stw r21,LTR_rsvd0(r20) ; (TEST/DEBUG) Record the owner
1191 #endif
1192
1193 #if ESPDEBUG
1194 dcbf 0,r20 ; Force to memory
1195 sync ; Make sure it all goes
1196 #endif
1197
1198 ctdisa64: mtcrf 0x80,r25 ; Restore the used condition register field
1199 ld r20,tempr0(r11) ; Restore work register
1200 ld r21,tempr1(r11) ; Restore work register
1201 ld r25,tempr2(r11) ; Restore work register
1202 mtctr r13 ; Restore the caller's CTR
1203 ld r22,tempr3(r11) ; Restore work register
1204 ld r23,tempr4(r11) ; Restore work register
1205 ld r24,tempr5(r11) ; Restore work register
1206 b uftX64 ; Go restore the rest and go...
1207
1208 ctbail64: mtcrf 0x80,r25 ; Restore the used condition register field
1209 ld r20,tempr0(r11) ; Restore work register
1210 ld r21,tempr1(r11) ; Restore work register
1211 ld r25,tempr2(r11) ; Restore work register
1212 mtctr r13 ; Restore the caller's CTR
1213 ld r22,tempr3(r11) ; Restore work register
1214 ld r23,tempr4(r11) ; Restore work register
1215 li r11,T_SYSTEM_CALL|T_FAM ; Set system code call
1216 b extEntry64 ; Go straight to the 64-bit code...
1217
1218
1219
1220 ; Handle a system call that is not a UFT and which thus goes upstairs.
1221
1222 uftNormalFF: ; here with entire cr in r13
1223 mtcr r13 ; restore all 8 fields
1224 b uftNormalSyscall1 ; Join common...
1225
1226 uftNormal80: ; here with callers cr0 in r13
1227 mtcrf 0x80,r13 ; restore cr0
1228 b uftNormalSyscall1 ; Join common...
1229
1230 uftNormalSyscall: ; r13 = callers ctr
1231 mtctr r13 ; restore ctr
1232 uftNormalSyscall1:
1233 li r11,T_SYSTEM_CALL|T_FAM ; this is a system call (and fall through)
1234
1235
1236 /*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
1237 /*
1238 * .L_exception_entry(type)
1239 *
1240 * Come here via branch directly from the vector, or falling down from above, with the following
1241 * set up:
1242 *
1243 * ENTRY: interrupts off, VM off, in 64-bit mode if supported
1244 * Caller's r13 saved in sprg2.
1245 * Caller's r11 saved in sprg3.
1246 * Exception code (ie, T_SYSTEM_CALL etc) in r11.
1247 * All other registers are live.
1248 *
1249 */
1250
1251 .L_exception_entry: ; WARNING: can fall through from UFT handler
1252
1253 /*
1254 *
1255 * Here we will save off a mess of registers, the special ones and R0-R12. We use the DCBZ
1256 * instruction to clear and allcoate a line in the cache. This way we won't take any cache
1257 * misses, so these stores won't take all that long. Except the first line that is because
1258 * we can't do a DCBZ if the L1 D-cache is off. The rest we will skip if they are
1259 * off also.
1260 *
1261 * Note that if we are attempting to sleep (as opposed to nap or doze) all interruptions
1262 * are ignored.
1263 */
1264
1265
1266 .globl EXT(extPatch32)
1267
1268
1269 LEXT(extPatch32)
1270 b extEntry64 ; Go do 64-bit (patched to a nop if 32-bit)
1271 mfsprg r13,0 ; Load per_proc
1272 lwz r13,next_savearea+4(r13) ; Get the exception save area
1273 stw r0,saver0+4(r13) ; Save register 0
1274 stw r1,saver1+4(r13) ; Save register 1
1275
1276 mfspr r1,hid0 ; Get HID0
1277 mfcr r0 ; Save the whole CR
1278
1279 mtcrf 0x20,r1 ; Get set to test for sleep
1280 cror doze,doze,nap ; Remember if we are napping
1281 bf sleep,notsleep ; Skip if we are not trying to sleep
1282
1283 mtcrf 0x20,r0 ; Restore the CR
1284 lwz r0,saver0+4(r13) ; Restore R0
1285 lwz r1,saver1+4(r13) ; Restore R1
1286 mfsprg r13,0 ; Get the per_proc
1287 lwz r11,pfAvailable(r13) ; Get back the feature flags
1288 mfsprg r13,2 ; Restore R13
1289 mtsprg 2,r11 ; Set sprg2 to the features
1290 mfsprg r11,3 ; Restore R11
1291 rfi ; Jump back into sleep code...
1292 .long 0 ; Leave these here please...
1293 .long 0
1294 .long 0
1295 .long 0
1296 .long 0
1297 .long 0
1298 .long 0
1299 .long 0
1300
1301
1302 ;
1303 ; This is the 32-bit context saving stuff
1304 ;
1305
1306 .align 5
1307
1308 notsleep: stw r2,saver2+4(r13) ; Save this one
1309 bf doze,notspdo ; Skip the next if we are not napping/dozing...
1310 rlwinm r2,r1,0,nap+1,doze-1 ; Clear any possible nap and doze bits
1311 mtspr hid0,r2 ; Clear the nap/doze bits
1312 notspdo:
1313
1314 #if INSTRUMENT
1315 mfspr r2,pmc1 ; INSTRUMENT - saveinstr[0] - Take earliest possible stamp
1316 stw r2,0x6100+(0x00*16)+0x0(0) ; INSTRUMENT - Save it
1317 mfspr r2,pmc2 ; INSTRUMENT - Get stamp
1318 stw r2,0x6100+(0x00*16)+0x4(0) ; INSTRUMENT - Save it
1319 mfspr r2,pmc3 ; INSTRUMENT - Get stamp
1320 stw r2,0x6100+(0x00*16)+0x8(0) ; INSTRUMENT - Save it
1321 mfspr r2,pmc4 ; INSTRUMENT - Get stamp
1322 stw r2,0x6100+(0x00*16)+0xC(0) ; INSTRUMENT - Save it
1323 #endif
1324
1325 la r1,saver4(r13) ; Point to the next line in case we need it
1326 crmove wasNapping,doze ; Remember if we were napping
1327 mfsprg r2,0 ; Get the per_proc area
1328 dcbz 0,r1 ; allocate r4-r7 32-byte line in cache
1329
1330 ;
1331 ; Remember, we are setting up CR6 with feature flags
1332 ;
1333 andi. r1,r11,T_FAM ; Check FAM bit
1334
1335 stw r3,saver3+4(r13) ; Save this one
1336 stw r4,saver4+4(r13) ; Save this one
1337 andc r11,r11,r1 ; Clear FAM bit
1338 beq+ noFAM ; Is it FAM intercept
1339 mfsrr1 r3 ; Load srr1
1340 rlwinm. r3,r3,0,MSR_PR_BIT,MSR_PR_BIT ; Are we trapping from supervisor state?
1341 beq+ noFAM ; From supervisor state
1342 lwz r1,spcFlags(r2) ; Load spcFlags
1343 rlwinm r1,r1,1+FamVMmodebit,30,31 ; Extract FamVMenabit and FamVMmodebit
1344 cmpwi cr0,r1,2 ; Check FamVMena set without FamVMmode
1345 bne+ noFAM ; Can this context be FAM intercept
1346 lwz r4,FAMintercept(r2) ; Load exceptions mask to intercept
1347 srwi r1,r11,2 ; divide r11 by 4
1348 lis r3,0x8000 ; Set r3 to 0x80000000
1349 srw r1,r3,r1 ; Set bit for current exception
1350 and. r1,r1,r4 ; And current exception with the intercept mask
1351 beq+ noFAM ; Is it FAM intercept
1352 b EXT(vmm_fam_exc)
1353 noFAM:
1354 lwz r1,pfAvailable(r2) ; Get the CPU features flags
1355 la r3,saver8(r13) ; Point to line with r8-r11
1356 mtcrf 0xE2,r1 ; Put the features flags (that we care about) in the CR
1357 dcbz 0,r3 ; allocate r8-r11 32-byte line in cache
1358 la r3,saver12(r13) ; point to r12-r15 line
1359 lis r4,hi16(MASK(MSR_VEC)|MASK(MSR_FP)|MASK(MSR_ME)) ; Set up the MSR we will use throughout. Note that ME come on here if MCK
1360 stw r6,saver6+4(r13) ; Save this one
1361 ori r4,r4,lo16(MASK(MSR_VEC)|MASK(MSR_FP)|MASK(MSR_ME)) ; Rest of MSR
1362 stw r8,saver8+4(r13) ; Save this one
1363 crmove featAltivec,pfAltivecb ; Set the Altivec flag
1364 mtmsr r4 ; Set MSR
1365 isync
1366 mfsrr0 r6 ; Get the interruption SRR0
1367 la r8,savesrr0(r13) ; point to line with SRR0, SRR1, CR, XER, and LR
1368 dcbz 0,r3 ; allocate r12-r15 32-byte line in cache
1369 la r3,saver16(r13) ; point to next line
1370 dcbz 0,r8 ; allocate 32-byte line with SRR0, SRR1, CR, XER, and LR
1371 stw r7,saver7+4(r13) ; Save this one
1372 lhz r8,PP_CPU_FLAGS(r2) ; Get the flags
1373 mfsrr1 r7 ; Get the interrupt SRR1
1374 rlwinm r8,r8,(((31-MSR_BE_BIT)+(traceBEb+16+1))&31),MSR_BE_BIT,MSR_BE_BIT ; Set BE bit if special trace is on
1375 stw r6,savesrr0+4(r13) ; Save the SRR0
1376 rlwinm r6,r7,(((31-MSR_BE_BIT)+(MSR_PR_BIT+1))&31),MSR_BE_BIT,MSR_BE_BIT ; Move PR bit to BE bit
1377 stw r5,saver5+4(r13) ; Save this one
1378 and r8,r6,r8 ; Remove BE bit only if problem state and special tracing on
1379 mfsprg r6,2 ; Get interrupt time R13
1380 mtsprg 2,r1 ; Set the feature flags
1381 andc r7,r7,r8 ; Clear BE bit if special trace is on and PR is set
1382 mfsprg r8,3 ; Get rupt time R11
1383 stw r7,savesrr1+4(r13) ; Save SRR1
1384 stw r8,saver11+4(r13) ; Save rupt time R11
1385 stw r6,saver13+4(r13) ; Save rupt R13
1386 dcbz 0,r3 ; allocate 32-byte line with r16-r19
1387 la r3,saver20(r13) ; point to next line
1388
1389 getTB: mftbu r6 ; Get the upper timebase
1390 mftb r7 ; Get the lower timebase
1391 mftbu r8 ; Get the upper one again
1392 cmplw r6,r8 ; Did the top tick?
1393 bne- getTB ; Yeah, need to get it again...
1394
1395 #if INSTRUMENT
1396 mfspr r6,pmc1 ; INSTRUMENT - saveinstr[1] - Save halfway context save stamp
1397 stw r6,0x6100+(0x01*16)+0x0(0) ; INSTRUMENT - Save it
1398 mfspr r6,pmc2 ; INSTRUMENT - Get stamp
1399 stw r6,0x6100+(0x01*16)+0x4(0) ; INSTRUMENT - Save it
1400 mfspr r6,pmc3 ; INSTRUMENT - Get stamp
1401 stw r6,0x6100+(0x01*16)+0x8(0) ; INSTRUMENT - Save it
1402 mfspr r6,pmc4 ; INSTRUMENT - Get stamp
1403 stw r6,0x6100+(0x01*16)+0xC(0) ; INSTRUMENT - Save it
1404 #endif
1405
1406 stw r8,ruptStamp(r2) ; Save the top of time stamp
1407 stw r8,SAVtime(r13) ; Save the top of time stamp
1408 stw r7,ruptStamp+4(r2) ; Save the bottom of time stamp
1409 stw r7,SAVtime+4(r13) ; Save the bottom of time stamp
1410
1411 dcbz 0,r3 ; allocate 32-byte line with r20-r23
1412 stw r9,saver9+4(r13) ; Save this one
1413
1414 stw r10,saver10+4(r13) ; Save this one
1415 mflr r4 ; Get the LR
1416 mfxer r10 ; Get the XER
1417
1418 bf+ wasNapping,notNapping ; Skip if not waking up from nap...
1419
1420 lwz r6,napStamp+4(r2) ; Pick up low order nap stamp
1421 lis r3,hi16(EXT(machine_idle_ret)) ; Get high part of nap/doze return
1422 lwz r5,napStamp(r2) ; and high order
1423 subfc r7,r6,r7 ; Subtract low stamp from now
1424 lwz r6,napTotal+4(r2) ; Pick up low total
1425 subfe r5,r5,r8 ; Subtract high stamp and borrow from now
1426 lwz r8,napTotal(r2) ; Pick up the high total
1427 addc r6,r6,r7 ; Add low to total
1428 ori r3,r3,lo16(EXT(machine_idle_ret)) ; Get low part of nap/doze return
1429 adde r8,r8,r5 ; Add high and carry to total
1430 stw r6,napTotal+4(r2) ; Save the low total
1431 stw r8,napTotal(r2) ; Save the high total
1432 stw r3,savesrr0+4(r13) ; Modify to return to nap/doze exit
1433
1434 rlwinm. r3,r1,0,pfSlowNapb,pfSlowNapb ; Should HID1 be restored?
1435 beq notInSlowNap
1436
1437 lwz r3,pfHID1(r2) ; Get saved HID1 value
1438 mtspr hid1,r3 ; Restore HID1
1439
1440 notInSlowNap:
1441 rlwinm. r3,r1,0,pfNoL2PFNapb,pfNoL2PFNapb ; Should MSSCR0 be restored?
1442 beq notNapping
1443
1444 lwz r3,pfMSSCR0(r2) ; Get saved MSSCR0 value
1445 mtspr msscr0,r3 ; Restore MSSCR0
1446 sync
1447 isync
1448
1449 notNapping: stw r12,saver12+4(r13) ; Save this one
1450
1451 stw r14,saver14+4(r13) ; Save this one
1452 stw r15,saver15+4(r13) ; Save this one
1453 la r14,saver24(r13) ; Point to the next block to save into
1454 mfctr r6 ; Get the CTR
1455 stw r16,saver16+4(r13) ; Save this one
1456 la r15,savectr(r13) ; point to line with CTR, DAR, DSISR, Exception code, and VRSAVE
1457 stw r4,savelr+4(r13) ; Save rupt LR
1458
1459 dcbz 0,r14 ; allocate 32-byte line with r24-r27
1460 la r16,saver28(r13) ; point to line with r28-r31
1461 dcbz 0,r15 ; allocate line with CTR, DAR, DSISR, Exception code, and VRSAVE
1462 stw r17,saver17+4(r13) ; Save this one
1463 stw r18,saver18+4(r13) ; Save this one
1464 stw r6,savectr+4(r13) ; Save rupt CTR
1465 stw r0,savecr(r13) ; Save rupt CR
1466 stw r19,saver19+4(r13) ; Save this one
1467 mfdar r6 ; Get the rupt DAR
1468 stw r20,saver20+4(r13) ; Save this one
1469 dcbz 0,r16 ; allocate 32-byte line with r28-r31
1470
1471 stw r21,saver21+4(r13) ; Save this one
1472 lwz r21,spcFlags(r2) ; Get the special flags from per_proc
1473 stw r10,savexer+4(r13) ; Save the rupt XER
1474 stw r30,saver30+4(r13) ; Save this one
1475 lhz r30,pfrptdProc(r2) ; Get the reported processor type
1476 stw r31,saver31+4(r13) ; Save this one
1477 stw r22,saver22+4(r13) ; Save this one
1478 stw r23,saver23+4(r13) ; Save this one
1479 stw r24,saver24+4(r13) ; Save this one
1480 stw r25,saver25+4(r13) ; Save this one
1481 mfdsisr r7 ; Get the rupt DSISR
1482 stw r26,saver26+4(r13) ; Save this one
1483 stw r27,saver27+4(r13) ; Save this one
1484 andis. r21,r21,hi16(perfMonitor) ; Is the performance monitor enabled?
1485 stw r28,saver28+4(r13) ; Save this one
1486 cmpwi cr1, r30,CPU_SUBTYPE_POWERPC_750 ; G3?
1487 la r27,savevscr(r13) ; point to 32-byte line with VSCR and FPSCR
1488 cmpwi cr2,r30,CPU_SUBTYPE_POWERPC_7400 ; This guy?
1489 stw r29,saver29+4(r13) ; Save R29
1490 stw r6,savedar+4(r13) ; Save the rupt DAR
1491 li r10,savepmc ; Point to pmc savearea
1492
1493 beq+ noPerfMonSave32 ; No perfmon on here...
1494
1495 dcbz r10,r13 ; Clear first part of pmc area
1496 li r10,savepmc+0x20 ; Point to pmc savearea second part
1497 li r22,0 ; r22: zero
1498 dcbz r10,r13 ; Clear second part of pmc area
1499
1500 beq cr1,perfMonSave32_750 ; This is a G3...
1501
1502 beq cr2,perfMonSave32_7400 ; Regular olde G4...
1503
1504 mfspr r24,pmc5 ; Here for a 7450
1505 mfspr r25,pmc6
1506 stw r24,savepmc+16(r13) ; Save PMC5
1507 stw r25,savepmc+20(r13) ; Save PMC6
1508 mtspr pmc5,r22 ; Leave PMC5 clear
1509 mtspr pmc6,r22 ; Leave PMC6 clear
1510
1511 perfMonSave32_7400:
1512 mfspr r25,mmcr2
1513 stw r25,savemmcr2+4(r13) ; Save MMCR2
1514 mtspr mmcr2,r22 ; Leave MMCR2 clear
1515
1516 perfMonSave32_750:
1517 mfspr r23,mmcr0
1518 mfspr r24,mmcr1
1519 stw r23,savemmcr0+4(r13) ; Save MMCR0
1520 stw r24,savemmcr1+4(r13) ; Save MMCR1
1521 mtspr mmcr0,r22 ; Leave MMCR0 clear
1522 mtspr mmcr1,r22 ; Leave MMCR1 clear
1523 mfspr r23,pmc1
1524 mfspr r24,pmc2
1525 mfspr r25,pmc3
1526 mfspr r26,pmc4
1527 stw r23,savepmc+0(r13) ; Save PMC1
1528 stw r24,savepmc+4(r13) ; Save PMC2
1529 stw r25,savepmc+8(r13) ; Save PMC3
1530 stw r26,savepmc+12(r13) ; Save PMC4
1531 mtspr pmc1,r22 ; Leave PMC1 clear
1532 mtspr pmc2,r22 ; Leave PMC2 clear
1533 mtspr pmc3,r22 ; Leave PMC3 clear
1534 mtspr pmc4,r22 ; Leave PMC4 clear
1535
1536 noPerfMonSave32:
1537 dcbz 0,r27 ; allocate line with VSCR and FPSCR
1538
1539 stw r7,savedsisr(r13) ; Save the rupt code DSISR
1540 stw r11,saveexception(r13) ; Save the exception code
1541
1542
1543 ;
1544 ; Everything is saved at this point, except for FPRs, and VMX registers.
1545 ; Time for us to get a new savearea and then trace interrupt if it is enabled.
1546 ;
1547
1548 lwz r25,traceMask(0) ; Get the trace mask
1549 li r0,SAVgeneral ; Get the savearea type value
1550 lhz r19,PP_CPU_NUMBER(r2) ; Get the logical processor number
1551 rlwinm r22,r11,30,0,31 ; Divide interrupt code by 2
1552 stb r0,SAVflags+2(r13) ; Mark valid context
1553 addi r22,r22,10 ; Adjust code so we shift into CR5
1554 li r23,trcWork ; Get the trace work area address
1555 rlwnm r7,r25,r22,22,22 ; Set CR5_EQ bit position to 0 if tracing allowed
1556 li r26,0x8 ; Get start of cpu mask
1557 srw r26,r26,r19 ; Get bit position of cpu number
1558 mtcrf 0x04,r7 ; Set CR5 to show trace or not
1559 and. r26,r26,r25 ; See if we trace this cpu
1560 crandc cr5_eq,cr5_eq,cr0_eq ; Turn off tracing if cpu is disabled
1561 ;
1562 ; At this point, we can take another exception and lose nothing.
1563 ;
1564
1565 #if INSTRUMENT
1566 mfspr r26,pmc1 ; INSTRUMENT - saveinstr[2] - Take stamp after save is done
1567 stw r26,0x6100+(0x02*16)+0x0(0) ; INSTRUMENT - Save it
1568 mfspr r26,pmc2 ; INSTRUMENT - Get stamp
1569 stw r26,0x6100+(0x02*16)+0x4(0) ; INSTRUMENT - Save it
1570 mfspr r26,pmc3 ; INSTRUMENT - Get stamp
1571 stw r26,0x6100+(0x02*16)+0x8(0) ; INSTRUMENT - Save it
1572 mfspr r26,pmc4 ; INSTRUMENT - Get stamp
1573 stw r26,0x6100+(0x02*16)+0xC(0) ; INSTRUMENT - Save it
1574 #endif
1575
1576 bne+ cr5,xcp32xit ; Skip all of this if no tracing here...
1577
1578 ;
1579 ; We select a trace entry using a compare and swap on the next entry field.
1580 ; Since we do not lock the actual trace buffer, there is a potential that
1581 ; another processor could wrap an trash our entry. Who cares?
1582 ;
1583
1584 lwz r25,traceStart(0) ; Get the start of trace table
1585 lwz r26,traceEnd(0) ; Get end of trace table
1586
1587 trcsel: lwarx r20,0,r23 ; Get and reserve the next slot to allocate
1588
1589 addi r22,r20,LTR_size ; Point to the next trace entry
1590 cmplw r22,r26 ; Do we need to wrap the trace table?
1591 bne+ gotTrcEnt ; No wrap, we got us a trace entry...
1592
1593 mr r22,r25 ; Wrap back to start
1594
1595 gotTrcEnt: stwcx. r22,0,r23 ; Try to update the current pointer
1596 bne- trcsel ; Collision, try again...
1597
1598 #if ESPDEBUG
1599 dcbf 0,r23 ; Force to memory
1600 sync
1601 #endif
1602
1603 dcbz 0,r20 ; Clear and allocate first trace line
1604
1605 ;
1606 ; Let us cut that trace entry now.
1607 ;
1608 ; Note that this code cuts a trace table entry for everything but the CutTrace call.
1609 ; An identical entry is made during normal CutTrace processing. Any entry
1610 ; format changes made must be done in both places.
1611 ;
1612
1613 lwz r16,ruptStamp(r2) ; Get top of time base
1614 lwz r17,ruptStamp+4(r2) ; Get the bottom of time stamp
1615
1616 li r14,32 ; Offset to second line
1617
1618 lwz r0,saver0+4(r13) ; Get back interrupt time R0
1619 lwz r1,saver1+4(r13) ; Get back interrupt time R1
1620 lwz r8,savecr(r13) ; Get the CR value
1621
1622 dcbz r14,r20 ; Zap the second line
1623
1624 sth r19,LTR_cpu(r20) ; Stash the cpu number
1625 li r14,64 ; Offset to third line
1626 sth r11,LTR_excpt(r20) ; Save the exception type
1627 lwz r7,saver2+4(r13) ; Get back interrupt time R2
1628 lwz r3,saver3+4(r13) ; Restore this one
1629
1630 dcbz r14,r20 ; Zap the third half
1631
1632 mfdsisr r9 ; Get the DSISR
1633 li r14,96 ; Offset to forth line
1634 stw r16,LTR_timeHi(r20) ; Set the upper part of TB
1635 stw r17,LTR_timeLo(r20) ; Set the lower part of TB
1636 lwz r10,savelr+4(r13) ; Get the LR
1637 mfsrr0 r17 ; Get SRR0 back, it is still good
1638
1639 dcbz r14,r20 ; Zap the forth half
1640 lwz r4,saver4+4(r13) ; Restore this one
1641 lwz r5,saver5+4(r13) ; Restore this one
1642 mfsrr1 r18 ; SRR1 is still good in here
1643
1644 stw r8,LTR_cr(r20) ; Save the CR
1645 lwz r6,saver6+4(r13) ; Get R6
1646 mfdar r16 ; Get this back
1647 stw r9,LTR_dsisr(r20) ; Save the DSISR
1648 stw r17,LTR_srr0+4(r20) ; Save the SSR0
1649
1650 stw r18,LTR_srr1+4(r20) ; Save the SRR1
1651 stw r16,LTR_dar+4(r20) ; Save the DAR
1652 mfctr r17 ; Get the CTR (still good in register)
1653 stw r13,LTR_save+4(r20) ; Save the savearea
1654 stw r10,LTR_lr+4(r20) ; Save the LR
1655
1656 stw r17,LTR_ctr+4(r20) ; Save off the CTR
1657 stw r0,LTR_r0+4(r20) ; Save off register 0
1658 stw r1,LTR_r1+4(r20) ; Save off register 1
1659 stw r7,LTR_r2+4(r20) ; Save off register 2
1660
1661
1662 stw r3,LTR_r3+4(r20) ; Save off register 3
1663 stw r4,LTR_r4+4(r20) ; Save off register 4
1664 stw r5,LTR_r5+4(r20) ; Save off register 5
1665 stw r6,LTR_r6+4(r20) ; Save off register 6
1666
1667 #if ESPDEBUG
1668 addi r17,r20,32 ; Second line
1669 addi r16,r20,64 ; Third line
1670 dcbst br0,r20 ; Force to memory
1671 dcbst br0,r17 ; Force to memory
1672 addi r17,r17,32 ; Fourth line
1673 dcbst br0,r16 ; Force to memory
1674 dcbst br0,r17 ; Force to memory
1675
1676 sync ; Make sure it all goes
1677 #endif
1678 xcp32xit: mr r14,r11 ; Save the interrupt code across the call
1679 bl EXT(save_get_phys_32) ; Grab a savearea
1680 mfsprg r2,0 ; Get the per_proc info
1681 li r10,emfp0 ; Point to floating point save
1682 mr r11,r14 ; Get the exception code back
1683 dcbz r10,r2 ; Clear for speed
1684 stw r3,next_savearea+4(r2) ; Store the savearea for the next rupt
1685
1686 #if INSTRUMENT
1687 mfspr r4,pmc1 ; INSTRUMENT - saveinstr[3] - Take stamp after next savearea
1688 stw r4,0x6100+(0x03*16)+0x0(0) ; INSTRUMENT - Save it
1689 mfspr r4,pmc2 ; INSTRUMENT - Get stamp
1690 stw r4,0x6100+(0x03*16)+0x4(0) ; INSTRUMENT - Save it
1691 mfspr r4,pmc3 ; INSTRUMENT - Get stamp
1692 stw r4,0x6100+(0x03*16)+0x8(0) ; INSTRUMENT - Save it
1693 mfspr r4,pmc4 ; INSTRUMENT - Get stamp
1694 stw r4,0x6100+(0x03*16)+0xC(0) ; INSTRUMENT - Save it
1695 #endif
1696 b xcpCommon ; Go join the common interrupt processing...
1697
1698 ;
1699 ;
1700 ; This is the 64-bit context saving stuff
1701 ;
1702
1703 .align 5
1704
1705 extEntry64: mfsprg r13,0 ; Load per_proc
1706 ld r13,next_savearea(r13) ; Get the exception save area
1707 std r0,saver0(r13) ; Save register 0
1708 lis r0,hi16(MASK(MSR_VEC)|MASK(MSR_FP)|MASK(MSR_ME)) ; Set up the MSR we will use throughout. Note that ME come on here if MCK
1709 std r1,saver1(r13) ; Save register 1
1710 ori r1,r0,lo16(MASK(MSR_VEC)|MASK(MSR_FP)|MASK(MSR_ME)) ; Rest of MSR
1711 lis r0,0x0010 ; Get rupt code transform validity mask
1712 mtmsr r1 ; Set MSR
1713 isync
1714
1715 ori r0,r0,0x0200 ; Get rupt code transform validity mask
1716 std r2,saver2(r13) ; Save this one
1717 lis r1,0x00F0 ; Top half of xform XOR
1718 rlwinm r2,r11,29,27,31 ; Get high 5 bits of rupt code
1719 std r3,saver3(r13) ; Save this one
1720 slw r0,r0,r2 ; Move transform validity bit to bit 0
1721 std r4,saver4(r13) ; Save this one
1722 std r5,saver5(r13) ; Save this one
1723 ori r1,r1,0x04EC ; Bottom half of xform XOR
1724 mfxer r5 ; Save the XER because we are about to muck with it
1725 rlwinm r4,r11,1,27,28 ; Get bottom of interrupt code * 8
1726 lis r3,hi16(dozem|napm) ; Get the nap and doze bits
1727 srawi r0,r0,31 ; Get 0xFFFFFFFF of xform valid, 0 otherwise
1728 rlwnm r4,r1,r4,24,31 ; Extract the xform XOR
1729 li r1,saver16 ; Point to the next line
1730 and r4,r4,r0 ; Only keep transform if we are to use it
1731 li r2,lgKillResv ; Point to the killing field
1732 mfcr r0 ; Save the CR
1733 stwcx. r2,0,r2 ; Kill any pending reservation
1734 dcbz128 r1,r13 ; Blow away the line
1735 sldi r3,r3,32 ; Position it
1736 mfspr r1,hid0 ; Get HID0
1737 andc r3,r1,r3 ; Clear nap and doze
1738 xor r11,r11,r4 ; Transform 970 rupt code to standard keeping FAM bit
1739 cmpld r3,r1 ; See if nap and/or doze was on
1740 std r6,saver6(r13) ; Save this one
1741 mfsprg r2,0 ; Get the per_proc area
1742 la r6,savesrr0(r13) ; point to line with SRR0, SRR1, CR, XER, and LR
1743 beq++ eE64NoNap ; No nap here, skip all this...
1744
1745 sync ; Make sure we are clean
1746 mtspr hid0,r3 ; Set the updated hid0
1747 mfspr r1,hid0 ; Yes, this is silly, keep it here
1748 mfspr r1,hid0 ; Yes, this is a duplicate, keep it here
1749 mfspr r1,hid0 ; Yes, this is a duplicate, keep it here
1750 mfspr r1,hid0 ; Yes, this is a duplicate, keep it here
1751 mfspr r1,hid0 ; Yes, this is a duplicate, keep it here
1752 mfspr r1,hid0 ; Yes, this is a duplicate, keep it here
1753
1754 eE64NoNap: crnot wasNapping,cr0_eq ; Remember if we were napping
1755 andi. r1,r11,T_FAM ; Check FAM bit
1756 beq++ eEnoFAM ; Is it FAM intercept
1757 mfsrr1 r3 ; Load srr1
1758 andc r11,r11,r1 ; Clear FAM bit
1759 rlwinm. r3,r3,0,MSR_PR_BIT,MSR_PR_BIT ; Are we trapping from supervisor state?
1760 beq++ eEnoFAM ; From supervisor state
1761 lwz r1,spcFlags(r2) ; Load spcFlags
1762 rlwinm r1,r1,1+FamVMmodebit,30,31 ; Extract FamVMenabit and FamVMmodebit
1763 cmpwi cr0,r1,2 ; Check FamVMena set without FamVMmode
1764 bne++ eEnoFAM ; Can this context be FAM intercept
1765 lwz r4,FAMintercept(r2) ; Load exceptions mask to intercept
1766 li r3,0 ; Clear
1767 srwi r1,r11,2 ; divide r11 by 4
1768 oris r3,r3,0x8000 ; Set r3 to 0x80000000
1769 srw r1,r3,r1 ; Set bit for current exception
1770 and. r1,r1,r4 ; And current exception with the intercept mask
1771 beq++ eEnoFAM ; Is it FAM intercept
1772 b EXT(vmm_fam_exc)
1773
1774 .align 5
1775
1776 eEnoFAM: lwz r1,pfAvailable(r2) ; Get the CPU features flags
1777 dcbz128 0,r6 ; allocate 128-byte line with SRR0, SRR1, CR, XER, and LR
1778
1779 ;
1780 ; Remember, we are setting up CR6 with feature flags
1781 ;
1782 std r7,saver7(r13) ; Save this one
1783 mtcrf 0x80,r1 ; Put the features flags (that we care about) in the CR
1784 std r8,saver8(r13) ; Save this one
1785 mtcrf 0x40,r1 ; Put the features flags (that we care about) in the CR
1786 mfsrr0 r6 ; Get the interruption SRR0
1787 lhz r8,PP_CPU_FLAGS(r2) ; Get the flags
1788 mtcrf 0x20,r1 ; Put the features flags (that we care about) in the CR
1789 mfsrr1 r7 ; Get the interrupt SRR1
1790 rlwinm r8,r8,(((31-MSR_BE_BIT)+(traceBEb+16+1))&31),MSR_BE_BIT,MSR_BE_BIT ; Set BE bit if special trace is on
1791 std r6,savesrr0(r13) ; Save the SRR0
1792 mtcrf 0x02,r1 ; Put the features flags (that we care about) in the CR
1793 rlwinm r6,r7,(((31-MSR_BE_BIT)+(MSR_PR_BIT+1))&31),MSR_BE_BIT,MSR_BE_BIT ; Move PR bit to BE bit
1794 and r8,r6,r8 ; Remove BE bit only if problem state and special tracing on
1795 std r9,saver9(r13) ; Save this one
1796 andc r7,r7,r8 ; Clear BE bit if special trace is on and PR is set
1797 crmove featAltivec,pfAltivecb ; Set the Altivec flag
1798 std r7,savesrr1(r13) ; Save SRR1
1799 mfsprg r9,3 ; Get rupt time R11
1800 std r10,saver10(r13) ; Save this one
1801 mfsprg r6,2 ; Get interrupt time R13
1802 std r9,saver11(r13) ; Save rupt time R11
1803 mtsprg 2,r1 ; Set the feature flags
1804 std r12,saver12(r13) ; Save this one
1805 mflr r4 ; Get the LR
1806 mftb r7 ; Get the timebase
1807 std r6,saver13(r13) ; Save rupt R13
1808 std r7,ruptStamp(r2) ; Save the time stamp
1809 std r7,SAVtime(r13) ; Save the time stamp
1810
1811 bf++ wasNapping,notNappingSF ; Skip if not waking up from nap...
1812
1813 ld r6,napStamp(r2) ; Pick up nap stamp
1814 lis r3,hi16(EXT(machine_idle_ret)) ; Get high part of nap/doze return
1815 sub r7,r7,r6 ; Subtract stamp from now
1816 ld r6,napTotal(r2) ; Pick up total
1817 add r6,r6,r7 ; Add low to total
1818 ori r3,r3,lo16(EXT(machine_idle_ret)) ; Get low part of nap/doze return
1819 std r6,napTotal(r2) ; Save the high total
1820 std r3,savesrr0(r13) ; Modify to return to nap/doze exit
1821
1822 notNappingSF:
1823 std r14,saver14(r13) ; Save this one
1824 std r15,saver15(r13) ; Save this one
1825 stw r0,savecr(r13) ; Save rupt CR
1826 mfctr r6 ; Get the CTR
1827 std r16,saver16(r13) ; Save this one
1828 std r4,savelr(r13) ; Save rupt LR
1829
1830 std r17,saver17(r13) ; Save this one
1831 li r7,savepmc ; Point to pmc area
1832 std r18,saver18(r13) ; Save this one
1833 lwz r17,spcFlags(r2) ; Get the special flags from per_proc
1834 std r6,savectr(r13) ; Save rupt CTR
1835 std r19,saver19(r13) ; Save this one
1836 mfdar r6 ; Get the rupt DAR
1837 std r20,saver20(r13) ; Save this one
1838
1839 dcbz128 r7,r13 ; Clear out the pmc spot
1840
1841 std r21,saver21(r13) ; Save this one
1842 std r5,savexer(r13) ; Save the rupt XER
1843 std r22,saver22(r13) ; Save this one
1844 std r23,saver23(r13) ; Save this one
1845 std r24,saver24(r13) ; Save this one
1846 std r25,saver25(r13) ; Save this one
1847 mfdsisr r7 ; Get the rupt DSISR
1848 std r26,saver26(r13) ; Save this one
1849 andis. r17,r17,hi16(perfMonitor) ; Is the performance monitor enabled?
1850 std r27,saver27(r13) ; Save this one
1851 li r10,emfp0 ; Point to floating point save
1852 std r28,saver28(r13) ; Save this one
1853 la r27,savevscr(r13) ; point to 32-byte line with VSCR and FPSCR
1854 std r29,saver29(r13) ; Save R29
1855 std r30,saver30(r13) ; Save this one
1856 std r31,saver31(r13) ; Save this one
1857 std r6,savedar(r13) ; Save the rupt DAR
1858 stw r7,savedsisr(r13) ; Save the rupt code DSISR
1859 stw r11,saveexception(r13) ; Save the exception code
1860
1861 beq++ noPerfMonSave64 ; Performance monitor not on...
1862
1863 li r22,0 ; r22: zero
1864
1865 mfspr r23,mmcr0_gp
1866 mfspr r24,mmcr1_gp
1867 mfspr r25,mmcra_gp
1868 std r23,savemmcr0(r13) ; Save MMCR0
1869 std r24,savemmcr1(r13) ; Save MMCR1
1870 std r25,savemmcr2(r13) ; Save MMCRA
1871 mtspr mmcr0_gp,r22 ; Leave MMCR0 clear
1872 mtspr mmcr1_gp,r22 ; Leave MMCR1 clear
1873 mtspr mmcra_gp,r22 ; Leave MMCRA clear
1874 mfspr r23,pmc1_gp
1875 mfspr r24,pmc2_gp
1876 mfspr r25,pmc3_gp
1877 mfspr r26,pmc4_gp
1878 stw r23,savepmc+0(r13) ; Save PMC1
1879 stw r24,savepmc+4(r13) ; Save PMC2
1880 stw r25,savepmc+8(r13) ; Save PMC3
1881 stw r26,savepmc+12(r13) ; Save PMC4
1882 mfspr r23,pmc5_gp
1883 mfspr r24,pmc6_gp
1884 mfspr r25,pmc7_gp
1885 mfspr r26,pmc8_gp
1886 stw r23,savepmc+16(r13) ; Save PMC5
1887 stw r24,savepmc+20(r13) ; Save PMC6
1888 stw r25,savepmc+24(r13) ; Save PMC7
1889 stw r26,savepmc+28(r13) ; Save PMC8
1890 mtspr pmc1_gp,r22 ; Leave PMC1 clear
1891 mtspr pmc2_gp,r22 ; Leave PMC2 clear
1892 mtspr pmc3_gp,r22 ; Leave PMC3 clear
1893 mtspr pmc4_gp,r22 ; Leave PMC4 clear
1894 mtspr pmc5_gp,r22 ; Leave PMC5 clear
1895 mtspr pmc6_gp,r22 ; Leave PMC6 clear
1896 mtspr pmc7_gp,r22 ; Leave PMC7 clear
1897 mtspr pmc8_gp,r22 ; Leave PMC8 clear
1898
1899 noPerfMonSave64:
1900
1901 ;
1902 ; Everything is saved at this point, except for FPRs, and VMX registers.
1903 ; Time for us to get a new savearea and then trace interrupt if it is enabled.
1904 ;
1905
1906 lwz r25,traceMask(0) ; Get the trace mask
1907 li r0,SAVgeneral ; Get the savearea type value
1908 lhz r19,PP_CPU_NUMBER(r2) ; Get the logical processor number
1909 stb r0,SAVflags+2(r13) ; Mark valid context
1910 rlwinm r22,r11,30,0,31 ; Divide interrupt code by 2
1911 li r23,trcWork ; Get the trace work area address
1912 addi r22,r22,10 ; Adjust code so we shift into CR5
1913 li r26,0x8 ; Get start of cpu mask
1914 rlwnm r7,r25,r22,22,22 ; Set CR5_EQ bit position to 0 if tracing allowed
1915 srw r26,r26,r19 ; Get bit position of cpu number
1916 mtcrf 0x04,r7 ; Set CR5 to show trace or not
1917 and. r26,r26,r25 ; See if we trace this cpu
1918 crandc cr5_eq,cr5_eq,cr0_eq ; Turn off tracing if cpu is disabled
1919
1920 bne++ cr5,xcp64xit ; Skip all of this if no tracing here...
1921
1922 ;
1923 ; We select a trace entry using a compare and swap on the next entry field.
1924 ; Since we do not lock the actual trace buffer, there is a potential that
1925 ; another processor could wrap an trash our entry. Who cares?
1926 ;
1927
1928 lwz r25,traceStart(0) ; Get the start of trace table
1929 lwz r26,traceEnd(0) ; Get end of trace table
1930
1931 trcselSF: lwarx r20,0,r23 ; Get and reserve the next slot to allocate
1932
1933 addi r22,r20,LTR_size ; Point to the next trace entry
1934 cmplw r22,r26 ; Do we need to wrap the trace table?
1935 bne++ gotTrcEntSF ; No wrap, we got us a trace entry...
1936
1937 mr r22,r25 ; Wrap back to start
1938
1939 gotTrcEntSF:
1940 stwcx. r22,0,r23 ; Try to update the current pointer
1941 bne- trcselSF ; Collision, try again...
1942
1943 #if ESPDEBUG
1944 dcbf 0,r23 ; Force to memory
1945 sync
1946 #endif
1947
1948 ;
1949 ; Let us cut that trace entry now.
1950 ;
1951 ; Note that this code cuts a trace table entry for everything but the CutTrace call.
1952 ; An identical entry is made during normal CutTrace processing. Any entry
1953 ; format changes made must be done in both places.
1954 ;
1955
1956 dcbz128 0,r20 ; Zap the trace entry
1957
1958 lwz r9,SAVflags(r13) ; Get savearea flags
1959
1960 ld r16,ruptStamp(r2) ; Get top of time base
1961 ld r0,saver0(r13) ; Get back interrupt time R0 (we need this whether we trace or not)
1962 std r16,LTR_timeHi(r20) ; Set the upper part of TB
1963 ld r1,saver1(r13) ; Get back interrupt time R1
1964 rlwinm r9,r9,20,16,23 ; Isolate the special flags
1965 ld r18,saver2(r13) ; Get back interrupt time R2
1966 std r0,LTR_r0(r20) ; Save off register 0
1967 rlwimi r9,r19,0,24,31 ; Slide in the cpu number
1968 ld r3,saver3(r13) ; Restore this one
1969 sth r9,LTR_cpu(r20) ; Stash the cpu number and special flags
1970 std r1,LTR_r1(r20) ; Save off register 1
1971 ld r4,saver4(r13) ; Restore this one
1972 std r18,LTR_r2(r20) ; Save off register 2
1973 ld r5,saver5(r13) ; Restore this one
1974 ld r6,saver6(r13) ; Get R6
1975 std r3,LTR_r3(r20) ; Save off register 3
1976 lwz r16,savecr(r13) ; Get the CR value
1977 std r4,LTR_r4(r20) ; Save off register 4
1978 mfsrr0 r17 ; Get SRR0 back, it is still good
1979 std r5,LTR_r5(r20) ; Save off register 5
1980 std r6,LTR_r6(r20) ; Save off register 6
1981 mfsrr1 r18 ; SRR1 is still good in here
1982 stw r16,LTR_cr(r20) ; Save the CR
1983 std r17,LTR_srr0(r20) ; Save the SSR0
1984 std r18,LTR_srr1(r20) ; Save the SRR1
1985
1986 mfdar r17 ; Get this back
1987 ld r16,savelr(r13) ; Get the LR
1988 std r17,LTR_dar(r20) ; Save the DAR
1989 mfctr r17 ; Get the CTR (still good in register)
1990 std r16,LTR_lr(r20) ; Save the LR
1991 std r17,LTR_ctr(r20) ; Save off the CTR
1992 mfdsisr r17 ; Get the DSISR
1993 std r13,LTR_save(r20) ; Save the savearea
1994 stw r17,LTR_dsisr(r20) ; Save the DSISR
1995 sth r11,LTR_excpt(r20) ; Save the exception type
1996 #if 0
1997 lwz r17,FPUowner(r2) ; (TEST/DEBUG) Get the current floating point owner
1998 stw r17,LTR_rsvd0(r20) ; (TEST/DEBUG) Record the owner
1999 #endif
2000
2001 #if ESPDEBUG
2002 dcbf 0,r20 ; Force to memory
2003 sync ; Make sure it all goes
2004 #endif
2005 xcp64xit: mr r14,r11 ; Save the interrupt code across the call
2006 bl EXT(save_get_phys_64) ; Grab a savearea
2007 mfsprg r2,0 ; Get the per_proc info
2008 li r10,emfp0 ; Point to floating point save
2009 mr r11,r14 ; Get the exception code back
2010 dcbz128 r10,r2 ; Clear for speed
2011 std r3,next_savearea(r2) ; Store the savearea for the next rupt
2012 b xcpCommon ; Go join the common interrupt processing...
2013
2014 ;
2015 ; All of the context is saved. Now we will get a
2016 ; fresh savearea. After this we can take an interrupt.
2017 ;
2018
2019 .align 5
2020
2021 xcpCommon:
2022
2023 ;
2024 ; Here we will save some floating point and vector status
2025 ; and we also set a clean default status for a new interrupt level.
2026 ; Note that we assume that emfp0 is on an altivec boundary
2027 ; and that R10 points to it (as a displacemnt from R2).
2028 ;
2029 ; We need to save the FPSCR as if it is normal context.
2030 ; This is because pending exceptions will cause an exception even if
2031 ; FP is disabled. We need to clear the FPSCR when we first start running in the
2032 ; kernel.
2033 ;
2034
2035 stfd f0,emfp0(r2) ; Save FPR0
2036 stfd f1,emfp1(r2) ; Save FPR1
2037 li r19,0 ; Assume no Altivec
2038 mffs f0 ; Get the FPSCR
2039 lfd f1,Zero(0) ; Make a 0
2040 stfd f0,savefpscrpad(r13) ; Save the FPSCR
2041 li r9,0 ; Get set to clear VRSAVE
2042 mtfsf 0xFF,f1 ; Clear it
2043 addi r14,r10,16 ; Displacement to second vector register
2044 lfd f0,emfp0(r2) ; Restore FPR0
2045 la r28,savevscr(r13) ; Point to the status area
2046 lfd f1,emfp1(r2) ; Restore FPR1
2047
2048 bf featAltivec,noavec ; No Altivec on this CPU...
2049
2050 stvxl v0,r10,r2 ; Save a register
2051 stvxl v1,r14,r2 ; Save a second register
2052 mfspr r19,vrsave ; Get the VRSAVE register
2053 mfvscr v0 ; Get the vector status register
2054 vspltish v1,1 ; Turn on the non-Java bit and saturate
2055 stvxl v0,0,r28 ; Save the vector status
2056 vspltisw v0,1 ; Turn on the saturate bit
2057 vxor v1,v1,v0 ; Turn off saturate
2058 mtvscr v1 ; Set the non-java, no saturate status for new level
2059 mtspr vrsave,r9 ; Clear VRSAVE for each interrupt level
2060
2061 lvxl v0,r10,r2 ; Restore first work register
2062 lvxl v1,r14,r2 ; Restore second work register
2063
2064 noavec: stw r19,savevrsave(r13) ; Save the vector register usage flags
2065
2066 ;
2067 ; We are now done saving all of the context. Start filtering the interrupts.
2068 ; Note that a Redrive will count as an actual interrupt.
2069 ; Note also that we take a lot of system calls so we will start decode here.
2070 ;
2071
2072 Redrive:
2073
2074
2075 #if INSTRUMENT
2076 mfspr r20,pmc1 ; INSTRUMENT - saveinstr[4] - Take stamp before exception filter
2077 stw r20,0x6100+(0x04*16)+0x0(0) ; INSTRUMENT - Save it
2078 mfspr r20,pmc2 ; INSTRUMENT - Get stamp
2079 stw r20,0x6100+(0x04*16)+0x4(0) ; INSTRUMENT - Save it
2080 mfspr r20,pmc3 ; INSTRUMENT - Get stamp
2081 stw r20,0x6100+(0x04*16)+0x8(0) ; INSTRUMENT - Save it
2082 mfspr r20,pmc4 ; INSTRUMENT - Get stamp
2083 stw r20,0x6100+(0x04*16)+0xC(0) ; INSTRUMENT - Save it
2084 #endif
2085 lwz r22,SAVflags(r13) ; Pick up the flags
2086 lwz r0,saver0+4(r13) ; Get back interrupt time syscall number
2087 mfsprg r2,0 ; Restore per_proc
2088
2089 lwz r20,lo16(xcpTable)(r11) ; Get the interrupt handler (note: xcpTable must be in 1st 32k of physical memory)
2090 la r12,hwCounts(r2) ; Point to the exception count area
2091 andis. r24,r22,hi16(SAVeat) ; Should we eat this one?
2092 rlwinm r22,r22,SAVredriveb+1,31,31 ; Get a 1 if we are redriving
2093 add r12,r12,r11 ; Point to the count
2094 lwz r25,0(r12) ; Get the old value
2095 lwz r23,hwRedrives(r2) ; Get the redrive count
2096 crmove cr3_eq,cr0_eq ; Remember if we are ignoring
2097 xori r24,r22,1 ; Get the NOT of the redrive
2098 mtctr r20 ; Point to the interrupt handler
2099 mtcrf 0x80,r0 ; Set our CR0 to the high nybble of possible syscall code
2100 add r25,r25,r24 ; Count this one if not a redrive
2101 add r23,r23,r22 ; Count this one if if is a redrive
2102 crandc cr0_lt,cr0_lt,cr0_gt ; See if we have R0 equal to 0b10xx...x
2103 stw r25,0(r12) ; Store it back
2104 stw r23,hwRedrives(r2) ; Save the redrive count
2105 bne-- cr3,IgnoreRupt ; Interruption is being ignored...
2106 bctr ; Go process the exception...
2107
2108
2109 ;
2110 ; Exception vector filter table (like everything in this file, must be in 1st 32KB of physical memory)
2111 ;
2112
2113 .align 7
2114
2115 xcpTable:
2116 .long EatRupt ; T_IN_VAIN
2117 .long PassUpTrap ; T_RESET
2118 .long MachineCheck ; T_MACHINE_CHECK
2119 .long EXT(handlePF) ; T_DATA_ACCESS
2120 .long EXT(handlePF) ; T_INSTRUCTION_ACCESS
2121 .long PassUpRupt ; T_INTERRUPT
2122 .long EXT(AlignAssist) ; T_ALIGNMENT
2123 .long EXT(Emulate) ; T_PROGRAM
2124 .long PassUpFPU ; T_FP_UNAVAILABLE
2125 .long PassUpRupt ; T_DECREMENTER
2126 .long PassUpTrap ; T_IO_ERROR
2127 .long PassUpTrap ; T_RESERVED
2128 .long xcpSyscall ; T_SYSTEM_CALL
2129 .long PassUpTrap ; T_TRACE
2130 .long PassUpTrap ; T_FP_ASSIST
2131 .long PassUpTrap ; T_PERF_MON
2132 .long PassUpVMX ; T_VMX
2133 .long PassUpTrap ; T_INVALID_EXCP0
2134 .long PassUpTrap ; T_INVALID_EXCP1
2135 .long PassUpTrap ; T_INVALID_EXCP2
2136 .long PassUpTrap ; T_INSTRUCTION_BKPT
2137 .long PassUpRupt ; T_SYSTEM_MANAGEMENT
2138 .long EXT(AltivecAssist) ; T_ALTIVEC_ASSIST
2139 .long PassUpRupt ; T_THERMAL
2140 .long PassUpTrap ; T_INVALID_EXCP5
2141 .long PassUpTrap ; T_INVALID_EXCP6
2142 .long PassUpTrap ; T_INVALID_EXCP7
2143 .long PassUpTrap ; T_INVALID_EXCP8
2144 .long PassUpTrap ; T_INVALID_EXCP9
2145 .long PassUpTrap ; T_INVALID_EXCP10
2146 .long PassUpTrap ; T_INVALID_EXCP11
2147 .long PassUpTrap ; T_INVALID_EXCP12
2148 .long PassUpTrap ; T_INVALID_EXCP13
2149
2150 .long PassUpTrap ; T_RUNMODE_TRACE
2151
2152 .long PassUpRupt ; T_SIGP
2153 .long PassUpTrap ; T_PREEMPT
2154 .long conswtch ; T_CSWITCH
2155 .long PassUpRupt ; T_SHUTDOWN
2156 .long PassUpAbend ; T_CHOKE
2157
2158 .long EXT(handleDSeg) ; T_DATA_SEGMENT
2159 .long EXT(handleISeg) ; T_INSTRUCTION_SEGMENT
2160
2161 .long WhoaBaby ; T_SOFT_PATCH
2162 .long WhoaBaby ; T_MAINTENANCE
2163 .long WhoaBaby ; T_INSTRUMENTATION
2164 .long WhoaBaby ; T_ARCHDEP0
2165 .long EatRupt ; T_HDEC
2166 ;
2167 ; Just what the heck happened here????
2168 ; NB: also get here from UFT dispatch table, on bogus index
2169 ;
2170
2171 WhoaBaby: b . ; Open the hood and wait for help
2172
2173 .align 5
2174
2175 IgnoreRupt:
2176 lwz r20,hwIgnored(r2) ; Grab the ignored interruption count
2177 addi r20,r20,1 ; Count this one
2178 stw r20,hwIgnored(r2) ; Save the ignored count
2179 b EatRupt ; Ignore it...
2180
2181
2182
2183 ;
2184 ; System call
2185 ;
2186
2187 .align 5
2188
2189 xcpSyscall: lis r20,hi16(EXT(shandler)) ; Assume this is a normal one, get handler address
2190 rlwinm r6,r0,1,0,31 ; Move sign bit to the end
2191 ori r20,r20,lo16(EXT(shandler)) ; Assume this is a normal one, get handler address
2192 bnl++ cr0,PassUp ; R0 not 0b10xxx...x, can not be any kind of magical system call, just pass it up...
2193 lwz r7,savesrr1+4(r13) ; Get the entering MSR (low half)
2194 lwz r1,dgFlags(0) ; Get the flags
2195 cmplwi cr2,r6,1 ; See if original R0 had the CutTrace request code in it
2196
2197 rlwinm. r7,r7,0,MSR_PR_BIT,MSR_PR_BIT ; Did we come from user state?
2198 beq++ FCisok ; From supervisor state...
2199
2200 rlwinm. r1,r1,0,enaUsrFCallb,enaUsrFCallb ; Are they valid?
2201 beq++ PassUp ; No, treat as a normal one...
2202
2203 FCisok: beq++ cr2,EatRupt ; This is a CutTrace system call, we are done with it...
2204
2205 ;
2206 ; Here is where we call the firmware. If it returns T_IN_VAIN, that means
2207 ; that it has handled the interruption. Remember: thou shalt not trash R13
2208 ; while you are away. Anything else is ok.
2209 ;
2210
2211 lwz r3,saver3+4(r13) ; Restore the first parameter
2212 b EXT(FirmwareCall) ; Go handle the firmware call....
2213
2214 ;
2215 ; Here is where we return from the firmware call
2216 ;
2217
2218 .align 5
2219 .globl EXT(FCReturn)
2220
2221 LEXT(FCReturn)
2222 cmplwi r3,T_IN_VAIN ; Was it handled?
2223 beq++ EatRupt ; Interrupt was handled...
2224 mr r11,r3 ; Put the rupt code into the right register
2225 b Redrive ; Go through the filter again...
2226
2227
2228 ;
2229 ; Here is where we return from the PTE miss and segment exception handler
2230 ;
2231
2232 .align 5
2233 .globl EXT(PFSExit)
2234
2235 LEXT(PFSExit)
2236
2237 #if 0
2238 mfsprg r2,0 ; (BRINGUP)
2239 lwz r0,savedsisr(r13) ; (BRINGUP)
2240 andis. r0,r0,hi16(dsiAC) ; (BRINGUP)
2241 beq++ didnthit ; (BRINGUP)
2242 lwz r0,20(0) ; (BRINGUP)
2243 mr. r0,r0 ; (BRINGUP)
2244 bne-- didnthit ; (BRINGUP)
2245 #if 0
2246 li r0,1 ; (BRINGUP)
2247 stw r0,20(0) ; (BRINGUP)
2248 lis r0,hi16(Choke) ; (BRINGUP)
2249 ori r0,r0,lo16(Choke) ; (BRINGUP)
2250 sc ; (BRINGUP)
2251 #endif
2252
2253 lwz r4,savesrr0+4(r13) ; (BRINGUP)
2254 lwz r8,savesrr1+4(r13) ; (BRINGUP)
2255 lwz r6,savedar+4(r13) ; (BRINGUP)
2256 rlwinm. r0,r8,0,MSR_IR_BIT,MSR_IR_BIT ; (BRINGUP)
2257 mfmsr r9 ; (BRINGUP)
2258 ori r0,r9,lo16(MASK(MSR_DR)) ; (BRINGUP)
2259 beq-- hghg ; (BRINGUP)
2260 mtmsr r0 ; (BRINGUP)
2261 isync ; (BRINGUP)
2262
2263 hghg: lwz r5,0(r4) ; (BRINGUP)
2264 beq-- hghg1 ; (BRINGUP)
2265 mtmsr r9 ; (BRINGUP)
2266 isync ; (BRINGUP)
2267
2268 hghg1: rlwinm r7,r5,6,26,31 ; (BRINGUP)
2269 rlwinm r27,r5,14,24,28 ; (BRINGUP)
2270 addi r3,r13,saver0+4 ; (BRINGUP)
2271 lwzx r3,r3,r27 ; (BRINGUP)
2272
2273 #if 0
2274 lwz r27,patcharea+4(r2) ; (BRINGUP)
2275 mr. r3,r3 ; (BRINGUP)
2276 bne++ nbnbnb ; (BRINGUP)
2277 addi r27,r27,1 ; (BRINGUP)
2278 stw r27,patcharea+4(r2) ; (BRINGUP)
2279 nbnbnb:
2280 #endif
2281
2282 rlwinm. r28,r8,0,MSR_DR_BIT,MSR_DR_BIT ; (BRINGUP)
2283 rlwinm r27,r6,0,0,29 ; (BRINGUP)
2284 ori r28,r9,lo16(MASK(MSR_DR)) ; (BRINGUP)
2285 mfspr r10,dabr ; (BRINGUP)
2286 li r0,0 ; (BRINGUP)
2287 mtspr dabr,r0 ; (BRINGUP)
2288 cmplwi cr1,r7,31 ; (BRINGUP)
2289 beq-- qqq0 ; (BRINGUP)
2290 mtmsr r28 ; (BRINGUP)
2291 qqq0:
2292 isync ; (BRINGUP)
2293
2294 lwz r27,0(r27) ; (BRINGUP) - Get original value
2295
2296 bne cr1,qqq1 ; (BRINGUP)
2297
2298 rlwinm r5,r5,31,22,31 ; (BRINGUP)
2299 cmplwi cr1,r5,151 ; (BRINGUP)
2300 beq cr1,qqq3 ; (BRINGUP)
2301 cmplwi cr1,r5,407 ; (BRINGUP)
2302 beq cr1,qqq2 ; (BRINGUP)
2303 cmplwi cr1,r5,215 ; (BRINGUP)
2304 beq cr1,qqq0q ; (BRINGUP)
2305 cmplwi cr1,r5,1014 ; (BRINGUP)
2306 beq cr1,qqqm1 ; (BRINGUP)
2307
2308 lis r0,hi16(Choke) ; (BRINGUP)
2309 ori r0,r0,lo16(Choke) ; (BRINGUP)
2310 sc ; (BRINGUP)
2311
2312 qqqm1: rlwinm r7,r6,0,0,26 ; (BRINGUP)
2313 stw r0,0(r7) ; (BRINGUP)
2314 stw r0,4(r7) ; (BRINGUP)
2315 stw r0,8(r7) ; (BRINGUP)
2316 stw r0,12(r7) ; (BRINGUP)
2317 stw r0,16(r7) ; (BRINGUP)
2318 stw r0,20(r7) ; (BRINGUP)
2319 stw r0,24(r7) ; (BRINGUP)
2320 stw r0,28(r7) ; (BRINGUP)
2321 b qqq9
2322
2323 qqq1: cmplwi r7,38 ; (BRINGUP)
2324 bgt qqq2 ; (BRINGUP)
2325 blt qqq3 ; (BRINGUP)
2326
2327 qqq0q: stb r3,0(r6) ; (BRINGUP)
2328 b qqq9 ; (BRINGUP)
2329
2330 qqq2: sth r3,0(r6) ; (BRINGUP)
2331 b qqq9 ; (BRINGUP)
2332
2333 qqq3: stw r3,0(r6) ; (BRINGUP)
2334
2335 qqq9:
2336 #if 0
2337 rlwinm r7,r6,0,0,29 ; (BRINGUP)
2338 lwz r0,0(r7) ; (BRINGUP) - Get newest value
2339 #else
2340 lis r7,hi16(0x000792B8) ; (BRINGUP)
2341 ori r7,r7,lo16(0x000792B8) ; (BRINGUP)
2342 lwz r0,0(r7) ; (BRINGUP) - Get newest value
2343 #endif
2344 mtmsr r9 ; (BRINGUP)
2345 mtspr dabr,r10 ; (BRINGUP)
2346 isync ; (BRINGUP)
2347
2348 #if 0
2349 lwz r28,patcharea+12(r2) ; (BRINGUP)
2350 mr. r28,r28 ; (BRINGUP)
2351 bne++ qqq12 ; (BRINGUP)
2352 lis r28,0x4000 ; (BRINGUP)
2353
2354 qqq12: stw r27,0(r28) ; (BRINGUP)
2355 lwz r6,savedar+4(r13) ; (BRINGUP)
2356 stw r0,4(r28) ; (BRINGUP)
2357 stw r4,8(r28) ; (BRINGUP)
2358 stw r6,12(r28) ; (BRINGUP)
2359 addi r28,r28,16 ; (BRINGUP)
2360 mr. r3,r3 ; (BRINGUP)
2361 stw r28,patcharea+12(r2) ; (BRINGUP)
2362 lwz r10,patcharea+8(r2) ; (BRINGUP)
2363 lwz r0,patcharea+4(r2) ; (BRINGUP)
2364 #endif
2365
2366 #if 1
2367 stw r0,patcharea(r2) ; (BRINGUP)
2368 #endif
2369
2370 #if 0
2371 xor r28,r0,r27 ; (BRINGUP) - See how much it changed
2372 rlwinm r28,r28,24,24,31 ; (BRINGUP)
2373 cmplwi r28,1 ; (BRINGUP)
2374
2375 ble++ qqq10 ; (BRINGUP)
2376
2377 mr r7,r0 ; (BRINGUP)
2378 li r0,1 ; (BRINGUP)
2379 stw r0,20(0) ; (BRINGUP)
2380 lis r0,hi16(Choke) ; (BRINGUP)
2381 ori r0,r0,lo16(Choke) ; (BRINGUP)
2382 sc ; (BRINGUP)
2383 #endif
2384
2385
2386 qqq10: addi r4,r4,4 ; (BRINGUP)
2387 stw r4,savesrr0+4(r13) ; (BRINGUP)
2388
2389 li r11,T_IN_VAIN ; (BRINGUP)
2390 b EatRupt ; (BRINGUP)
2391
2392 didnthit: ; (BRINGUP)
2393 #endif
2394 #if 0
2395 lwz r0,20(0) ; (BRINGUP)
2396 mr. r0,r0 ; (BRINGUP)
2397 beq++ opopop ; (BRINGUP)
2398 li r0,0 ; (BRINGUP)
2399 stw r0,20(0) ; (BRINGUP)
2400 lis r0,hi16(Choke) ; (BRINGUP)
2401 ori r0,r0,lo16(Choke) ; (BRINGUP)
2402 sc ; (BRINGUP)
2403 opopop:
2404 #endif
2405 lwz r0,savesrr1+4(r13) ; Get the MSR in use at exception time
2406 cmplwi cr1,r11,T_IN_VAIN ; Was it handled?
2407 rlwinm. r4,r0,0,MSR_PR_BIT,MSR_PR_BIT ; Are we trapping from supervisor state?
2408 beq++ cr1,EatRupt ; Yeah, just blast back to the user...
2409 beq-- NoFamPf
2410 mfsprg r2,0 ; Get back per_proc
2411 lwz r1,spcFlags(r2) ; Load spcFlags
2412 rlwinm r1,r1,1+FamVMmodebit,30,31 ; Extract FamVMenabit and FamVMmodebit
2413 cmpi cr0,r1,2 ; Check FamVMena set without FamVMmode
2414 bne-- cr0,NoFamPf
2415 lwz r6,FAMintercept(r2) ; Load exceptions mask to intercept
2416 li r5,0 ; Clear
2417 srwi r1,r11,2 ; divide r11 by 4
2418 oris r5,r5,0x8000 ; Set r5 to 0x80000000
2419 srw r1,r5,r1 ; Set bit for current exception
2420 and. r1,r1,r6 ; And current exception with the intercept mask
2421 beq++ NoFamPf ; Is it FAM intercept
2422 bl EXT(vmm_fam_pf)
2423 b EatRupt
2424
2425 NoFamPf: andi. r4,r0,lo16(MASK(MSR_RI)) ; See if the recover bit is on
2426 lis r0,0x8000 ; Get 0xFFFFFFFF80000000
2427 add r0,r0,r0 ; Get 0xFFFFFFFF00000000
2428 beq++ PassUpTrap ; Not on, normal case...
2429 ;
2430 ; Here is where we handle the "recovery mode" stuff.
2431 ; This is set by an emulation routine to trap any faults when it is fetching data or
2432 ; instructions.
2433 ;
2434 ; If we get a fault, we turn off RI, set CR0_EQ to false, bump the PC, and set R0
2435 ; and R1 to the DAR and DSISR, respectively.
2436 ;
2437 lwz r3,savesrr0(r13) ; Get the failing instruction address
2438 lwz r4,savesrr0+4(r13) ; Get the failing instruction address
2439 lwz r5,savecr(r13) ; Get the condition register
2440 or r4,r4,r0 ; Fill the high part with foxes
2441 lwz r0,savedar(r13) ; Get the DAR
2442 addic r4,r4,4 ; Skip failing instruction
2443 lwz r6,savedar+4(r13) ; Get the DAR
2444 addze r3,r3 ; Propagate carry
2445 rlwinm r5,r5,0,3,1 ; Clear CR0_EQ to let emulation code know we failed
2446 lwz r7,savedsisr(r13) ; Grab the DSISR
2447 stw r3,savesrr0(r13) ; Save resume address
2448 stw r4,savesrr0+4(r13) ; Save resume address
2449 stw r5,savecr(r13) ; And the resume CR
2450 stw r0,saver0(r13) ; Pass back the DAR
2451 stw r6,saver0+4(r13) ; Pass back the DAR
2452 stw r7,saver1+4(r13) ; Pass back the DSISR
2453 b EatRupt ; Resume emulated code
2454
2455 ;
2456 ; Here is where we handle the context switch firmware call. The old
2457 ; context has been saved. The new savearea is in kind of hokey, the high order
2458 ; half is stored in saver7 and the low half is in saver3. We will just
2459 ; muck around with the savearea pointers, and then join the exit routine
2460 ;
2461
2462 .align 5
2463
2464 conswtch:
2465 li r0,0xFFF ; Get page boundary
2466 mr r29,r13 ; Save the save
2467 andc r30,r13,r0 ; Round down to page boundary (64-bit safe)
2468 lwz r5,saver3+4(r13) ; Switch to the new savearea
2469 bf-- pf64Bitb,xcswNo64 ; Not 64-bit...
2470 lwz r6,saver7+4(r13) ; Get the high order half
2471 sldi r6,r6,32 ; Position high half
2472 or r5,r5,r6 ; Merge them
2473
2474 xcswNo64: lwz r30,SACvrswap+4(r30) ; get real to virtual translation
2475 mr r13,r5 ; Switch saveareas
2476 li r0,0 ; Clear this
2477 xor r27,r29,r30 ; Flip to virtual
2478 stw r0,saver3(r5) ; Push the new virtual savearea to the switch to routine
2479 stw r27,saver3+4(r5) ; Push the new virtual savearea to the switch to routine
2480 b EatRupt ; Start it up...
2481
2482 ;
2483 ; Handle machine check here.
2484 ;
2485 ; ?
2486 ;
2487
2488 .align 5
2489
2490 MachineCheck:
2491
2492 bt++ pf64Bitb,mck64 ; ?
2493
2494 lwz r27,savesrr1+4(r13) ; Pick up srr1
2495
2496 ;
2497 ; Check if the failure was in
2498 ; ml_probe_read. If so, this is expected, so modify the PC to
2499 ; ml_proble_read_mck and then eat the exception.
2500 ;
2501 lwz r30,savesrr0+4(r13) ; Get the failing PC
2502 lis r28,hi16(EXT(ml_probe_read_mck)) ; High order part
2503 lis r27,hi16(EXT(ml_probe_read)) ; High order part
2504 ori r28,r28,lo16(EXT(ml_probe_read_mck)) ; Get the low part
2505 ori r27,r27,lo16(EXT(ml_probe_read)) ; Get the low part
2506 cmplw r30,r28 ; Check highest possible
2507 cmplw cr1,r30,r27 ; Check lowest
2508 bge- PassUpTrap ; Outside of range
2509 blt- cr1,PassUpTrap ; Outside of range
2510 ;
2511 ; We need to fix up the BATs here because the probe
2512 ; routine messed them all up... As long as we are at it,
2513 ; fix up to return directly to caller of probe.
2514 ;
2515
2516 lis r11,hi16(EXT(shadow_BAT)+shdDBAT) ; Get shadow address
2517 ori r11,r11,lo16(EXT(shadow_BAT)+shdDBAT) ; Get shadow address
2518
2519 lwz r30,0(r11) ; Pick up DBAT 0 high
2520 lwz r28,4(r11) ; Pick up DBAT 0 low
2521 lwz r27,8(r11) ; Pick up DBAT 1 high
2522 lwz r18,16(r11) ; Pick up DBAT 2 high
2523 lwz r11,24(r11) ; Pick up DBAT 3 high
2524
2525 sync
2526 mtdbatu 0,r30 ; Restore DBAT 0 high
2527 mtdbatl 0,r28 ; Restore DBAT 0 low
2528 mtdbatu 1,r27 ; Restore DBAT 1 high
2529 mtdbatu 2,r18 ; Restore DBAT 2 high
2530 mtdbatu 3,r11 ; Restore DBAT 3 high
2531 sync
2532
2533 lwz r28,savelr+4(r13) ; Get return point
2534 lwz r27,saver0+4(r13) ; Get the saved MSR
2535 li r30,0 ; Get a failure RC
2536 stw r28,savesrr0+4(r13) ; Set the return point
2537 stw r27,savesrr1+4(r13) ; Set the continued MSR
2538 stw r30,saver3+4(r13) ; Set return code
2539 b EatRupt ; Yum, yum, eat it all up...
2540
2541 ;
2542 ; 64-bit machine checks
2543 ;
2544
2545 mck64:
2546
2547 ;
2548 ; NOTE: WE NEED TO RETHINK RECOVERABILITY A BIT - radar 3167190
2549 ;
2550
2551 ld r23,savesrr0(r13) ; Grab the SRR0 in case we need bad instruction
2552 ld r20,savesrr1(r13) ; Grab the SRR1 so we can decode the thing
2553 lwz r21,savedsisr(r13) ; We might need this in a bit
2554 ld r22,savedar(r13) ; We might need this in a bit
2555
2556 lis r8,AsyMCKSrc ; Get the Async MCK Source register address
2557 mfsprg r19,2 ; Get the feature flags
2558 ori r8,r8,0x8000 ; Set to read data
2559 rlwinm. r0,r19,0,pfSCOMFixUpb,pfSCOMFixUpb ; Do we need to fix the SCOM data?
2560
2561 sync
2562
2563 mtspr scomc,r8 ; Request the MCK source
2564 mfspr r24,scomd ; Get the source
2565 mfspr r8,scomc ; Get back the status (we just ignore it)
2566 sync
2567 isync
2568
2569 lis r8,AsyMCKRSrc ; Get the Async MCK Source AND mask address
2570 li r9,0 ; Get and AND mask of 0
2571
2572 sync
2573
2574 mtspr scomd,r9 ; Set the AND mask to 0
2575 mtspr scomc,r8 ; Write the AND mask and clear conditions
2576 mfspr r8,scomc ; Get back the status (we just ignore it)
2577 sync
2578 isync
2579
2580 lis r8,cFIR ; Get the Core FIR register address
2581 ori r8,r8,0x8000 ; Set to read data
2582
2583 sync
2584
2585 mtspr scomc,r8 ; Request the Core FIR
2586 mfspr r25,scomd ; Get the source
2587 mfspr r8,scomc ; Get back the status (we just ignore it)
2588 sync
2589 isync
2590
2591 lis r8,cFIRrst ; Get the Core FIR AND mask address
2592
2593 sync
2594
2595 mtspr scomd,r9 ; Set the AND mask to 0
2596 mtspr scomc,r8 ; Write the AND mask and clear conditions
2597 mfspr r8,scomc ; Get back the status (we just ignore it)
2598 sync
2599 isync
2600
2601 lis r8,l2FIR ; Get the L2 FIR register address
2602 ori r8,r8,0x8000 ; Set to read data
2603
2604 sync
2605
2606 mtspr scomc,r8 ; Request the L2 FIR
2607 mfspr r26,scomd ; Get the source
2608 mfspr r8,scomc ; Get back the status (we just ignore it)
2609 sync
2610 isync
2611
2612 lis r8,l2FIRrst ; Get the L2 FIR AND mask address
2613
2614 sync
2615
2616 mtspr scomd,r9 ; Set the AND mask to 0
2617 mtspr scomc,r8 ; Write the AND mask and clear conditions
2618 mfspr r8,scomc ; Get back the status (we just ignore it)
2619 sync
2620 isync
2621
2622 lis r8,busFIR ; Get the Bus FIR register address
2623 ori r8,r8,0x8000 ; Set to read data
2624
2625 sync
2626
2627 mtspr scomc,r8 ; Request the Bus FIR
2628 mfspr r27,scomd ; Get the source
2629 mfspr r8,scomc ; Get back the status (we just ignore it)
2630 sync
2631 isync
2632
2633 lis r8,busFIRrst ; Get the Bus FIR AND mask address
2634
2635 sync
2636
2637 mtspr scomd,r9 ; Set the AND mask to 0
2638 mtspr scomc,r8 ; Write the AND mask and clear conditions
2639 mfspr r8,scomc ; Get back the status (we just ignore it)
2640 sync
2641 isync
2642
2643 ; Note: bug in early chips where scom reads are shifted right by 1. We fix that here.
2644 ; Also note that we will lose bit 63
2645
2646 beq++ mckNoFix ; No fix up is needed
2647 sldi r24,r24,1 ; Shift left 1
2648 sldi r25,r25,1 ; Shift left 1
2649 sldi r26,r26,1 ; Shift left 1
2650 sldi r27,r27,1 ; Shift left 1
2651
2652 mckNoFix: std r24,savexdat0(r13) ; Save the MCK source in case we pass the error
2653 std r25,savexdat1(r13) ; Save the Core FIR in case we pass the error
2654 std r26,savexdat2(r13) ; Save the L2 FIR in case we pass the error
2655 std r27,savexdat3(r13) ; Save the BUS FIR in case we pass the error
2656
2657 rlwinm. r0,r20,0,mckIFUE-32,mckIFUE-32 ; Is this some kind of uncorrectable?
2658 bne mckUE ; Yeah...
2659
2660 rlwinm. r0,r20,0,mckLDST-32,mckLDST-32 ; Some kind of load/store error?
2661 bne mckHandleLDST ; Yes...
2662
2663 rldicl. r0,r20,46,62 ; Get the error cause code
2664 beq mckNotSure ; We need some more checks for this one...
2665
2666 cmplwi r0,2 ; Check for TLB parity error
2667 blt mckSLBparity ; This is an SLB parity error...
2668 bgt mckhIFUE ; This is an IFetch tablewalk reload UE...
2669
2670 ; IFetch TLB parity error
2671
2672 isync
2673 tlbiel r23 ; Locally invalidate TLB entry for iaddr
2674 sync ; Wait for it
2675 b ceMck ; All recovered...
2676
2677 ; SLB parity error. This could be software caused. We get one if there is
2678 ; more than 1 valid SLBE with a matching ESID. That one we do not want to
2679 ; try to recover from. Search for it and if we get it, panic.
2680
2681 mckSLBparity:
2682 crclr cr0_eq ; Make sure we are not equal so we take correct exit
2683
2684 la r3,emvr0(r2) ; Use this to keep track of valid ESIDs we find
2685 li r5,0 ; Start with index 0
2686
2687 mckSLBck: la r4,emvr0(r2) ; Use this to keep track of valid ESIDs we find
2688 slbmfee r6,r5 ; Get the next SLBE
2689 andis. r0,r6,0x0800 ; See if valid bit is on
2690 beq mckSLBnx ; Skip invalid and go to next
2691
2692 mckSLBck2: cmpld r4,r3 ; Have we reached the end of the table?
2693 beq mckSLBne ; Yes, go enter this one...
2694 ld r7,0(r4) ; Pick up the saved ESID
2695 cmpld r6,r7 ; Is this a match?
2696 beq mckSLBrec ; Whoops, I did bad, recover and pass up...
2697 addi r4,r4,8 ; Next table entry
2698 b mckSLBck2 ; Check the next...
2699
2700 mckSLBnx: addi r5,r5,1 ; Point to next SLBE
2701 cmplwi r5,64 ; Have we checked all of them?
2702 bne++ mckSLBck ; Not yet, check again...
2703 b mckSLBrec ; We looked at them all, go recover...
2704
2705 mckSLBne: std r6,0(r3) ; Save this ESID
2706 addi r3,r3,8 ; Point to the new slot
2707 b mckSLBnx ; Go do the next SLBE...
2708
2709 ; Recover an SLB error
2710
2711 mckSLBrec: li r0,0 ; Set an SLB slot index of 0
2712 slbia ; Trash all SLB entries (except for entry 0 that is)
2713 slbmfee r7,r0 ; Get the entry that is in SLB index 0
2714 rldicr r7,r7,0,35 ; Clear the valid bit and the rest
2715 slbie r7 ; Invalidate it
2716
2717 li r3,0 ; Set the first SLBE
2718
2719 mckSLBclr: slbmte r0,r3 ; Clear the whole entry to 0s
2720 addi r3,r3,1 ; Bump index
2721 cmplwi cr1,r3,64 ; Have we done them all?
2722 bne++ cr1,mckSLBclr ; Yup....
2723
2724 sth r3,ppInvSeg(r2) ; Store non-zero to trigger SLB reload
2725 bne++ ceMck ; This was not a programming error, all recovered...
2726 b ueMck ; Pass the software error up...
2727
2728 ;
2729 ; Handle a load/store unit error. We need to decode the DSISR
2730 ;
2731
2732 mckHandleLDST:
2733 rlwinm. r0,r21,0,mckL1DCPE,mckL1DCPE ; An L1 data cache parity error?
2734 bne++ mckL1D ; Yeah, we dealt with this back in the vector...
2735
2736 rlwinm. r0,r21,0,mckL1DTPE,mckL1DTPE ; An L1 tag error?
2737 bne++ mckL1T ; Yeah, we dealt with this back in the vector...
2738
2739 rlwinm. r0,r21,0,mckUEdfr,mckUEdfr ; Is the a "deferred" UE?
2740 bne mckDUE ; Yeah, go see if expected...
2741
2742 rlwinm. r0,r21,0,mckUETwDfr,mckUETwDfr ; Is the a "deferred" tablewalk UE?
2743 bne mckDTW ; Yeah, no recovery...
2744
2745 rlwinm. r0,r21,0,mckSLBPE,mckSLBPE ; SLB parity error?
2746 bne mckSLBparity ; Yeah, go attempt recovery....
2747
2748 ; This is a recoverable D-ERAT or TLB error
2749
2750 la r9,hwMckERCPE(r2) ; Get DERAT parity error count
2751
2752 mckInvDAR: isync
2753 tlbiel r22 ; Locally invalidate the TLB entry
2754 sync
2755
2756 lwz r21,0(r9) ; Get count
2757 addi r21,r21,1 ; Count this one
2758 stw r21,0(r9) ; Stick it back
2759
2760 b ceMck ; All recovered...
2761
2762 ;
2763 ; When we come here, we are not quite sure what the error is. We need to
2764 ; dig a bit further.
2765 ;
2766 ; R24 is interrupt source
2767 ; R25 is Core FIR
2768 ;
2769 ; Note that both have been cleared already.
2770 ;
2771
2772 mckNotSure:
2773 rldicl. r0,r24,AsyMCKfir+1,63 ; Something in the FIR?
2774 bne-- mckFIR ; Yup, go check some more...
2775
2776 rldicl. r0,r24,AsyMCKhri+1,63 ; Hang recovery?
2777 bne-- mckHangRcvr ; Yup...
2778
2779 rldicl. r0,r24,AsyMCKext+1,63 ; External signal?
2780 bne-- mckExtMck ; Yup...
2781
2782 ;
2783 ; We really do not know what this one is or what to do with it...
2784 ;
2785
2786 mckUnk: lwz r21,hwMckUnk(r2) ; Get unknown error count
2787 addi r21,r21,1 ; Count it
2788 stw r21,hwMckUnk(r2) ; Stuff it
2789 b ueMck ; Go south, young man...
2790
2791 ;
2792 ; Hang recovery. This is just a notification so we only count.
2793 ;
2794
2795 mckHangRcrvr:
2796 lwz r21,hwMckHang(r2) ; Get hang recovery count
2797 addi r21,r21,1 ; Count this one
2798 stw r21,hwMckHang(r2) ; Stick it back
2799 b ceMck ; All recovered...
2800
2801 ;
2802 ; Externally signaled MCK. No recovery for the moment, but we this may be
2803 ; where we handle ml_probe_read problems eventually.
2804 ;
2805 mckExtMck:
2806 lwz r21,hwMckHang(r2) ; Get hang recovery count
2807 addi r21,r21,1 ; Count this one
2808 stw r21,hwMckHang(r2) ; Stick it back
2809 b ceMck ; All recovered...
2810
2811 ;
2812 ; Machine check cause is in a FIR. Suss it out here.
2813 ; Core FIR is in R25 and has been cleared in HW.
2814 ;
2815
2816 mckFIR: rldicl. r0,r25,cFIRICachePE+1,63 ; I-Cache parity error?
2817 la r19,hwMckICachePE(r2) ; Point to counter
2818 bne mckInvICache ; Go invalidate I-Cache...
2819
2820 rldicl. r0,r25,cFIRITagPE0+1,63 ; I-Cache tag parity error?
2821 la r19,hwMckITagPE(r2) ; Point to counter
2822 bne mckInvICache ; Go invalidate I-Cache...
2823
2824 rldicl. r0,r25,cFIRITagPE1+1,63 ; I-Cache tag parity error?
2825 la r19,hwMckITagPE(r2) ; Point to counter
2826 bne mckInvICache ; Go invalidate I-Cache...
2827
2828 rldicl. r0,r25,cFIRIEratPE+1,63 ; IERAT parity error?
2829 la r19,hwMckIEratPE(r2) ; Point to counter
2830 bne mckInvERAT ; Go invalidate ERATs...
2831
2832 rldicl. r0,r25,cFIRIFUL2UE+1,63 ; IFetch got L2 UE?
2833 bne mckhIFUE ; Go count and pass up...
2834
2835 rldicl. r0,r25,cFIRDCachePE+1,63 ; D-Cache PE?
2836 bne mckL1D ; Handled, just go count...
2837
2838 rldicl. r0,r25,cFIRDTagPE+1,63 ; D-Cache tag PE?
2839 bne mckL1T ; Handled, just go count...
2840
2841 rldicl. r0,r25,cFIRDEratPE+1,63 ; DERAT PE?
2842 la r19,hwMckDEratPE(r2) ; Point to counter
2843 bne mckInvERAT ; Go invalidate ERATs...
2844
2845 rldicl. r0,r25,cFIRTLBPE+1,63 ; TLB PE?
2846 la r9,hwMckTLBPE(r2) ; Get TLB parity error count
2847 bne mckInvDAR ; Go recover...
2848
2849 rldicl. r0,r25,cFIRSLBPE+1,63 ; SLB PE?
2850 bne mckSLBparity ; Cope with it...
2851
2852 b mckUnk ; Have not a clue...
2853
2854 ;
2855 ; General recovery for I-Cache errors. Just flush it completely.
2856 ;
2857
2858 .align 7 ; Force into cache line
2859
2860 mckInvICache:
2861 lis r0,0x0080 ; Get a 0x0080 (bit 9 >> 32)
2862 mfspr r21,hid1 ; Get the current HID1
2863 sldi r0,r0,32 ; Get the "forced ICBI match" bit
2864 or r0,r0,r21 ; Set forced match
2865
2866 isync
2867 mtspr hid1,r0 ; Stick it
2868 mtspr hid1,r0 ; Stick it again
2869 isync
2870
2871 li r6,0 ; Start at 0
2872
2873 mckIcbi: icbi 0,r6 ; Kill I$
2874 addi r6,r6,128 ; Next line
2875 andis. r5,r6,1 ; Have we done them all?
2876 beq++ mckIcbi ; Not yet...
2877
2878 isync
2879 mtspr hid1,r21 ; Restore original HID1
2880 mtspr hid1,r21 ; Stick it again
2881 isync
2882
2883 lwz r5,0(r19) ; Get the counter
2884 addi r5,r5,1 ; Count it
2885 stw r5,0(r19) ; Stuff it back
2886 b ceMck ; All recovered...
2887
2888
2889 ; General recovery for ERAT problems - handled in exception vector already
2890
2891 mckInvERAT: lwz r21,0(r19) ; Get the exception count spot
2892 addi r21,r21,1 ; Count this one
2893 stw r21,0(r19) ; Save count
2894 b ceMck ; All recovered...
2895
2896 ; General hang recovery - this is a notification only, just count.
2897
2898 mckHangRcvr:
2899 lwz r21,hwMckHang(r2) ; Get hang recovery count
2900 addi r21,r21,1 ; Count this one
2901 stw r21,hwMckHang(r2) ; Stick it back
2902 b ceMck ; All recovered...
2903
2904
2905 ;
2906 ; These are the uncorrectable errors, just count them then pass it along.
2907 ;
2908
2909 mckUE: lwz r21,hwMckUE(r2) ; Get general uncorrectable error count
2910 addi r21,r21,1 ; Count it
2911 stw r21,hwMckUE(r2) ; Stuff it
2912 b ueMck ; Go south, young man...
2913
2914 mckhIFUE: lwz r21,hwMckIUEr(r2) ; Get I-Fetch TLB reload uncorrectable error count
2915 addi r21,r21,1 ; Count it
2916 stw r21,hwMckIUEr(r2) ; Stuff it
2917 b ueMck ; Go south, young man...
2918
2919 mckDUE: lwz r21,hwMckDUE(r2) ; Get deferred uncorrectable error count
2920 addi r21,r21,1 ; Count it
2921 stw r21,hwMckDUE(r2) ; Stuff it
2922
2923 ;
2924 ; Right here is where we end up after a failure on a ml_probe_read_64.
2925 ; We will check if that is the case, and if so, fix everything up and
2926 ; return from it.
2927
2928 lis r8,hi16(EXT(ml_probe_read_64)) ; High of start
2929 lis r9,hi16(EXT(ml_probe_read_mck_64)) ; High of end
2930 ori r8,r8,lo16(EXT(ml_probe_read_64)) ; Low of start
2931 ori r9,r9,lo16(EXT(ml_probe_read_mck_64)) ; Low of end
2932 cmpld r23,r8 ; Too soon?
2933 cmpld cr1,r23,r9 ; Too late?
2934
2935 cror cr0_lt,cr0_lt,cr1_gt ; Too soon or too late?
2936 ld r3,saver12(r13) ; Get the original MSR
2937 ld r5,savelr(r13) ; Get the return address
2938 li r4,0 ; Get fail code
2939 blt-- ueMck ; This is a normal machine check, just pass up...
2940 std r5,savesrr0(r13) ; Set the return MSR
2941
2942 std r3,savesrr1(r13) ; Set the return address
2943 std r4,saver3(r13) ; Set failure return code
2944 b ceMck ; All recovered...
2945
2946 mckDTW: lwz r21,hwMckDTW(r2) ; Get deferred tablewalk uncorrectable error count
2947 addi r21,r21,1 ; Count it
2948 stw r21,hwMckDTW(r2) ; Stuff it
2949 b ueMck ; Go south, young man...
2950
2951 mckL1D: lwz r21,hwMckL1DPE(r2) ; Get data cache parity error count
2952 addi r21,r21,1 ; Count it
2953 stw r21,hwMckL1DPE(r2) ; Stuff it
2954 b ceMck ; All recovered...
2955
2956 mckL1T: lwz r21,hwMckL1TPE(r2) ; Get TLB parity error count
2957 addi r21,r21,1 ; Count it
2958 stw r21,hwMckL1TPE(r2) ; Stuff it
2959
2960 ceMck: lwz r21,mckFlags(0) ; Get the flags
2961 li r0,1 ; Set the recovered flag before passing up
2962 rlwinm. r21,r21,0,31,31 ; Check if we want to log recoverables
2963 stw r0,savemisc3(r13) ; Set it
2964 beq++ EatRupt ; No log of recoverables wanted...
2965 b PassUpTrap ; Go up and log error...
2966
2967 ueMck: li r0,0 ; Set the unrecovered flag before passing up
2968 stw r0,savemisc3(r13) ; Set it
2969 b PassUpTrap ; Go up and log error and probably panic
2970
2971
2972 /*
2973 * Here's where we come back from some instruction emulator. If we come back with
2974 * T_IN_VAIN, the emulation is done and we should just reload state and directly
2975 * go back to the interrupted code. Otherwise, we'll check to see if
2976 * we need to redrive with a different interrupt, i.e., DSI.
2977 * Note that this we are actually not redriving the rupt, rather changing it
2978 * into a different one. Thus we clear the redrive bit.
2979 */
2980
2981 .align 5
2982 .globl EXT(EmulExit)
2983
2984 LEXT(EmulExit)
2985
2986 cmplwi cr1,r11,T_IN_VAIN ; Was it emulated?
2987 lis r1,hi16(SAVredrive) ; Get redrive request
2988 beq++ cr1,EatRupt ; Yeah, just blast back to the user...
2989 lwz r4,SAVflags(r13) ; Pick up the flags
2990
2991 and. r0,r4,r1 ; Check if redrive requested
2992
2993 beq++ PassUpTrap ; No redrive, just keep on going...
2994
2995 b Redrive ; Redrive the exception...
2996
2997 ;
2998 ; Jump into main handler code switching on VM at the same time.
2999 ;
3000 ; We assume kernel data is mapped contiguously in physical
3001 ; memory, otherwise we would need to switch on (at least) virtual data.
3002 ; SRs are already set up.
3003 ;
3004
3005 .align 5
3006
3007 PassUpTrap: lis r20,hi16(EXT(thandler)) ; Get thandler address
3008 ori r20,r20,lo16(EXT(thandler)) ; Get thandler address
3009 b PassUp ; Go pass it up...
3010
3011 PassUpRupt: lis r20,hi16(EXT(ihandler)) ; Get ihandler address
3012 ori r20,r20,lo16(EXT(ihandler)) ; Get ihandler address
3013 b PassUp ; Go pass it up...
3014
3015 .align 5
3016
3017 PassUpFPU: lis r20,hi16(EXT(fpu_switch)) ; Get FPU switcher address
3018 ori r20,r20,lo16(EXT(fpu_switch)) ; Get FPU switcher address
3019 b PassUp ; Go pass it up...
3020
3021 PassUpVMX: lis r20,hi16(EXT(vec_switch)) ; Get VMX switcher address
3022 ori r20,r20,lo16(EXT(vec_switch)) ; Get VMX switcher address
3023 bt++ featAltivec,PassUp ; We have VMX on this CPU...
3024 li r11,T_PROGRAM ; Say that it is a program exception
3025 li r20,8 ; Set invalid instruction
3026 stw r11,saveexception(r13) ; Set the new the exception code
3027 sth r20,savesrr1+4(r13) ; Set the invalid instruction SRR code
3028
3029 b PassUpTrap ; Go pass it up...
3030
3031 .align 5
3032
3033 PassUpAbend:
3034 lis r20,hi16(EXT(chandler)) ; Get choke handler address
3035 ori r20,r20,lo16(EXT(chandler)) ; Get choke handler address
3036 b PassUp ; Go pass it up...
3037
3038 .align 5
3039
3040 PassUp:
3041 #if INSTRUMENT
3042 mfspr r29,pmc1 ; INSTRUMENT - saveinstr[11] - Take stamp at passup or eatrupt
3043 stw r29,0x6100+(11*16)+0x0(0) ; INSTRUMENT - Save it
3044 mfspr r29,pmc2 ; INSTRUMENT - Get stamp
3045 stw r29,0x6100+(11*16)+0x4(0) ; INSTRUMENT - Save it
3046 mfspr r29,pmc3 ; INSTRUMENT - Get stamp
3047 stw r29,0x6100+(11*16)+0x8(0) ; INSTRUMENT - Save it
3048 mfspr r29,pmc4 ; INSTRUMENT - Get stamp
3049 stw r29,0x6100+(11*16)+0xC(0) ; INSTRUMENT - Save it
3050 #endif
3051
3052 lwz r10,SAVflags(r13) ; Pick up the flags
3053
3054 li r0,0xFFF ; Get a page mask
3055 li r2,MASK(MSR_BE)|MASK(MSR_SE) ; Get the mask to save trace bits
3056 andc r5,r13,r0 ; Back off to the start of savearea block
3057 mfmsr r3 ; Get our MSR
3058 rlwinm r10,r10,0,SAVredriveb+1,SAVredriveb-1 ; Clear the redrive before we pass it up
3059 li r21,MSR_SUPERVISOR_INT_OFF ; Get our normal MSR value
3060 and r3,r3,r2 ; Clear all but trace
3061 lwz r5,SACvrswap+4(r5) ; Get real to virtual conversion
3062 or r21,r21,r3 ; Keep the trace bits if they are on
3063 stw r10,SAVflags(r13) ; Set the flags with the cleared redrive flag
3064
3065 xor r4,r13,r5 ; Pass up the virtual address of context savearea
3066 mfsprg r29,0 ; Get the per_proc block back
3067 rlwinm r4,r4,0,0,31 ; Clean top half of virtual savearea if 64-bit
3068
3069 mr r3,r21 ; Pass in the MSR we will go to
3070 bl EXT(switchSegs) ; Go handle the segment registers/STB
3071
3072 #if INSTRUMENT
3073 mfspr r30,pmc1 ; INSTRUMENT - saveinstr[7] - Take stamp afer switchsegs
3074 stw r30,0x6100+(7*16)+0x0(0) ; INSTRUMENT - Save it
3075 mfspr r30,pmc2 ; INSTRUMENT - Get stamp
3076 stw r30,0x6100+(7*16)+0x4(0) ; INSTRUMENT - Save it
3077 mfspr r30,pmc3 ; INSTRUMENT - Get stamp
3078 stw r30,0x6100+(7*16)+0x8(0) ; INSTRUMENT - Save it
3079 mfspr r30,pmc4 ; INSTRUMENT - Get stamp
3080 stw r30,0x6100+(7*16)+0xC(0) ; INSTRUMENT - Save it
3081 #endif
3082 lwz r3,saveexception(r13) ; Recall the exception code
3083
3084 mtsrr0 r20 ; Set up the handler address
3085 mtsrr1 r21 ; Set up our normal MSR value
3086
3087 bt++ pf64Bitb,puLaunch ; Handle 64-bit machine...
3088
3089 rfi ; Launch the exception handler
3090
3091 puLaunch: rfid ; Launch the exception handler
3092
3093 /*
3094 * This routine is the main place where we return from an interruption.
3095 *
3096 * This is also where we release the quickfret list. These are saveareas
3097 * that were released as part of the exception exit path in hw_exceptions.
3098 * In order to save an atomic operation (which actually will not work
3099 * properly on a 64-bit machine) we use holdQFret to indicate that the list
3100 * is in flux and should not be looked at here. This comes into play only
3101 * when we take a PTE miss when we are queuing a savearea onto qfret.
3102 * Quite rare but could happen. If the flag is set, this code does not
3103 * release the list and waits until next time.
3104 *
3105 * All we need to remember here is that R13 must point to the savearea
3106 * that has the context we need to load up. Translation and interruptions
3107 * must be disabled.
3108 *
3109 * This code always loads the context in the savearea pointed to
3110 * by R13. In the process, it throws away the savearea. If there
3111 * is any tomfoolery with savearea stacks, it must be taken care of
3112 * before we get here.
3113 *
3114 */
3115
3116 .align 5
3117
3118 EatRupt: mfsprg r29,0 ; Get the per_proc block back
3119 mr r31,r13 ; Move the savearea pointer to the far end of the register set
3120 mfsprg r27,2 ; Get the processor features
3121
3122 lwz r3,holdQFret(r29) ; Get the release hold off flag
3123
3124 bt++ pf64Bitb,eat64a ; Skip down to the 64-bit version of this
3125
3126 ;
3127 ; This starts the 32-bit version
3128 ;
3129
3130 mr. r3,r3 ; Should we hold off the quick release?
3131 lwz r30,quickfret+4(r29) ; Pick up the quick fret list, if any
3132 la r21,saver0(r31) ; Point to the first thing we restore
3133 bne- ernoqfret ; Hold off set, do not release just now...
3134
3135 erchkfret: mr. r3,r30 ; Any savearea to quickly release?
3136 beq+ ernoqfret ; No quickfrets...
3137 lwz r30,SAVprev+4(r30) ; Chain back now
3138
3139 bl EXT(save_ret_phys) ; Put it on the free list
3140 stw r30,quickfret+4(r29) ; Dequeue previous guy (really, it is ok to wait until after the release)
3141 b erchkfret ; Try the next one...
3142
3143 .align 5
3144
3145 ernoqfret:
3146 #if INSTRUMENT
3147 mfspr r30,pmc1 ; INSTRUMENT - saveinstr[5] - Take stamp at saveareas released
3148 stw r30,0x6100+(5*16)+0x0(0) ; INSTRUMENT - Save it
3149 mfspr r30,pmc2 ; INSTRUMENT - Get stamp
3150 stw r30,0x6100+(5*16)+0x4(0) ; INSTRUMENT - Save it
3151 mfspr r30,pmc3 ; INSTRUMENT - Get stamp
3152 stw r30,0x6100+(5*16)+0x8(0) ; INSTRUMENT - Save it
3153 mfspr r30,pmc4 ; INSTRUMENT - Get stamp
3154 stw r30,0x6100+(5*16)+0xC(0) ; INSTRUMENT - Save it
3155 #endif
3156
3157 dcbt 0,r21 ; Touch in the first thing we need
3158
3159 ;
3160 ; Here we release the savearea.
3161 ;
3162 ; Important!!!! The savearea is released before we are done with it. When the
3163 ; local free savearea list (anchored at lclfree) gets too long, save_ret_phys
3164 ; will trim the list, making the extra saveareas allocatable by another processor
3165 ; The code in there must ALWAYS leave our savearea on the local list, otherwise
3166 ; we could be very, very unhappy. The code there always queues the "just released"
3167 ; savearea to the head of the local list. Then, if it needs to trim, it will
3168 ; start with the SECOND savearea, leaving ours intact.
3169 ;
3170 ;
3171
3172 mr r3,r31 ; Get the exiting savearea in parm register
3173 bl EXT(save_ret_phys) ; Put it on the free list
3174 #if INSTRUMENT
3175 mfspr r3,pmc1 ; INSTRUMENT - saveinstr[6] - Take stamp afer savearea released
3176 stw r3,0x6100+(6*16)+0x0(0) ; INSTRUMENT - Save it
3177 mfspr r3,pmc2 ; INSTRUMENT - Get stamp
3178 stw r3,0x6100+(6*16)+0x4(0) ; INSTRUMENT - Save it
3179 mfspr r3,pmc3 ; INSTRUMENT - Get stamp
3180 stw r3,0x6100+(6*16)+0x8(0) ; INSTRUMENT - Save it
3181 mfspr r3,pmc4 ; INSTRUMENT - Get stamp
3182 stw r3,0x6100+(6*16)+0xC(0) ; INSTRUMENT - Save it
3183 #endif
3184
3185 lwz r3,savesrr1+4(r31) ; Pass in the MSR we are going to
3186 bl EXT(switchSegs) ; Go handle the segment registers/STB
3187 #if INSTRUMENT
3188 mfspr r30,pmc1 ; INSTRUMENT - saveinstr[10] - Take stamp afer switchsegs
3189 stw r30,0x6100+(10*16)+0x0(0) ; INSTRUMENT - Save it
3190 mfspr r30,pmc2 ; INSTRUMENT - Get stamp
3191 stw r30,0x6100+(10*16)+0x4(0) ; INSTRUMENT - Save it
3192 mfspr r30,pmc3 ; INSTRUMENT - Get stamp
3193 stw r30,0x6100+(10*16)+0x8(0) ; INSTRUMENT - Save it
3194 mfspr r30,pmc4 ; INSTRUMENT - Get stamp
3195 stw r30,0x6100+(10*16)+0xC(0) ; INSTRUMENT - Save it
3196 #endif
3197 li r3,savesrr1+4 ; Get offset to the srr1 value
3198
3199 lhz r9,PP_CPU_FLAGS(r29) ; Get the processor flags
3200 lwarx r26,r3,r31 ; Get destination MSR and take reservation along the way (just so we can blow it away)
3201
3202 rlwinm r25,r26,27,22,22 ; Move PR bit to BE
3203
3204 cmplw cr3,r14,r14 ; Set that we do not need to stop streams
3205
3206 rlwinm r9,r9,(((31-MSR_BE_BIT)+(traceBEb+16+1))&31),MSR_BE_BIT,MSR_BE_BIT ; Set BE bit if special trace is on
3207 li r21,emfp0 ; Point to the fp savearea
3208 and r9,r9,r25 ; Clear BE if supervisor state
3209 or r26,r26,r9 ; Flip on the BE bit for special trace if needed
3210 stwcx. r26,r3,r31 ; Blow away any reservations we hold (and set BE)
3211
3212 lwz r25,savesrr0+4(r31) ; Get the SRR0 to use
3213
3214 la r28,saver4(r31) ; Point to the 32-byte line with r4-r7
3215 dcbz r21,r29 ; Clear a work area
3216 lwz r0,saver0+4(r31) ; Restore R0
3217 dcbt 0,r28 ; Touch in r4-r7
3218 lwz r1,saver1+4(r31) ; Restore R1
3219 lwz r2,saver2+4(r31) ; Restore R2
3220 la r28,saver8(r31) ; Point to the 32-byte line with r8-r11
3221 lwz r3,saver3+4(r31) ; Restore R3
3222 andis. r6,r27,hi16(pfAltivec) ; Do we have altivec on the machine?
3223 dcbt 0,r28 ; touch in r8-r11
3224 lwz r4,saver4+4(r31) ; Restore R4
3225 la r28,saver12(r31) ; Point to the 32-byte line with r12-r15
3226 mtsrr0 r25 ; Restore the SRR0 now
3227 lwz r5,saver5+4(r31) ; Restore R5
3228 mtsrr1 r26 ; Restore the SRR1 now
3229 lwz r6,saver6+4(r31) ; Restore R6
3230
3231 dcbt 0,r28 ; touch in r12-r15
3232 la r28,saver16(r31)
3233
3234 lwz r7,saver7+4(r31) ; Restore R7
3235 lwz r8,saver8+4(r31) ; Restore R8
3236 lwz r9,saver9+4(r31) ; Restore R9
3237
3238 dcbt 0,r28 ; touch in r16-r19
3239 la r28,saver20(r31)
3240
3241 lwz r10,saver10+4(r31) ; Restore R10
3242 lwz r11,saver11+4(r31) ; Restore R11
3243
3244 dcbt 0,r28 ; touch in r20-r23
3245 la r28,savevscr(r31) ; Point to the status area
3246
3247 lwz r12,saver12+4(r31) ; Restore R12
3248 lwz r13,saver13+4(r31) ; Restore R13
3249
3250 la r14,savectr+4(r31)
3251 dcbt 0,r28 ; Touch in VSCR and FPSCR
3252 dcbt 0,r14 ; touch in CTR, DAR, DSISR, VRSAVE, and Exception code
3253
3254 lwz r26,next_savearea+4(r29) ; Get the exception save area
3255 la r28,saver24(r31)
3256
3257 lwz r14,saver14+4(r31) ; Restore R14
3258 lwz r15,saver15+4(r31) ; Restore R15
3259
3260
3261 stfd f0,emfp0(r29) ; Save FP0
3262 lwz r27,savevrsave(r31) ; Get the vrsave
3263 dcbt 0,r28 ; touch in r24-r27
3264 la r28,savevscr(r31) ; Point to the status area
3265 lfd f0,savefpscrpad(r31) ; Get the fpscr
3266 la r22,saver28(r31)
3267 mtfsf 0xFF,f0 ; Restore fpscr
3268 lfd f0,emfp0(r29) ; Restore the used register
3269
3270 beq noavec3 ; No Altivec on this CPU...
3271
3272 stvxl v0,r21,r29 ; Save a vector register
3273 lvxl v0,0,r28 ; Get the vector status
3274 mtspr vrsave,r27 ; Set the vrsave
3275 mtvscr v0 ; Set the vector status
3276 lvxl v0,r21,r29 ; Restore work vector register
3277
3278 noavec3: dcbt 0,r22 ; touch in r28-r31
3279
3280 lwz r23,spcFlags(r29) ; Get the special flags from per_proc
3281 la r17,savesrr0(r31)
3282 la r26,saver0(r26) ; Point to the first part of the next savearea
3283 dcbt 0,r17 ; touch in SRR0, SRR1, CR, XER, LR
3284 lhz r28,pfrptdProc(r29) ; Get the reported processor type
3285
3286 lwz r16,saver16+4(r31) ; Restore R16
3287 lwz r17,saver17+4(r31) ; Restore R17
3288 lwz r18,saver18+4(r31) ; Restore R18
3289 lwz r19,saver19+4(r31) ; Restore R19
3290 lwz r20,saver20+4(r31) ; Restore R20
3291 lwz r21,saver21+4(r31) ; Restore R21
3292 lwz r22,saver22+4(r31) ; Restore R22
3293
3294 cmpwi cr1,r28,CPU_SUBTYPE_POWERPC_750 ; G3?
3295
3296 dcbz 0,r26 ; Clear and allocate next savearea we use in the off chance it is still in when we next interrupt
3297
3298 andis. r23,r23,hi16(perfMonitor) ; Is the performance monitor enabled?
3299 lwz r23,saver23+4(r31) ; Restore R23
3300 cmpwi cr2,r28,CPU_SUBTYPE_POWERPC_7400 ; Yer standard G4?
3301 lwz r24,saver24+4(r31) ; Restore R24
3302 lwz r25,saver25+4(r31) ; Restore R25
3303 lwz r26,saver26+4(r31) ; Restore R26
3304 lwz r27,saver27+4(r31) ; Restore R27
3305
3306 beq+ noPerfMonRestore32 ; No perf monitor...
3307
3308 beq- cr1,perfMonRestore32_750 ; This is a G3...
3309 beq- cr2,perfMonRestore32_7400 ; Standard G4...
3310
3311 lwz r28,savepmc+16(r31)
3312 lwz r29,savepmc+20(r31)
3313 mtspr pmc5,r28 ; Restore PMC5
3314 mtspr pmc6,r29 ; Restore PMC6
3315
3316 perfMonRestore32_7400:
3317 lwz r28,savemmcr2+4(r31)
3318 mtspr mmcr2,r28 ; Restore MMCR2
3319
3320 perfMonRestore32_750:
3321 lwz r28,savepmc+0(r31)
3322 lwz r29,savepmc+4(r31)
3323 mtspr pmc1,r28 ; Restore PMC1
3324 mtspr pmc2,r29 ; Restore PMC2
3325 lwz r28,savepmc+8(r31)
3326 lwz r29,savepmc+12(r31)
3327 mtspr pmc3,r28 ; Restore PMC3
3328 mtspr pmc4,r29 ; Restore PMC4
3329 lwz r28,savemmcr1+4(r31)
3330 lwz r29,savemmcr0+4(r31)
3331 mtspr mmcr1,r28 ; Restore MMCR1
3332 mtspr mmcr0,r29 ; Restore MMCR0
3333
3334 noPerfMonRestore32:
3335 lwz r28,savecr(r31) ; Get CR to restore
3336 lwz r29,savexer+4(r31) ; Get XER to restore
3337 mtcr r28 ; Restore the CR
3338 lwz r28,savelr+4(r31) ; Get LR to restore
3339 mtxer r29 ; Restore the XER
3340 lwz r29,savectr+4(r31) ; Get the CTR to restore
3341 mtlr r28 ; Restore the LR
3342 lwz r28,saver30+4(r31) ; Get R30
3343 mtctr r29 ; Restore the CTR
3344 lwz r29,saver31+4(r31) ; Get R31
3345 mtsprg 2,r28 ; Save R30 for later
3346 lwz r28,saver28+4(r31) ; Restore R28
3347 mtsprg 3,r29 ; Save R31 for later
3348 lwz r29,saver29+4(r31) ; Restore R29
3349
3350 mfsprg r31,0 ; Get per_proc
3351 mfsprg r30,2 ; Restore R30
3352 lwz r31,pfAvailable(r31) ; Get the feature flags
3353 mtsprg 2,r31 ; Set the feature flags
3354 mfsprg r31,3 ; Restore R31
3355
3356 rfi ; Click heels three times and think very hard that there is no place like home...
3357
3358 .long 0 ; Leave this here
3359 .long 0
3360 .long 0
3361 .long 0
3362 .long 0
3363 .long 0
3364 .long 0
3365 .long 0
3366
3367
3368 ;
3369 ; This starts the 64-bit version
3370 ;
3371
3372 .align 7
3373
3374 eat64a: ld r30,quickfret(r29) ; Pick up the quick fret list, if any
3375
3376 mr. r3,r3 ; Should we hold off the quick release?
3377 la r21,saver0(r31) ; Point to the first thing we restore
3378 bne-- ernoqfre64 ; Hold off set, do not release just now...
3379
3380 erchkfre64: mr. r3,r30 ; Any savearea to quickly release?
3381 beq+ ernoqfre64 ; No quickfrets...
3382 ld r30,SAVprev(r30) ; Chain back now
3383
3384 bl EXT(save_ret_phys) ; Put it on the free list
3385
3386 std r30,quickfret(r29) ; Dequeue previous guy (really, it is ok to wait until after the release)
3387 b erchkfre64 ; Try the next one...
3388
3389 .align 7
3390
3391 ernoqfre64: dcbt 0,r21 ; Touch in the first thing we need
3392
3393 ;
3394 ; Here we release the savearea.
3395 ;
3396 ; Important!!!! The savearea is released before we are done with it. When the
3397 ; local free savearea list (anchored at lclfree) gets too long, save_ret_phys
3398 ; will trim the list, making the extra saveareas allocatable by another processor
3399 ; The code in there must ALWAYS leave our savearea on the local list, otherwise
3400 ; we could be very, very unhappy. The code there always queues the "just released"
3401 ; savearea to the head of the local list. Then, if it needs to trim, it will
3402 ; start with the SECOND savearea, leaving ours intact.
3403 ;
3404 ;
3405
3406 li r3,lgKillResv ; Get spot to kill reservation
3407 stdcx. r3,0,r3 ; Blow away any reservations we hold
3408
3409 mr r3,r31 ; Get the exiting savearea in parm register
3410 bl EXT(save_ret_phys) ; Put it on the free list
3411
3412 lwz r3,savesrr1+4(r31) ; Pass in the MSR we will be going to
3413 bl EXT(switchSegs) ; Go handle the segment registers/STB
3414
3415 lhz r9,PP_CPU_FLAGS(r29) ; Get the processor flags
3416 ld r26,savesrr1(r31) ; Get destination MSR
3417 cmplw cr3,r14,r14 ; Set that we do not need to stop streams
3418 rlwinm r25,r26,27,22,22 ; Move PR bit to BE
3419
3420 rlwinm r9,r9,(((31-MSR_BE_BIT)+(traceBEb+16+1))&31),MSR_BE_BIT,MSR_BE_BIT ; Set BE bit if special trace is on
3421 li r21,emfp0 ; Point to a workarea
3422 and r9,r9,r25 ; Clear BE if supervisor state
3423 or r26,r26,r9 ; Flip on the BE bit for special trace if needed
3424
3425 ld r25,savesrr0(r31) ; Get the SRR0 to use
3426 la r28,saver16(r31) ; Point to the 128-byte line with r16-r31
3427 dcbz128 r21,r29 ; Clear a work area
3428 ld r0,saver0(r31) ; Restore R0
3429 dcbt 0,r28 ; Touch in r16-r31
3430 ld r1,saver1(r31) ; Restore R1
3431 ld r2,saver2(r31) ; Restore R2
3432 ld r3,saver3(r31) ; Restore R3
3433 mtcrf 0x80,r27 ; Get facility availability flags (do not touch CR1-7)
3434 ld r4,saver4(r31) ; Restore R4
3435 mtsrr0 r25 ; Restore the SRR0 now
3436 ld r5,saver5(r31) ; Restore R5
3437 mtsrr1 r26 ; Restore the SRR1 now
3438 ld r6,saver6(r31) ; Restore R6
3439
3440 ld r7,saver7(r31) ; Restore R7
3441 ld r8,saver8(r31) ; Restore R8
3442 ld r9,saver9(r31) ; Restore R9
3443
3444 la r28,savevscr(r31) ; Point to the status area
3445
3446 ld r10,saver10(r31) ; Restore R10
3447 ld r11,saver11(r31) ; Restore R11
3448 ld r12,saver12(r31) ; Restore R12
3449 ld r13,saver13(r31) ; Restore R13
3450
3451 ld r26,next_savearea(r29) ; Get the exception save area
3452
3453 ld r14,saver14(r31) ; Restore R14
3454 ld r15,saver15(r31) ; Restore R15
3455 lwz r27,savevrsave(r31) ; Get the vrsave
3456
3457 bf-- pfAltivecb,noavec2s ; Skip if no VMX...
3458
3459 stvxl v0,r21,r29 ; Save a vector register
3460 lvxl v0,0,r28 ; Get the vector status
3461 mtvscr v0 ; Set the vector status
3462
3463 lvxl v0,r21,r29 ; Restore work vector register
3464
3465 noavec2s: mtspr vrsave,r27 ; Set the vrsave
3466
3467 lwz r28,saveexception(r31) ; Get exception type
3468 stfd f0,emfp0(r29) ; Save FP0
3469 lfd f0,savefpscrpad(r31) ; Get the fpscr
3470 mtfsf 0xFF,f0 ; Restore fpscr
3471 lfd f0,emfp0(r29) ; Restore the used register
3472 ld r16,saver16(r31) ; Restore R16
3473 lwz r30,spcFlags(r29) ; Get the special flags from per_proc
3474 ld r17,saver17(r31) ; Restore R17
3475 ld r18,saver18(r31) ; Restore R18
3476 cmplwi cr1,r28,T_RESET ; Are we returning from a reset?
3477 ld r19,saver19(r31) ; Restore R19
3478 ld r20,saver20(r31) ; Restore R20
3479 li r27,0 ; Get a zero
3480 ld r21,saver21(r31) ; Restore R21
3481 la r26,saver0(r26) ; Point to the first part of the next savearea
3482 andis. r30,r30,hi16(perfMonitor) ; Is the performance monitor enabled?
3483 ld r22,saver22(r31) ; Restore R22
3484 ld r23,saver23(r31) ; Restore R23
3485 bne++ cr1,er64rrst ; We are not returning from a reset...
3486 stw r27,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Allow resets again
3487
3488 er64rrst: ld r24,saver24(r31) ; Restore R24
3489
3490 dcbz128 0,r26 ; Clear and allocate next savearea we use in the off chance it is still in when we next interrupt
3491
3492 ld r25,saver25(r31) ; Restore R25
3493 ld r26,saver26(r31) ; Restore R26
3494 ld r27,saver27(r31) ; Restore R27
3495
3496 beq++ noPerfMonRestore64 ; Nope...
3497
3498 lwz r28,savepmc+0(r31)
3499 lwz r29,savepmc+4(r31)
3500 mtspr pmc1_gp,r28 ; Restore PMC1
3501 mtspr pmc2_gp,r29 ; Restore PMC2
3502 lwz r28,savepmc+8(r31)
3503 lwz r29,savepmc+12(r31)
3504 mtspr pmc3_gp,r28 ; Restore PMC3
3505 mtspr pmc4_gp,r29 ; Restore PMC4
3506 lwz r28,savepmc+16(r31)
3507 lwz r29,savepmc+20(r31)
3508 mtspr pmc5_gp,r28 ; Restore PMC5
3509 mtspr pmc6_gp,r29 ; Restore PMC6
3510 lwz r28,savepmc+24(r31)
3511 lwz r29,savepmc+28(r31)
3512 mtspr pmc7_gp,r28 ; Restore PMC7
3513 mtspr pmc8_gp,r29 ; Restore PMC8
3514 ld r28,savemmcr1(r31)
3515 ld r29,savemmcr2(r31)
3516 mtspr mmcr1_gp,r28 ; Restore MMCR1
3517 mtspr mmcra_gp,r29 ; Restore MMCRA
3518 ld r28,savemmcr0(r31)
3519
3520 mtspr mmcr0_gp,r28 ; Restore MMCR0
3521
3522 noPerfMonRestore64:
3523 mfsprg r30,0 ; Get per_proc
3524 lwz r28,savecr(r31) ; Get CR to restore
3525 ld r29,savexer(r31) ; Get XER to restore
3526 mtcr r28 ; Restore the CR
3527 ld r28,savelr(r31) ; Get LR to restore
3528 mtxer r29 ; Restore the XER
3529 ld r29,savectr(r31) ; Get the CTR to restore
3530 mtlr r28 ; Restore the LR
3531 ld r28,saver30(r31) ; Get R30
3532 mtctr r29 ; Restore the CTR
3533 ld r29,saver31(r31) ; Get R31
3534 mtspr hsprg0,r28 ; Save R30 for later
3535 ld r28,saver28(r31) ; Restore R28
3536 mtsprg 3,r29 ; Save R31 for later
3537 ld r29,saver29(r31) ; Restore R29
3538
3539 lwz r31,pfAvailable(r30) ; Get the feature flags
3540 ld r30,UAW(r30) ; Get the User Assist DoubleWord
3541 mtsprg 2,r31 ; Set the feature flags
3542 mfsprg r31,3 ; Restore R31
3543 mtsprg 3,r30 ; Set the UAW
3544 mfspr r30,hsprg0 ; Restore R30
3545
3546 rfid ; Click heels three times and think very hard that there is no place like home...
3547
3548
3549
3550 /*
3551 * exception_exit(savearea *)
3552 *
3553 *
3554 * ENTRY : IR and/or DR and/or interruptions can be on
3555 * R3 points to the virtual address of a savearea
3556 */
3557
3558 .align 5
3559 .globl EXT(exception_exit)
3560
3561 LEXT(exception_exit)
3562
3563 mfsprg r29,2 ; Get feature flags
3564 mr r31,r3 ; Get the savearea in the right register
3565 mtcrf 0x04,r29 ; Set the features
3566 li r0,1 ; Get this just in case
3567 mtcrf 0x02,r29 ; Set the features
3568 lis r30,hi16(MASK(MSR_VEC)|MASK(MSR_FP)|MASK(MSR_ME)) ; Set up the MSR we will use throughout. Note that ME come on here if MCK
3569 rlwinm r4,r3,0,0,19 ; Round down to savearea block base
3570 lis r1,hi16(SAVredrive) ; Get redrive request
3571 mfsprg r2,0 ; Get the per_proc block
3572 ori r30,r30,lo16(MASK(MSR_VEC)|MASK(MSR_FP)|MASK(MSR_ME)) ; Rest of MSR
3573 bt++ pf64Bitb,eeSixtyFour ; We are 64-bit...
3574
3575 lwz r4,SACvrswap+4(r4) ; Get the virtual to real translation
3576
3577 bt pfNoMSRirb,eeNoMSR ; No MSR...
3578
3579 mtmsr r30 ; Translation and all off
3580 isync ; Toss prefetch
3581 b eeNoMSRx
3582
3583 .align 5
3584
3585 eeSixtyFour:
3586 ld r4,SACvrswap(r4) ; Get the virtual to real translation
3587 rldimi r30,r0,63,MSR_SF_BIT ; Set SF bit (bit 0)
3588 mtmsrd r30 ; Set 64-bit mode, turn off EE, DR, and IR
3589 isync ; Toss prefetch
3590 b eeNoMSRx
3591
3592 .align 5
3593
3594 eeNoMSR: li r0,loadMSR ; Get the MSR setter SC
3595 mr r3,r30 ; Get new MSR
3596 sc ; Set it
3597
3598 eeNoMSRx: xor r31,r31,r4 ; Convert the savearea to physical addressing
3599 lwz r4,SAVflags(r31) ; Pick up the flags
3600 mr r13,r31 ; Put savearea here also
3601
3602 #if INSTRUMENT
3603 mfspr r5,pmc1 ; INSTRUMENT - saveinstr[8] - stamp exception exit
3604 stw r5,0x6100+(8*16)+0x0(0) ; INSTRUMENT - Save it
3605 mfspr r5,pmc2 ; INSTRUMENT - Get stamp
3606 stw r5,0x6100+(8*16)+0x4(0) ; INSTRUMENT - Save it
3607 mfspr r5,pmc3 ; INSTRUMENT - Get stamp
3608 stw r5,0x6100+(8*16)+0x8(0) ; INSTRUMENT - Save it
3609 mfspr r5,pmc4 ; INSTRUMENT - Get stamp
3610 stw r5,0x6100+(8*16)+0xC(0) ; INSTRUMENT - Save it
3611 #endif
3612
3613
3614 and. r0,r4,r1 ; Check if redrive requested
3615
3616 dcbt br0,r2 ; We will need this in just a sec
3617
3618 beq+ EatRupt ; No redrive, just exit...
3619
3620 0: mftbu r2 ; Avoid using an obsolete timestamp for the redrive
3621 mftb r4
3622 mftbu r0
3623 cmplw r0,r2
3624 bne-- 0b
3625
3626 stw r2,SAVtime(r13)
3627 stw r4,SAVtime+4(r13)
3628
3629 lwz r11,saveexception(r13) ; Restore exception code
3630 b Redrive ; Redrive the exception...
3631
3632
3633
3634 .align 12 ; Force page alignment
3635
3636 .globl EXT(ExceptionVectorsEnd)
3637 EXT(ExceptionVectorsEnd): /* Used if relocating the exception vectors */
3638
3639
3640
3641
3642 ;
3643 ; Here is where we keep the low memory globals
3644 ;
3645
3646 . = 0x5000
3647
3648 .ascii "Hagfish " ; 5000 Unique eyecatcher
3649 .long 0 ; 5008 Zero
3650 .long 0 ; 500C Zero cont...
3651 .long EXT(PerProcTable) ; 5010 pointer to per_proc_entry table
3652 .long 0 ; 5014 Zero
3653
3654 .globl EXT(mckFlags)
3655 EXT(mckFlags):
3656 .long 0 ; 5018 Machine check flags
3657
3658 .long EXT(version) ; 501C Pointer to kernel version string
3659 .long 0 ; 5020 physical memory window virtual address
3660 .long 0 ; 5024 physical memory window virtual address
3661 .long 0 ; 5028 user memory window virtual address
3662 .long 0 ; 502C user memory window virtual address
3663 .long 0 ; 5030 VMM boot-args forced feature flags
3664
3665 .globl EXT(maxDec)
3666 EXT(maxDec):
3667 .long 0x7FFFFFFF ; 5034 maximum decrementer value
3668
3669
3670 .globl EXT(pmsCtlp)
3671 EXT(pmsCtlp):
3672 .long 0 ; 5038 Pointer to power management stepper control
3673
3674 .long 0 ; 503C reserved
3675 .long 0 ; 5040 reserved
3676 .long 0 ; 5044 reserved
3677 .long 0 ; 5048 reserved
3678 .long 0 ; 504C reserved
3679 .long 0 ; 5050 reserved
3680 .long 0 ; 5054 reserved
3681 .long 0 ; 5058 reserved
3682 .long 0 ; 505C reserved
3683 .long 0 ; 5060 reserved
3684 .long 0 ; 5064 reserved
3685 .long 0 ; 5068 reserved
3686 .long 0 ; 506C reserved
3687 .long 0 ; 5070 reserved
3688 .long 0 ; 5074 reserved
3689 .long 0 ; 5078 reserved
3690 .long 0 ; 507C reserved
3691
3692 .globl EXT(trcWork)
3693 EXT(trcWork):
3694 .long 0 ; 5080 The next trace entry to use
3695 #if DEBUG
3696 .long 0xFFFFFFFF ; 5084 All enabled
3697 #else
3698 .long 0x00000000 ; 5084 All disabled on non-debug systems
3699 #endif
3700 .long 0 ; 5088 Start of the trace table
3701 .long 0 ; 508C End (wrap point) of the trace
3702 .long 0 ; 5090 Saved mask while in debugger
3703 .long 0 ; 5094 Size of trace table (1 - 256 pages)
3704 .long 0 ; 5098 traceGas[0]
3705 .long 0 ; 509C traceGas[1]
3706
3707 .long 0 ; 50A0 reserved
3708 .long 0 ; 50A4 reserved
3709 .long 0 ; 50A8 reserved
3710 .long 0 ; 50AC reserved
3711 .long 0 ; 50B0 reserved
3712 .long 0 ; 50B4 reserved
3713 .long 0 ; 50B8 reserved
3714 .long 0 ; 50BC reserved
3715 .long 0 ; 50C0 reserved
3716 .long 0 ; 50C4 reserved
3717 .long 0 ; 50C8 reserved
3718 .long 0 ; 50CC reserved
3719 .long 0 ; 50D0 reserved
3720 .long 0 ; 50D4 reserved
3721 .long 0 ; 50D8 reserved
3722 .long 0 ; 50DC reserved
3723 .long 0 ; 50E0 reserved
3724 .long 0 ; 50E4 reserved
3725 .long 0 ; 50E8 reserved
3726 .long 0 ; 50EC reserved
3727 .long 0 ; 50F0 reserved
3728 .long 0 ; 50F4 reserved
3729 .long 0 ; 50F8 reserved
3730 .long 0 ; 50FC reserved
3731
3732 .globl EXT(saveanchor)
3733
3734 EXT(saveanchor): ; 5100 saveanchor
3735 .set .,.+SVsize
3736
3737 .long 0 ; 5140 reserved
3738 .long 0 ; 5144 reserved
3739 .long 0 ; 5148 reserved
3740 .long 0 ; 514C reserved
3741 .long 0 ; 5150 reserved
3742 .long 0 ; 5154 reserved
3743 .long 0 ; 5158 reserved
3744 .long 0 ; 515C reserved
3745 .long 0 ; 5160 reserved
3746 .long 0 ; 5164 reserved
3747 .long 0 ; 5168 reserved
3748 .long 0 ; 516C reserved
3749 .long 0 ; 5170 reserved
3750 .long 0 ; 5174 reserved
3751 .long 0 ; 5178 reserved
3752 .long 0 ; 517C reserved
3753
3754 .long 0 ; 5180 tlbieLock
3755
3756 .long 0 ; 5184 reserved
3757 .long 0 ; 5188 reserved
3758 .long 0 ; 518C reserved
3759 .long 0 ; 5190 reserved
3760 .long 0 ; 5194 reserved
3761 .long 0 ; 5198 reserved
3762 .long 0 ; 519C reserved
3763 .long 0 ; 51A0 reserved
3764 .long 0 ; 51A4 reserved
3765 .long 0 ; 51A8 reserved
3766 .long 0 ; 51AC reserved
3767 .long 0 ; 51B0 reserved
3768 .long 0 ; 51B4 reserved
3769 .long 0 ; 51B8 reserved
3770 .long 0 ; 51BC reserved
3771 .long 0 ; 51C0 reserved
3772 .long 0 ; 51C4 reserved
3773 .long 0 ; 51C8 reserved
3774 .long 0 ; 51CC reserved
3775 .long 0 ; 51D0 reserved
3776 .long 0 ; 51D4 reserved
3777 .long 0 ; 51D8 reserved
3778 .long 0 ; 51DC reserved
3779 .long 0 ; 51E0 reserved
3780 .long 0 ; 51E4 reserved
3781 .long 0 ; 51E8 reserved
3782 .long 0 ; 51EC reserved
3783 .long 0 ; 51F0 reserved
3784 .long 0 ; 51F4 reserved
3785 .long 0 ; 51F8 reserved
3786 .long 0 ; 51FC reserved
3787
3788 .globl EXT(dgWork)
3789
3790 EXT(dgWork):
3791 .long 0 ; 5200 dgLock
3792 .long 0 ; 5204 dgFlags
3793 .long 0 ; 5208 dgMisc0
3794 .long 0 ; 520C dgMisc1
3795 .long 0 ; 5210 dgMisc2
3796 .long 0 ; 5214 dgMisc3
3797 .long 0 ; 5218 dgMisc4
3798 .long 0 ; 521C dgMisc5
3799
3800 .globl EXT(LcksOpts)
3801 EXT(LcksOpts):
3802 .long 0 ; 5220 lcksWork
3803 .long 0 ; 5224 reserved
3804 .long 0 ; 5228 reserved
3805 .long 0 ; 522C reserved
3806 .long 0 ; 5230 reserved
3807 .long 0 ; 5234 reserved
3808 .long 0 ; 5238 reserved
3809 .long 0 ; 523C reserved
3810 .long 0 ; 5240 reserved
3811 .long 0 ; 5244 reserved
3812 .long 0 ; 5248 reserved
3813 .long 0 ; 524C reserved
3814 .long 0 ; 5250 reserved
3815 .long 0 ; 5254 reserved
3816 .long 0 ; 5258 reserved
3817 .long 0 ; 525C reserved
3818 .long 0 ; 5260 reserved
3819 .long 0 ; 5264 reserved
3820 .long 0 ; 5268 reserved
3821 .long 0 ; 526C reserved
3822 .long 0 ; 5270 reserved
3823 .long 0 ; 5274 reserved
3824 .long 0 ; 5278 reserved
3825 .long 0 ; 527C reserved
3826
3827 .globl EXT(pPcfg)
3828 EXT(pPcfg):
3829 .long 0x80000000 | (12 << 8) | 12 ; 5280 pcfDefPcfg - 4k
3830 .long 0 ; 5284 pcfLargePcfg
3831 .long 0 ; 5288 Non-primary page configurations
3832 .long 0 ; 528C Non-primary page configurations
3833 .long 0 ; 5290 Non-primary page configurations
3834 .long 0 ; 5294 Non-primary page configurations
3835 .long 0 ; 5298 Non-primary page configurations
3836 .long 0 ; 529C Non-primary page configurations
3837
3838 .long 0 ; 52A0 reserved
3839 .long 0 ; 52A4 reserved
3840 .long 0 ; 52A8 reserved
3841 .long 0 ; 52AC reserved
3842 .long 0 ; 52B0 reserved
3843 .long 0 ; 52B4 reserved
3844 .long 0 ; 52B8 reserved
3845 .long 0 ; 52BC reserved
3846 .long 0 ; 52C0 reserved
3847 .long 0 ; 52C4 reserved
3848 .long 0 ; 52C8 reserved
3849 .long 0 ; 52CC reserved
3850 .long 0 ; 52D0 reserved
3851 .long 0 ; 52D4 reserved
3852 .long 0 ; 52D8 reserved
3853 .long 0 ; 52DC reserved
3854 .long 0 ; 52E0 reserved
3855 .long 0 ; 52E4 reserved
3856 .long 0 ; 52E8 reserved
3857 .long 0 ; 52EC reserved
3858 .long 0 ; 52F0 reserved
3859 .long 0 ; 52F4 reserved
3860 .long 0 ; 52F8 reserved
3861 .long 0 ; 52FC reserved
3862
3863 .globl EXT(killresv)
3864 EXT(killresv):
3865
3866 .long 0 ; 5300 Used to kill reservations
3867 .long 0 ; 5304 Used to kill reservations
3868 .long 0 ; 5308 Used to kill reservations
3869 .long 0 ; 530C Used to kill reservations
3870 .long 0 ; 5310 Used to kill reservations
3871 .long 0 ; 5314 Used to kill reservations
3872 .long 0 ; 5318 Used to kill reservations
3873 .long 0 ; 531C Used to kill reservations
3874 .long 0 ; 5320 Used to kill reservations
3875 .long 0 ; 5324 Used to kill reservations
3876 .long 0 ; 5328 Used to kill reservations
3877 .long 0 ; 532C Used to kill reservations
3878 .long 0 ; 5330 Used to kill reservations
3879 .long 0 ; 5334 Used to kill reservations
3880 .long 0 ; 5338 Used to kill reservations
3881 .long 0 ; 533C Used to kill reservations
3882 .long 0 ; 5340 Used to kill reservations
3883 .long 0 ; 5344 Used to kill reservations
3884 .long 0 ; 5348 Used to kill reservations
3885 .long 0 ; 534C Used to kill reservations
3886 .long 0 ; 5350 Used to kill reservations
3887 .long 0 ; 5354 Used to kill reservations
3888 .long 0 ; 5358 Used to kill reservations
3889 .long 0 ; 535C Used to kill reservations
3890 .long 0 ; 5360 Used to kill reservations
3891 .long 0 ; 5364 Used to kill reservations
3892 .long 0 ; 5368 Used to kill reservations
3893 .long 0 ; 536C Used to kill reservations
3894 .long 0 ; 5370 Used to kill reservations
3895 .long 0 ; 5374 Used to kill reservations
3896 .long 0 ; 5378 Used to kill reservations
3897 .long 0 ; 537C Used to kill reservations
3898
3899 .long 0 ; 5380 reserved
3900 .long 0 ; 5384 reserved
3901 .long 0 ; 5388 reserved
3902 .long 0 ; 538C reserved
3903 .long 0 ; 5390 reserved
3904 .long 0 ; 5394 reserved
3905 .long 0 ; 5398 reserved
3906 .long 0 ; 539C reserved
3907 .long 0 ; 53A0 reserved
3908 .long 0 ; 53A4 reserved
3909 .long 0 ; 53A8 reserved
3910 .long 0 ; 53AC reserved
3911 .long 0 ; 53B0 reserved
3912 .long 0 ; 53B4 reserved
3913 .long 0 ; 53B8 reserved
3914 .long 0 ; 53BC reserved
3915 .long 0 ; 53C0 reserved
3916 .long 0 ; 53C4 reserved
3917 .long 0 ; 53C8 reserved
3918 .long 0 ; 53CC reserved
3919 .long 0 ; 53D0 reserved
3920 .long 0 ; 53D4 reserved
3921 .long 0 ; 53D8 reserved
3922 .long 0 ; 53DC reserved
3923 .long 0 ; 53E0 reserved
3924 .long 0 ; 53E4 reserved
3925 .long 0 ; 53E8 reserved
3926 .long 0 ; 53EC reserved
3927 .long 0 ; 53F0 reserved
3928 .long 0 ; 53F4 reserved
3929 .long 0 ; 53F8 reserved
3930 .long 0 ; 53FC reserved
3931 .long 0 ; 5400 reserved
3932 .long 0 ; 5404 reserved
3933 .long 0 ; 5408 reserved
3934 .long 0 ; 540C reserved
3935 .long 0 ; 5410 reserved
3936 .long 0 ; 5414 reserved
3937 .long 0 ; 5418 reserved
3938 .long 0 ; 541C reserved
3939 .long 0 ; 5420 reserved
3940 .long 0 ; 5424 reserved
3941 .long 0 ; 5428 reserved
3942 .long 0 ; 542C reserved
3943 .long 0 ; 5430 reserved
3944 .long 0 ; 5434 reserved
3945 .long 0 ; 5438 reserved
3946 .long 0 ; 543C reserved
3947 .long 0 ; 5440 reserved
3948 .long 0 ; 5444 reserved
3949 .long 0 ; 5448 reserved
3950 .long 0 ; 544C reserved
3951 .long 0 ; 5450 reserved
3952 .long 0 ; 5454 reserved
3953 .long 0 ; 5458 reserved
3954 .long 0 ; 545C reserved
3955 .long 0 ; 5460 reserved
3956 .long 0 ; 5464 reserved
3957 .long 0 ; 5468 reserved
3958 .long 0 ; 546C reserved
3959 .long 0 ; 5470 reserved
3960 .long 0 ; 5474 reserved
3961 .long 0 ; 5478 reserved
3962 .long 0 ; 547C reserved
3963 ;
3964 ; The "shared page" is used for low-level debugging
3965 ;
3966
3967 . = 0x6000
3968 .globl EXT(sharedPage)
3969
3970 EXT(sharedPage): ; Per processor data area
3971 .long 0xC24BC195 ; Comm Area validity value
3972 .long 0x87859393 ; Comm Area validity value
3973 .long 0xE681A2C8 ; Comm Area validity value
3974 .long 0x8599855A ; Comm Area validity value
3975 .long 0xD74BD296 ; Comm Area validity value
3976 .long 0x8388E681 ; Comm Area validity value
3977 .long 0xA2C88599 ; Comm Area validity value
3978 .short 0x855A ; Comm Area validity value
3979 .short 1 ; Comm Area version number
3980 .fill 1016*4,1,0 ; (filled with 0s)
3981
3982 .data
3983 .align ALIGN
3984 .globl EXT(exception_end)
3985 EXT(exception_end):
3986 .long EXT(ExceptionVectorsEnd) -EXT(ExceptionVectorsStart) /* phys fn */
3987
3988
3989