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