#include <ppc/proc_reg.h>
#include <ppc/exception.h>
#include <ppc/Performance.h>
+#include <ppc/savearea.h>
#include <mach/ppc/vm_param.h>
-#include <ppc/POWERMAC/mp/MPPlugIn.h>
#define TRCSAVE 0
#define CHECKSAVE 0
#define featAltivec 26
#define wasNapping 27
#define featFP 28
+#define specAccess 29
#define VECTOR_SEGMENT .section __VECTORS, __interrupts
resetexc:
mtcr r11
- mfsprg r13,1 /* Get the exception save area */
li r11,T_RESET /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler200:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_MACHINE_CHECK /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler300:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_DATA_ACCESS /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler400:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_INSTRUCTION_ACCESS /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler500:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_INTERRUPT /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler600:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_ALIGNMENT /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler700:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_PROGRAM /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler800:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_FP_UNAVAILABLE /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler900:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_DECREMENTER /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handlerA00:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_IO_ERROR /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handlerB00:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_RESERVED /* Set 'rupt code */
b .L_exception_entry /* Join common... */
; 0x00007FF4 - Kernel only - loadMSR
;
; Note: none handled if virtual machine is running
+; Also, it we treat SCs as kernel SCs if the RI bit is set
;
. = 0xC00
mtsprg 2,r13 ; Save R13
mfsrr1 r13 ; Get SRR1 for loadMSR
mtsprg 3,r11 ; Save R11
+ rlwimi r13,r13,MSR_PR_BIT,0,0 ; Move PR bit to non-volatile CR0 bit 0
mfcr r11 ; Save the CR
- rlwinm. r13,r13,0,MSR_PR_BIT,MSR_PR_BIT ; From problem state?
+ mtcrf 0x81,r13 ; Get the moved PR and the RI for testing
+ crnot 0,0 ; Get !PR
+ cror 0,0,MSR_RI_BIT ; See if we have !PR or RI
mfsprg r13,0 ; Get the per_proc_area
- beq- uftInKern ; We are in the kernel...
+ bt- 0,uftInKern ; We are in the kernel...
cmplwi cr5,r0,0x7FF2 ; Ultra fast path cthread info call?
cmpwi cr6,r0,0x7FF3 ; Ultra fast path facility status?
;
notufp: mtcrf 0xFF,r11 ; Restore the used CRs
li r11,T_SYSTEM_CALL ; Set interrupt code
- mfsprg r13,1 ; Get the exception save area
b .L_exception_entry ; Join common...
uftInKern: cmplwi r0,0x7FF4 ; Ultra fast path loadMSR?
bne+ specbrtr ; Yeah...
notspectr: mtcr r11 ; Restore CR
- mfsprg r13,1 ; Get the savearea
li r11,T_TRACE ; Set interrupt code
b .L_exception_entry ; Join common...
.L_handlerE00:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_FP_ASSIST /* Set 'rupt code */
b .L_exception_entry /* Join common... */
PMIhandler:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_PERF_MON /* Set 'rupt code */
b .L_exception_entry /* Join common... */
VMXhandler:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_VMX /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler1300:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_INSTRUCTION_BKPT /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler1400:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_SYSTEM_MANAGEMENT /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler1600:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_ALTIVEC_ASSIST /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler1700:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_THERMAL /* Set 'rupt code */
b .L_exception_entry /* Join common... */
.L_handler2000:
mtsprg 2,r13 /* Save R13 */
mtsprg 3,r11 /* Save R11 */
- mfsprg r13,1 /* Get the exception save area */
li r11,T_RUNMODE_TRACE /* Set 'rupt code */
b .L_exception_entry /* Join common... */
* Note that if we are attempting to sleep (as opposed to nap or doze) all interruptions
* are ignored.
*/
+ mfsprg r13,0 /* Load per_proc */
+ lwz r13,next_savearea(r13) /* Get the exception save area */
stw r1,saver1(r13) ; Save register 1
stw r0,saver0(r13) ; Save register 0
+ dcbtst 0,r13 ; We will need this in a bit
mfspr r1,hid0 ; Get HID0
mfcr r0 ; Save the CR
mtcrf 255,r1 ; Get set to test for cache and sleep
rlwinm r2,r1,0,nap+1,doze-1 ; Clear any possible nap and doze bits
mtspr hid0,r2 ; Clear the nap/doze bits
cmplw r2,r1 ; See if we were napping
- li r1,32 ; Point to the next line in case we need it
+ la r1,saver8(r13) ; Point to the next line in case we need it
crnot wasNapping,cr0_eq ; Remember if we were napping
mfsprg r2,0 ; Get the per_proc area
bf- featL1ena,skipz1 ; L1 cache is disabled...
- dcbz r1,r13 ; Reserve our line in cache
+ dcbz 0,r1 ; Reserve our line in cache
;
; Remember, we are setting up CR6 with feature flags
;
skipz1: lwz r1,pfAvailable(r2) ; Get the CPU features flags
stw r3,saver3(r13) ; Save this one
+ la r3,savesrr0(r13) ; Point to the last line
mtcrf 0xE0,r1 ; Put the features flags (that we care about) in the CR
stw r4,saver4(r13) ; Save this one
stw r6,saver6(r13) ; Save this one
crmove featSMP,pfSMPcapb ; See if we have a PIR
stw r8,saver8(r13) ; Save this one
crmove featAltivec,pfAltivecb ; Set the Altivec flag
- mfsrr0 r6 /* Get the interruption SRR0 */
- stw r8,saver8(r13) /* Save this one */
- crmove featFP,pfFloatb ; Remember that we have floating point
- stw r7,saver7(r13) /* Save this one */
+ mfsrr0 r6 ; Get the interruption SRR0
+ stw r8,saver8(r13) ; Save this one
+ bf- featL1ena,skipz1a ; L1 cache is disabled...
+ dcbz 0,r3 ; Reserve our line in cache
+skipz1a: crmove featFP,pfFloatb ; Remember that we have floating point
+ stw r7,saver7(r13) ; Save this one
lhz r8,PP_CPU_FLAGS(r2) ; Get the flags
- mfsrr1 r7 /* Get the interrupt SRR1 */
+ mfsrr1 r7 ; Get the interrupt SRR1
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
- stw r6,savesrr0(r13) /* Save the SRR0 */
+ stw r6,savesrr0(r13) ; Save the SRR0
rlwinm r6,r7,(((31-MSR_BE_BIT)+(MSR_PR_BIT+1))&31),MSR_BE_BIT,MSR_BE_BIT ; Move PR bit to BE bit
- stw r5,saver5(r13) /* Save this one */
+ stw r5,saver5(r13) ; Save this one
and r8,r6,r8 ; Remove BE bit only if problem state and special tracing on
mfsprg r6,2 ; Get interrupt time R13
mtsprg 2,r1 ; Set the feature flags
andc r7,r7,r8 ; Clear BE bit if special trace is on and PR is set
- mfsprg r8,3 /* Get 'rupt time R11 */
- stw r7,savesrr1(r13) /* Save SRR1 */
- stw r6,saver13(r13) /* Save 'rupt R1 */
- stw r8,saver11(r13) /* Save 'rupt time R11 */
+ mfsprg r8,3 ; Get rupt time R11
+ stw r7,savesrr1(r13) ; Save SRR1
+ rlwinm. r7,r7,MSR_RI_BIT,MSR_RI_BIT ; Is this a special case access fault?
+ stw r6,saver13(r13) ; Save rupt R1
+ crnot specAccess,cr0_eq ; Set that we are doing a special access if RI is set
+ stw r8,saver11(r13) ; Save rupt time R11
getTB: mftbu r6 ; Get the upper timebase
mftb r7 ; Get the lower timebase
bne- getTB ; Yeah, need to get it again...
stw r8,ruptStamp(r2) ; Save the top of time stamp
- la r6,saver14(r13) ; Point to the next cache line
+ stw r8,SAVtime(r13) ; Save the top of time stamp
+ la r6,saver16(r13) ; Point to the next cache line
stw r7,ruptStamp+4(r2) ; Save the bottom of time stamp
+ stw r7,SAVtime+4(r13) ; Save the bottom of time stamp
+
bf- featL1ena,skipz2 ; L1 cache is disabled...
- dcbz 0,r6 /* Allocate in cache */
+ dcbz 0,r6 ; Allocate in cache
skipz2:
- stw r9,saver9(r13) /* Save this one */
+ stw r9,saver9(r13) ; Save this one
- la r9,saver30(r13) /* Point to the trailing end */
- stw r10,saver10(r13) /* Save this one */
- mflr r4 /* Get the LR */
+ stw r10,saver10(r13) ; Save this one
+ mflr r4 ; Get the LR
mfxer r10 ; Get the XER
bf+ wasNapping,notNapping ; Skip if not waking up from nap...
stw r6,napTotal+4(r2) ; Save the low total
stw r8,napTotal(r2) ; Save the high total
stw r3,savesrr0(r13) ; Modify to return to nap/doze exit
+
+ rlwinm. r3,r1,0,pfSlowNapb,pfSlowNapb ; Should HID1 be restored?
+ beq notInSlowNap
+
+ lwz r3,pfHID1(r2) ; Get saved HID1 value
+ mtspr hid1, r3 ; Restore HID1
+notInSlowNap:
+ rlwinm. r3,r1,0,pfNoL2PFNapb,pfNoL2PFNapb ; Should MSSCR0 be restored?
+ beq notNapping
-notNapping: stw r12,saver12(r13) /* Save this one */
+ lwz r3,pfMSSCR0(r2) ; Get saved MSSCR0 value
+ mtspr msscr0, r3 ; Restore MSSCR0
+ sync
+ isync
+
+notNapping: stw r12,saver12(r13) ; Save this one
- bf- featL1ena,skipz3 ; L1 cache is disabled...
- dcbz 0,r9 /* Allocate the last in the area */
-skipz3:
- stw r14,saver14(r13) /* Save this one */
- stw r15,saver15(r13) /* Save this one */
- la r14,saver22(r13) /* Point to the next block to save into */
+ stw r14,saver14(r13) ; Save this one
+ stw r15,saver15(r13) ; Save this one
+ la r14,saver24(r13) ; Point to the next block to save into
stw r0,savecr(r13) ; Save rupt CR
- mfctr r6 /* Get the CTR */
- stw r16,saver16(r13) /* Save this one */
- stw r4,savelr(r13) /* Save 'rupt LR */
+ mfctr r6 ; Get the CTR
+ stw r16,saver16(r13) ; Save this one
+ stw r4,savelr(r13) ; Save rupt LR
bf- featL1ena,skipz4 ; L1 cache is disabled...
- dcbz 0,r14 /* Allocate next save area line */
+ dcbz 0,r14 ; Allocate next save area line
skipz4:
- stw r17,saver17(r13) /* Save this one */
- stw r18,saver18(r13) /* Save this one */
- stw r6,savectr(r13) /* Save 'rupt CTR */
- stw r19,saver19(r13) /* Save this one */
- lis r12,HIGH_ADDR(KERNEL_SEG_REG0_VALUE) /* Get the high half of the kernel SR0 value */
- mfdar r6 /* Get the 'rupt DAR */
- stw r20,saver20(r13) /* Save this one */
-#if 0
- mfsr r14,sr0 ; (TEST/DEBUG)
- stw r14,savesr0(r13) ; (TEST/DEBUG)
- mfsr r14,sr1 ; (TEST/DEBUG)
- stw r14,savesr1(r13) ; (TEST/DEBUG)
- mfsr r14,sr2 ; (TEST/DEBUG)
- stw r14,savesr2(r13) ; (TEST/DEBUG)
- mfsr r14,sr3 ; (TEST/DEBUG)
- stw r14,savesr3(r13) ; (TEST/DEBUG)
- mfsr r14,sr4 ; (TEST/DEBUG)
- stw r14,savesr4(r13) ; (TEST/DEBUG)
- mfsr r14,sr5 ; (TEST/DEBUG)
- stw r14,savesr5(r13) ; (TEST/DEBUG)
- mfsr r14,sr6 ; (TEST/DEBUG)
- stw r14,savesr6(r13) ; (TEST/DEBUG)
- mfsr r14,sr7 ; (TEST/DEBUG)
- stw r14,savesr7(r13) ; (TEST/DEBUG)
- mfsr r14,sr8 ; (TEST/DEBUG)
- stw r14,savesr8(r13) ; (TEST/DEBUG)
- mfsr r14,sr9 ; (TEST/DEBUG)
- stw r14,savesr9(r13) ; (TEST/DEBUG)
- mfsr r14,sr10 ; (TEST/DEBUG)
- stw r14,savesr10(r13) ; (TEST/DEBUG)
- mfsr r14,sr11 ; (TEST/DEBUG)
- stw r14,savesr11(r13) ; (TEST/DEBUG)
- mfsr r14,sr12 ; (TEST/DEBUG)
- stw r14,savesr12(r13) ; (TEST/DEBUG)
- mfsr r14,sr13 ; (TEST/DEBUG)
- stw r14,savesr13(r13) ; (TEST/DEBUG)
- mfsr r14,sr15 ; (TEST/DEBUG)
- stw r14,savesr15(r13) ; (TEST/DEBUG)
-#endif
-
- mtsr sr0,r12 /* Set the kernel SR0 */
- stw r21,saver21(r13) /* Save this one */
+ stw r17,saver17(r13) ; Save this one
+ stw r18,saver18(r13) ; Save this one
+ stw r6,savectr(r13) ; Save rupt CTR
+ stw r19,saver19(r13) ; Save this one
+ lis r12,hi16(KERNEL_SEG_REG0_VALUE) ; Get the high half of the kernel SR0 value
+ mfdar r6 ; Get the rupt DAR
+ stw r20,saver20(r13) ; Save this one
+
+ bf+ specAccess,noSRsave ; Do not save SRs if this is not a special access...
+ mfsr r14,sr0 ; Get SR0
+ stw r14,savesr0(r13) ; and save
+ mfsr r14,sr1 ; Get SR1
+ stw r14,savesr1(r13) ; and save
+ mfsr r14,sr2 ; get SR2
+ stw r14,savesr2(r13) ; and save
+ mfsr r14,sr3 ; get SR3
+ stw r14,savesr3(r13) ; and save
+
+noSRsave: mtsr sr0,r12 ; Set the kernel SR0
+ stw r21,saver21(r13) ; Save this one
addis r12,r12,0x0010 ; Point to the second segment of kernel
stw r10,savexer(r13) ; Save the rupt XER
- mtsr sr1,r12 /* Set the kernel SR1 */
- stw r30,saver30(r13) /* Save this one */
+ mtsr sr1,r12 ; Set the kernel SR1
+ stw r30,saver30(r13) ; Save this one
addis r12,r12,0x0010 ; Point to the third segment of kernel
- stw r31,saver31(r13) /* Save this one */
- mtsr sr2,r12 /* Set the kernel SR2 */
- stw r22,saver22(r13) /* Save this one */
+ stw r31,saver31(r13) ; Save this one
+ mtsr sr2,r12 ; Set the kernel SR2
+ stw r22,saver22(r13) ; Save this one
addis r12,r12,0x0010 ; Point to the third segment of kernel
- la r10,savedar(r13) /* Point to exception info block */
- stw r23,saver23(r13) /* Save this one */
- mtsr sr3,r12 /* Set the kernel SR3 */
- stw r24,saver24(r13) /* Save this one */
- stw r25,saver25(r13) /* Save this one */
- mfdsisr r7 /* Get the 'rupt DSISR */
- stw r26,saver26(r13) /* Save this one */
-
- bf- featL1ena,skipz5 ; L1 cache is disabled...
- dcbz 0,r10 /* Allocate exception info line */
-skipz5:
-
- stw r27,saver27(r13) /* Save this one */
+ stw r23,saver23(r13) ; Save this one
+ mtsr sr3,r12 ; Set the kernel SR3
+ stw r24,saver24(r13) ; Save this one
+ stw r25,saver25(r13) ; Save this one
+ mfdsisr r7 ; Get the rupt DSISR
+ stw r26,saver26(r13) ; Save this one
+ stw r27,saver27(r13) ; Save this one
li r10,emfp0 ; Point to floating point save
- stw r28,saver28(r13) /* Save this one */
- stw r29,saver29(r13) /* Save this one */
+ stw r28,saver28(r13) ; Save this one
+ stw r29,saver29(r13) ; Save this one
mfsr r14,sr14 ; Get the copyin/out segment register
- stw r6,savedar(r13) /* Save the 'rupt DAR */
+ stw r6,savedar(r13) ; Save the rupt DAR
bf- featL1ena,skipz5a ; Do not do this if no L1...
dcbz r10,r2 ; Clear and allocate an L1 slot
-skipz5a: stw r7,savedsisr(r13) /* Save the 'rupt code DSISR */
- stw r11,saveexception(r13) /* Save the exception code */
+skipz5a: stw r7,savedsisr(r13) ; Save the rupt code DSISR
+ stw r11,saveexception(r13) ; Save the exception code
stw r14,savesr14(r13) ; Save copyin/copyout
- lis r8,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
+
+;
+; Here we will save some floating point and vector status
+; and we also set a clean default status for a new interrupt level.
+; Note that we assume that emfp0 is on an altivec boundary
+; and that R10 points to it (as a displacemnt from R2).
+;
+
+ lis r8,hi16(MASK(MSR_VEC)) ; Get the vector enable bit
+ mfmsr r6 ; Get the current MSR value
+ ori r8,r8,lo16(MASK(MSR_FP)) ; Add in the float enable
li r19,0 ; Assume no Altivec
- ori r8,r8,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
+ or r7,r6,r8 ; Enable floating point
+ li r9,0 ; Get set to clear VRSAVE
+ mtmsr r7 ; Do it
+ isync
bf featAltivec,noavec ; No Altivec on this CPU...
- li r9,0 ; Get set to clear VRSAVE
+ addi r14,r10,16 ; Displacement to second vector register
+ stvxl v0,r10,r2 ; Save a register
+ stvxl v1,r14,r2 ; Save a second register
+ mfvscr v0 ; Get the vector status register
+ la r28,savevscr(r13) ; Point to the status area
+ vspltish v1,1 ; Turn on the non-Java bit and saturate
+ stvxl v0,0,r28 ; Save the vector status
+ vspltisw v0,1 ; Turn on the saturate bit
mfspr r19,vrsave ; Get the VRSAVE register
+ vxor v1,v1,v0 ; Turn off saturate
mtspr vrsave,r9 ; Clear VRSAVE for each interrupt level
+ mtvscr v1 ; Set the non-java, no saturate status for new level
+
+ lvxl v0,r10,r2 ; Restore first work register
+ lvxl v1,r14,r2 ; Restore second work register
+
+noavec: stw r19,savevrsave(r13) ; Save the vector register usage flags
+
;
; We need to save the FPSCR as if it is normal context.
; This is because pending exceptions will cause an exception even if
; FP is disabled. We need to clear the FPSCR when we first start running in the
; kernel.
;
-noavec: stw r19,savevrsave(r13) ; Save the vector register usage flags
bf- featFP,nofpexe ; No possible floating point exceptions...
- mfmsr r9 ; Get the MSR value
- ori r7,r9,lo16(MASK(MSR_FP)) ; Enable floating point
- mtmsr r7 ; Do it
- isync
stfd f0,emfp0(r2) ; Save FPR0
stfd f1,emfp1(r2) ; Save FPR1
mffs f0 ; Get the FPSCR
fsub f1,f1,f1 ; Make a 0
- stfd f0,savexfpscrpad(r13) ; Save the FPSCR
+ stfd f0,savefpscrpad(r13) ; Save the FPSCR
mtfsf 0xFF,f1 ; Clear it
lfd f0,emfp0(r2) ; Restore FPR0
lfd f1,emfp1(r2) ; Restore FPR1
- mtmsr r9 ; Turn off FP
+
+nofpexe: mtmsr r6 ; Turn off FP and vector
isync
-nofpexe:
+
-/*
- * Everything is saved at this point, except for FPRs, and VMX registers
- *
- * Time for a new save area. Allocate the trace table entry now also
- * Note that we haven't touched R0-R5 yet. Except for R0 & R1, that's in the save
- */
+;
+; Everything is saved at this point, except for FPRs, and VMX registers.
+; Time for us to get a new savearea and then trace interrupt if it is enabled.
+;
+
+ li r0,SAVgeneral ; Get the savearea type value
+ lis r23,hi16(EXT(trcWork)) ; Get the trace work area address
+ mr r14,r11 ; Save the interrupt code across the call
+ stb r0,SAVflags+2(r13) ; Mark valid context
+ ori r23,r23,lo16(EXT(trcWork)) ; Get the rest
+ rlwinm r22,r11,30,0,31 ; Divide interrupt code by 2
+ lwz r25,traceMask(r23) ; Get the trace mask
+ addi r22,r22,10 ; Adjust code so we shift into CR5
+
+ bl EXT(save_get_phys) ; Grab a savearea
+
+ mfsprg r2,0 ; Get back the per_proc block
+ rlwnm r7,r25,r22,22,22 ; Set CR5_EQ bit position to 0 if tracing allowed
+ lhz r19,PP_CPU_NUMBER(r2) ; Get the logical processor number
+ li r26,0x8 ; Get start of cpu mask
+ mr r11,r14 ; Get the exception code back
+ srw r26,r26,r19 ; Get bit position of cpu number
+ mtcrf 0x04,r7 ; Set CR5 to show trace or not
+ and. r26,r26,r25 ; See if we trace this cpu
+ stw r3,next_savearea(r2) ; Remember the savearea we just got for the next rupt
+ crandc cr5_eq,cr5_eq,cr0_eq ; Turn off tracing if cpu is disabled
+;
+; At this point, we can take another exception and lose nothing.
+;
+
+ lwz r0,saver0(r13) ; Get back interrupt time R0 (we need this whether we trace or not)
+
+ bne+ cr5,skipTrace ; Skip all of this if no tracing here...
+;
+; We select a trace entry using a compare and swap on the next entry field.
+; Since we do not lock the actual trace buffer, there is a potential that
+; another processor could wrap an trash our entry. Who cares?
+;
-lllck: lwarx r9,0,r8 /* Grab the lock value */
- li r7,1 /* Use part of the delay time */
- mr. r9,r9 /* Is it locked? */
- bne- lllcks /* Yeah, wait for it to clear... */
- stwcx. r7,0,r8 /* Try to seize that there durn lock */
- beq+ lllckd /* Got it... */
- b lllck /* Collision, try again... */
+ lwz r25,traceStart(r23) ; Get the start of trace table
+ lwz r26,traceEnd(r23) ; Get end of trace table
+
+trcsel: lwarx r20,0,r23 ; Get and reserve the next slot to allocate
-lllcks: lwz r9,SVlock(r8) /* Get that lock in here */
- mr. r9,r9 /* Is it free yet? */
- beq+ lllck /* Yeah, try for it again... */
- b lllcks /* Sniff away... */
+ addi r22,r20,LTR_size ; Point to the next trace entry
+ cmplw r22,r26 ; Do we need to wrap the trace table?
+ bne+ gotTrcEnt ; No wrap, we got us a trace entry...
-lllckd: isync /* Purge any speculative executions here */
- lis r23,hi16(EXT(trcWork)) ; Get the work area address
- rlwinm r7,r11,30,0,31 /* Save 'rupt code shifted right 2 */
- ori r23,r23,lo16(EXT(trcWork)) ; Get the rest
-#if 1
- lwz r14,traceMask(r23) /* Get the trace mask */
-#else
- li r14,-1 /* (TEST/DEBUG) */
-#endif
- addi r7,r7,10 /* Adjust for CR5_EQ position */
- lwz r15,SVfree(r8) /* Get the head of the save area list */
- lwz r25,SVinuse(r8) /* Get the in use count */
- rlwnm r7,r14,r7,22,22 /* Set CR5_EQ bit position to 0 if tracing allowed */
- lwz r20,traceCurr(r23) /* Pick up the current trace entry */
- mtcrf 0x04,r7 /* Set CR5 to show trace or not */
-
- lwz r14,SACalloc(r15) /* Pick up the allocation bits */
- addi r25,r25,1 /* Bump up the in use count for the new savearea */
- lwz r21,traceEnd(r23) /* Grab up the end of it all */
- mr. r14,r14 /* Can we use the first one? */
- blt use1st /* Yeah... */
-
- andis. r14,r14,0x8000 /* Show we used the second and remember if it was the last */
- addi r10,r15,0x0800 /* Point to the first one */
- b gotsave /* We have the area now... */
-
-use1st: andis. r14,r14,0x4000 /* Mark first gone and remember if empty */
- mr r10,r15 /* Set the save area */
-
-gotsave: stw r14,SACalloc(r15) /* Put back the allocation bits */
- bne nodqsave /* There's still an empty slot, don't dequeue... */
-
- lwz r16,SACnext(r15) /* Get the next in line */
- stw r16,SVfree(r8) /* Dequeue our now empty save area block */
-
-nodqsave: addi r22,r20,LTR_size /* Point to the next trace entry */
- stw r25,SVinuse(r8) /* Set the in use count */
- li r17,0 /* Clear this for the lock */
- cmplw r22,r21 /* Do we need to wrap the trace table? */
- stw r17,SAVprev(r10) /* Clear back pointer for the newly allocated guy */
- mtsprg 1,r10 /* Get set for the next 'rupt */
- bne+ gotTrcEnt /* We got a trace entry... */
-
- lwz r22,traceStart(r23) /* Wrap back to the top */
-
-gotTrcEnt: bne- cr5,skipTrace1 /* Don't want to trace this kind... */
-
- stw r22,traceCurr(r23) /* Set the next entry for the next guy */
+ mr r22,r25 ; Wrap back to start
+
+gotTrcEnt: stwcx. r22,0,r23 ; Try to update the current pointer
+ bne- trcsel ; Collision, try again...
#if ESPDEBUG
- dcbst br0,r23 ; (TEST/DEBUG)
- sync ; (TEST/DEBUG)
+ dcbf 0,r23 ; Force to memory
+ sync
#endif
bf- featL1ena,skipz6 ; L1 cache is disabled...
- dcbz 0,r20 /* Allocate cache for the entry */
+ dcbz 0,r20 ; Clear and allocate first trace line
skipz6:
-
-skipTrace1: sync /* Make sure all stores are done */
- stw r17,SVlock(r8) /* Unlock both save and trace areas */
+;
+; Let us cut that trace entry now.
+;
-/*
- * At this point, we can take another exception and lose nothing.
- *
- * We still have the current savearea pointed to by R13, the next by R10 and
- * sprg1. R20 contains the pointer to a trace entry and CR5_eq says
- * to do the trace or not.
- *
- * Note that R13 was chosen as the save area pointer because the SIGP,
- * firmware, and DSI/ISI handlers aren't supposed to touch anything
- * over R12. But, actually, the DSI/ISI stuff does.
- *
- *
- * Let's cut that trace entry now.
- */
-
- lwz r0,saver0(r13) ; Get back interrupt time R0
- bne- cr5,skipTrace2 /* Don't want to trace this kind... */
- mfsprg r2,0 ; Get the per_proc
- li r14,32 /* Second line of entry */
+ li r14,32 ; Offset to second line
lwz r16,ruptStamp(r2) ; Get top of time base
lwz r17,ruptStamp+4(r2) ; Get the bottom of time stamp
bf- featL1ena,skipz7 ; L1 cache is disabled...
- dcbz r14,r20 /* Zap the second half */
-
-skipz7: stw r16,LTR_timeHi(r20) /* Set the upper part of TB */
- bf featSMP,nopir4 ; Is there a processor ID register on this guy?
- mfspr r19,pir /* Get the processor address */
- b gotpir4 /* Got it... */
-nopir4: li r19,0 /* Assume processor 0 for those underprivileged folks */
-gotpir4:
+ dcbz r14,r20 ; Zap the second half
+
+skipz7: stw r16,LTR_timeHi(r20) ; Set the upper part of TB
lwz r1,saver1(r13) ; Get back interrupt time R1
- stw r17,LTR_timeLo(r20) /* Set the lower part of TB */
- rlwinm r19,r19,0,27,31 /* Cut the junk */
- lwz r2,saver2(r13) ; Get back interrupt time R2
- stw r0,LTR_r0(r20) /* Save off register 0 */
+ stw r17,LTR_timeLo(r20) ; Set the lower part of TB
+ lwz r18,saver2(r13) ; Get back interrupt time R2
+ stw r0,LTR_r0(r20) ; Save off register 0
lwz r3,saver3(r13) ; Restore this one
- sth r19,LTR_cpu(r20) /* Stash the cpu address */
- stw r1,LTR_r1(r20) /* Save off register 1 */
+ sth r19,LTR_cpu(r20) ; Stash the cpu number
+ stw r1,LTR_r1(r20) ; Save off register 1
lwz r4,saver4(r13) ; Restore this one
- stw r2,LTR_r2(r20) /* Save off register 2 */
+ stw r18,LTR_r2(r20) ; Save off register 2
lwz r5,saver5(r13) ; Restore this one
- stw r3,LTR_r3(r20) /* Save off register 3 */
- lwz r16,savecr(r13) /* We don't remember the CR anymore, get it */
- stw r4,LTR_r4(r20) /* Save off register 4 */
- mfsrr0 r17 /* Get this back, it's still good */
- stw r5,LTR_r5(r20) /* Save off register 5 */
- mfsrr1 r18 /* This is still good in here also */
-
- stw r16,LTR_cr(r20) /* Save the CR (or dec) */
- stw r17,LTR_srr0(r20) /* Save the SSR0 */
- stw r18,LTR_srr1(r20) /* Save the SRR1 */
- mfdar r17 /* Get this back */
-
- mflr r16 /* Get the LR */
- stw r17,LTR_dar(r20) /* Save the DAR */
- mfctr r17 /* Get the CTR */
- stw r16,LTR_lr(r20) /* Save the LR */
+ stw r3,LTR_r3(r20) ; Save off register 3
+ lwz r16,savecr(r13) ; Get the CR value
+ stw r4,LTR_r4(r20) ; Save off register 4
+ mfsrr0 r17 ; Get SRR0 back, it is still good
+ stw r5,LTR_r5(r20) ; Save off register 5
+ mfsrr1 r18 ; SRR1 is still good in here
+ stw r16,LTR_cr(r20) ; Save the CR
+ stw r17,LTR_srr0(r20) ; Save the SSR0
+ stw r18,LTR_srr1(r20) ; Save the SRR1
+ mfdar r17 ; Get this back
+ lwz r16,savelr(r13) ; Get the LR
+ stw r17,LTR_dar(r20) ; Save the DAR
+ mfctr r17 ; Get the CTR (still good in register)
+ stw r16,LTR_lr(r20) ; Save the LR
#if 0
- lis r17,HIGH_ADDR(EXT(saveanchor)) ; (TEST/DEBUG)
- ori r17,r17,LOW_ADDR(EXT(saveanchor)) ; (TEST/DEBUG)
- lwz r16,SVcount(r17) ; (TEST/DEBUG)
- lwz r17,SVinuse(r17) ; (TEST/DEBUG)
- rlwimi r17,r16,16,0,15 ; (TEST/DEBUG)
+ lwz r17,emfp1(r2) ; (TEST/DEBUG)
#endif
- stw r17,LTR_ctr(r20) /* Save off the CTR */
- stw r13,LTR_save(r20) /* Save the savearea */
- sth r11,LTR_excpt(r20) /* Save the exception type */
+ stw r17,LTR_ctr(r20) ; Save off the CTR
+ stw r13,LTR_save(r20) ; Save the savearea
+ sth r11,LTR_excpt(r20) ; Save the exception type
#if ESPDEBUG
addi r17,r20,32 ; (TEST/DEBUG)
dcbst br0,r20 ; (TEST/DEBUG)
sync ; (TEST/DEBUG)
#endif
-/*
- * We're done with the trace, except for maybe modifying the exception
- * code later on. So, that means that we need to save R20 and CR5, but
- * R0 to R5 are clear now.
- *
- * So, let's finish setting up the kernel registers now.
- */
-
-skipTrace2:
-
-#if PERFTIMES && DEBUG
- li r3,68 ; Indicate interrupt
- mr r4,r11 ; Get code to log
- mr r5,r13 ; Get savearea to log
- mr r8,r0 ; Save R0
- bl EXT(dbgLog2) ; Cut log entry
- mr r0,r8 ; Restore R0
-#endif
-
- mfsprg r2,0 /* Get the per processor block */
-
-#if CHECKSAVE
-
- lis r4,0x7FFF /* (TEST/DEBUG) */
- mfdec r12 /* (TEST/DEBUG) */
- or r4,r4,r12 /* (TEST/DEBUG) */
- mtdec r4 /* (TEST/DEBUG) */
- li r4,0x20 /* (TEST/DEBUG) */
-
- lwarx r8,0,r4 ; ?
-
-mpwait2: lwarx r8,0,r4 /* (TEST/DEBUG) */
- mr. r8,r8 /* (TEST/DEBUG) */
- bne- mpwait2 /* (TEST/DEBUG) */
- stwcx. r4,0,r4 /* (TEST/DEBUG) */
- bne- mpwait2 /* (TEST/DEBUG) */
-
- isync /* (TEST/DEBUG) */
- lwz r4,0xE80(br0) /* (TEST/DEBUG) */
- mr. r4,r4 /* (TEST/DEBUG) */
- li r4,1 /* (TEST/DEBUG) */
- bne- doncheksv /* (TEST/DEBUG) */
-
- lis r8,HIGH_ADDR(EXT(saveanchor)) /* (TEST/DEBUG) */
- ori r8,r8,LOW_ADDR(EXT(saveanchor)) /* (TEST/DEBUG) */
-
- stw r4,0xE80(br0) /* (TEST/DEBUG) */
-
- lwarx r4,0,r8 ; ?
-
-mpwait2x: lwarx r4,0,r8 /* (TEST/DEBUG) */
- mr. r4,r4 /* (TEST/DEBUG) */
- bne- mpwait2x /* (TEST/DEBUG) */
- stwcx. r8,0,r8 /* (TEST/DEBUG) */
- bne- mpwait2x /* (TEST/DEBUG) */
-
- isync /* (TEST/DEBUG) */
-
- rlwinm r4,r13,0,0,19 /* (TEST/DEBUG) */
- lwz r21,SACflags(r4) /* (TEST/DEBUG) */
- rlwinm r22,r21,24,24,31 /* (TEST/DEBUG) */
- cmplwi r22,0x00EE /* (TEST/DEBUG) */
- lwz r22,SACvrswap(r4) /* (TEST/DEBUG) */
- bnel- currbad /* (TEST/DEBUG) */
- andis. r21,r21,hi16(sac_perm) /* (TEST/DEBUG) */
- bne- currnotbad /* (TEST/DEBUG) */
- mr. r22,r22 /* (TEST/DEBUG) */
- bne+ currnotbad /* (TEST/DEBUG) */
-
-currbad: lis r23,hi16(EXT(debugbackpocket)) /* (TEST/DEBUG) */
- ori r23,r23,lo16(EXT(debugbackpocket)) /* (TEST/DEBUG) */
- lwz r23,0(r23) ; (TEST/DEBUG)
- stw r23,SVfree(r8) /* (TEST/DEBUG) */
-
- mfsprg r25,1 /* (TEST/DEBUG) */
- mtsprg 1,r23 /* (TEST/DEBUG) */
- lwz r26,SACalloc(r23) /* (TEST/DEBUG) */
- rlwinm r26,r26,0,1,31 /* (TEST/DEBUG) */
- stw r26,SACalloc(r23) /* (TEST/DEBUG) */
-
- sync /* (TEST/DEBUG) */
-
- li r3,0 /* (TEST/DEBUG) */
- stw r3,0x20(br0) /* (TEST/DEBUG) */
- stw r3,0(r8) /* (TEST/DEBUG) */
- lis r0,hi16(Choke) ; (TEST/DEBUG)
- ori r0,r0,lo16(Choke) ; (TEST/DEBUG)
- sc ; System ABEND
-
-currnotbad:
- lwz r28,SVcount(r8) /* (TEST/DEBUG) */
- lwz r21,SVinuse(r8) /* (TEST/DEBUG) */
- lwz r23,SVmin(r8) /* (TEST/DEBUG) */
- sub r22,r28,r21 /* (TEST/DEBUG) */
- cmpw r22,r23 /* (TEST/DEBUG) */
- bge+ cksave0 /* (TEST/DEBUG) */
-
- bl currbad ; (TEST/DEBUG)
-
-cksave0: lwz r28,SVfree(r8) /* (TEST/DEBUG) */
- li r24,0 /* (TEST/DEBUG) */
- li r29,1 /* (TEST/SAVE) */
-
-cksave0a: mr. r28,r28 /* (TEST/DEBUG) */
- beq- cksave3 /* (TEST/DEBUG) */
-
- rlwinm. r21,r28,0,4,19 /* (TEST/DEBUG) */
- bne+ cksave1 /* (TEST/DEBUG) */
-
- bl currbad ; (TEST/DEBUG)
-
-cksave1: rlwinm. r21,r28,0,21,3 /* (TEST/DEBUG) */
- beq+ cksave2 /* (TEST/DEBUG) */
-
- bl currbad ; (TEST/DEBUG)
-
-cksave2: lwz r25,SACalloc(r28) /* (TEST/DEBUG) */
- lbz r26,SACflags+2(r28) /* (TEST/DEBUG) */
- lbz r21,SACflags+3(r28) /* (TEST/DEBUG) */
- cmplwi r26,0x00EE /* (TEST/DEBUG) */
- stb r29,SACflags+3(r28) /* (TEST/DEBUG) */
- beq+ cksave2z
-
- bl currbad ; (TEST/DEBUG)
-
-cksave2z: mr. r21,r21 /* (TEST/DEBUG) */
- beq+ cksave2a /* (TEST/DEBUG) */
-
- bl currbad ; (TEST/DEBUG)
-
-cksave2a: rlwinm r26,r25,1,31,31 /* (TEST/DEBUG) */
- rlwinm r27,r25,2,31,31 /* (TEST/DEBUG) */
- add r24,r24,r26 /* (TEST/DEBUG) */
- add r24,r24,r27 /* (TEST/DEBUG) */
- lwz r28,SACnext(r28) /* (TEST/DEBUG) */
- b cksave0a /* (TEST/DEBUG) */
-
-cksave3: cmplw r24,r22 /* (TEST/DEBUG) */
- beq+ cksave4 /* (TEST/DEBUG) */
-
- bl currbad ; (TEST/DEBUG)
-
-cksave4: lwz r28,SVfree(r8) /* (TEST/DEBUG) */
- li r24,0 /* (TEST/DEBUG) */
-
-cksave5: mr. r28,r28 /* (TEST/DEBUG) */
- beq- cksave6 /* (TEST/DEBUG) */
- stb r24,SACflags+3(r28) /* (TEST/DEBUG) */
- lwz r28,SACnext(r28) /* (TEST/DEBUG) */
- b cksave5 /* (TEST/DEBUG) */
-
-cksave6:
-
- li r4,0 /* (TEST/DEBUG) */
- stw r4,0xE80(br0) /* (TEST/DEBUG) */
- stw r4,0(r8) /* (TEST/DEBUG) */
-
-doncheksv:
- li r4,0 /* (TEST/DEBUG) */
- stw r4,0x20(br0) /* (TEST/DEBUG) */
- mtdec r12 /* (TEST/DEBUG) */
-#endif
-
- lis r4,HIGH_ADDR(EXT(MPspec)) /* Get the MP control block */
- dcbt 0,r2 /* We'll need the per_proc in a sec */
- cmplwi cr0,r11,T_INTERRUPT /* Do we have an external interrupt? */
- ori r4,r4,LOW_ADDR(EXT(MPspec)) /* Get the bottom half of the MP control block */
- bne+ notracex /* Not an external... */
-
-/*
- * Here we check to see if there was a interprocessor signal
- */
-
- lwz r4,MPSSIGPhandler(r4) /* Get the address of the SIGP interrupt filter */
- lhz r3,PP_CPU_FLAGS(r2) /* Get the CPU flags */
- cmplwi cr1,r4,0 /* Check if signal filter is initialized yet */
- andi. r3,r3,LOW_ADDR(SIGPactive) /* See if this processor has started up */
- mtlr r4 /* Load up filter address */
- beq- cr1,notracex /* We don't have a filter yet... */
- beq- notracex /* This processor hasn't started filtering yet... */
-
- blrl /* Filter the interrupt */
-
- mfsprg r2,0 /* Make sure we have the per processor block */
- cmplwi cr0,r3,kMPIOInterruptPending /* See what the filter says */
- li r11,T_INTERRUPT /* Assume we have a regular external 'rupt */
- beq+ modRupt /* Yeah, we figured it would be... */
- li r11,T_SIGP /* Assume we had a signal processor interrupt */
- bgt+ modRupt /* Yeah, at this point we would assume so... */
- li r11,T_IN_VAIN /* Nothing there actually, so eat it */
-
-modRupt: stw r11,PP_SAVE_EXCEPTION_TYPE(r2) /* Set that it was either in vain or a SIGP */
- stw r11,saveexception(r13) /* Save the exception code here also */
- bne- cr5,notracex /* Jump if no tracing... */
- sth r11,LTR_excpt(r20) /* Save the exception type */
-
-notracex:
-
-#if 0
- bf featSMP,nopir6 /* (TEST/DEBUG) */
- mfspr r7,pir /* (TEST/DEBUG) */
- b gotpir6 /* (TEST/DEBUG) */
-nopir6: li r7,0 /* (TEST/DEBUG) */
-gotpir6: /* (TEST/DEBUG) */
- lis r6,HIGH_ADDR(EXT(RuptCtrs)) /* (TEST/DEBUG) */
- rlwinm r7,r7,8,23,23 /* (TEST/DEBUG) */
- lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- rlwimi r7,r7,1,22,22 /* (TEST/DEBUG) */
- ori r6,r6,LOW_ADDR(EXT(RuptCtrs)) /* (TEST/DEBUG) */
- rlwinm r1,r11,2,0,29 /* (TEST/DEBUG) */
- add r6,r6,r7 /* (TEST/DEBUG) */
- ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- lwz r21,(47*16)+8(r6) /* (TEST/DEBUG) */
- lwz r22,(47*16)+12(r6) /* (TEST/DEBUG) */
- add r1,r1,r6 /* (TEST/DEBUG) */
- mftb r24 /* (TEST/DEBUG) */
- sub r22,r24,r22 /* (TEST/DEBUG) */
- lwz r4,4(r6) /* (TEST/DEBUG) */
- cmplw cr2,r22,r21 /* (TEST/DEBUG) */
- lwz r7,4(r1) /* (TEST/DEBUG) */
- lwz r21,8(r6) /* (TEST/DEBUG) */
- blt+ cr2,nottime /* (TEST/DEBUG) */
- stw r24,(47*16)+12(r6) /* (TEST/DEBUG) */
-
-nottime: addi r4,r4,1 /* (TEST/DEBUG) */
- lwz r22,8(r1) /* (TEST/DEBUG) */
- addi r7,r7,1 /* (TEST/DEBUG) */
- stw r4,4(r6) /* (TEST/DEBUG) */
- lwz r3,0(r6) /* (TEST/DEBUG) */
- mr. r21,r21 /* (TEST/DEBUG) */
- stw r7,4(r1) /* (TEST/DEBUG) */
- mtlr r12 /* (TEST/DEBUG) */
- lwz r1,0(r1) /* (TEST/DEBUG) */
- beq- nottimed1 /* (TEST/DEBUG) */
- blt+ cr2,isnttime1 /* (TEST/DEBUG) */
-
-nottimed1: mr. r3,r3 /* (TEST/DEBUG) */
- bgelrl+ /* (TEST/DEBUG) */
-
-isnttime1: mr. r22,r22 /* (TEST/DEBUG) */
- beq- nottimed2 /* (TEST/DEBUG) */
- blt+ cr2,isnttime2 /* (TEST/DEBUG) */
-
-nottimed2: mr. r3,r1 /* (TEST/DEBUG) */
- mtlr r12 /* (TEST/DEBUG) */
- mr r4,r7 /* (TEST/DEBUG) */
- bgelrl+ /* (TEST/DEBUG) */
- mr r3,r11 /* (TEST/DEBUG) */
-
-isnttime2: cmplwi r11,T_DATA_ACCESS /* (TEST/DEBUG) */
- lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- bne+ nodsidisp /* (TEST/DEBUG) */
- mr. r22,r22 /* (TEST/DEBUG) */
- beq- nottimed3 /* (TEST/DEBUG) */
- blt+ cr2,nodsidisp /* (TEST/DEBUG) */
-
-nottimed3: li r3,5 /* (TEST/DEBUG) */
- ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- lwz r4,savesrr0(r13) /* (TEST/DEBUG) */
- mtlr r12 /* (TEST/DEBUG) */
- blrl /* (TEST/DEBUG) */
-
- lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- lis r3,9 /* (TEST/DEBUG) */
- ori r3,r3,5 /* (TEST/DEBUG) */
- mtlr r12 /* (TEST/DEBUG) */
- lwz r4,savedar(r13) /* (TEST/DEBUG) */
- blrl /* (TEST/DEBUG) */
-
-nodsidisp: cmplwi r11,T_INSTRUCTION_ACCESS /* (TEST/DEBUG) */
- lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- bne+ noisidisp /* (TEST/DEBUG) */
- mr. r22,r22 /* (TEST/DEBUG) */
- beq- nottimed4 /* (TEST/DEBUG) */
- blt+ cr2,noisidisp /* (TEST/DEBUG) */
-
-nottimed4: li r3,6 /* (TEST/DEBUG) */
- ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- lwz r4,savesrr0(r13) /* (TEST/DEBUG) */
- mtlr r12 /* (TEST/DEBUG) */
- blrl /* (TEST/DEBUG) */
-
-noisidisp: mr r3,r11 /* (TEST/DEBUG) */
-#endif
-
-#if 0
- cmplwi r11,T_PROGRAM /* (TEST/DEBUG) */
- lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- bne+ nopgmdisp /* (TEST/DEBUG) */
- li r3,7 /* (TEST/DEBUG) */
- ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */
- lwz r4,savesrr0(r13) /* (TEST/DEBUG) */
- mtlr r12 /* (TEST/DEBUG) */
- blrl /* (TEST/DEBUG) */
-
-nopgmdisp: mr r3,r11 /* (TEST/DEBUG) */
-#endif
+;
+; We are done with the trace, except for maybe modifying the exception
+; code later on. So, that means that we need to save R20 and CR5.
+;
+; So, finish setting up the kernel registers now.
+;
- li r21,0 ; Assume no processor register for now
+skipTrace: lhz r21,PP_CPU_NUMBER(r2) ; Get the logical processor number
lis r12,hi16(EXT(hw_counts)) ; Get the high part of the interrupt counters
- bf featSMP,nopirhere ; Jump if this processor does not have a PIR...
- mfspr r21,pir ; Get the PIR
-
-nopirhere: ori r12,r12,lo16(EXT(hw_counts)) ; Get the low part of the interrupt counters
lwz r7,savesrr1(r13) ; Get the entering MSR
+ ori r12,r12,lo16(EXT(hw_counts)) ; Get the low part of the interrupt counters
rlwinm r21,r21,8,20,23 ; Get index to processor counts
- mtcrf 0x80,r0 /* Set our CR0 to the high nybble of the request code */
- rlwinm r6,r0,1,0,31 /* Move sign bit to the end */
- cmplwi cr1,r11,T_SYSTEM_CALL /* Did we get a system call? */
- crandc cr0_lt,cr0_lt,cr0_gt /* See if we have R0 equal to 0b10xx...x */
+ mtcrf 0x80,r0 ; Set our CR0 to the high nybble of possible syscall code
+ rlwinm r6,r0,1,0,31 ; Move sign bit to the end
+ cmplwi cr1,r11,T_SYSTEM_CALL ; Did we get a system call?
add r12,r12,r21 ; Point to the processor count area
- cmplwi cr3,r11,T_IN_VAIN /* Was this all in vain? All for nothing? */
+ crandc cr0_lt,cr0_lt,cr0_gt ; See if we have R0 equal to 0b10xx...x
lwzx r22,r12,r11 ; Get the old value
- cmplwi cr2,r6,1 /* See if original R0 had the CutTrace request code in it */
+ cmplwi cr3,r11,T_IN_VAIN ; Was this all in vain? All for nothing?
addi r22,r22,1 ; Count this one
- cmplwi cr4,r11,T_SIGP /* Indicate if we had a SIGP 'rupt */
+ cmplwi cr2,r6,1 ; See if original R0 had the CutTrace request code in it
stwx r22,r12,r11 ; Store it back
- beq- cr3,EatRupt /* Interrupt was all for nothing... */
+ beq- cr3,EatRupt ; Interrupt was all for nothing...
cmplwi cr3,r11,T_MACHINE_CHECK ; Did we get a machine check?
- bne+ cr1,noCutT /* Not a system call... */
- bnl+ cr0,noCutT /* R0 not 0b10xxx...x, can't be any kind of magical system call... */
+ bne+ cr1,noCutT ; Not a system call...
+ bnl+ cr0,noCutT ; R0 not 0b10xxx...x, can not be any kind of magical system call...
rlwinm. r7,r7,0,MSR_PR_BIT,MSR_PR_BIT ; Did we come from user state?
lis r1,hi16(EXT(dgWork)) ; Get the diagnostics flags
beq+ FCisok ; From supervisor state...
rlwinm. r1,r1,0,enaUsrFCallb,enaUsrFCallb ; Are they valid?
beq- noCutT ; No...
-FCisok: beq- cr2,isCutTrace /* This is a CutTrace system call */
+FCisok: beq- cr2,isCutTrace ; This is a CutTrace system call...
-/*
- * Here's where we call the firmware. If it returns T_IN_VAIN, that means
- * that it has handled the interruption. Remember: thou shalt not trash R13
- * or R20 while you are away. Anything else is ok.
- */
-
- lis r1,hi16(EXT(FirmwareCall)) /* Top half of firmware call handler */
- ori r1,r1,lo16(EXT(FirmwareCall)) /* Bottom half of it */
- lwz r3,saver3(r13) /* Restore the first parameter, the rest are ok already */
- mtlr r1 /* Get it in the link register */
- blrl /* Call the handler */
-
- cmplwi r3,T_IN_VAIN /* Was it handled? */
- mfsprg r2,0 /* Restore the per_processor area */
- beq+ EatRupt /* Interrupt was handled... */
- mr r11,r3 /* Put the 'rupt code in the right register */
- b noSIGP /* Go to the normal system call handler */
+;
+; Here is where we call the firmware. If it returns T_IN_VAIN, that means
+; that it has handled the interruption. Remember: thou shalt not trash R13
+; or R20 while you are away. Anything else is ok.
+;
+
+ lwz r3,saver3(r13) ; Restore the first parameter
+ bl EXT(FirmwareCall) ; Go handle the firmware call....
+
+ cmplwi r3,T_IN_VAIN ; Was it handled?
+ mfsprg r2,0 ; Restore the per_proc
+ beq+ EatRupt ; Interrupt was handled...
+ mr r11,r3 ; Put the rupt code into the right register
+ b filter ; Go to the normal system call handler...
+
+ .align 5
isCutTrace:
- li r7,-32768 /* Get a 0x8000 for the exception code */
- bne- cr5,EatRupt /* Tracing is disabled... */
- sth r7,LTR_excpt(r20) /* Modify the exception type to a CutTrace */
- b EatRupt /* Time to go home... */
+ li r7,-32768 ; Get a 0x8000 for the exception code
+ bne- cr5,EatRupt ; Tracing is disabled...
+ sth r7,LTR_excpt(r20) ; Modify the exception type to a CutTrace
+ b EatRupt ; Time to go home...
-/* We are here 'cause we didn't have a CutTrace system call */
+; We are here because we did not have a CutTrace system call
+
+ .align 5
noCutT: beq- cr3,MachineCheck ; Whoa... Machine check...
- bne+ cr4,noSIGP /* Skip away if we didn't get a SIGP... */
-
- lis r6,HIGH_ADDR(EXT(MPsignalFW)) /* Top half of SIGP handler */
- ori r6,r6,LOW_ADDR(EXT(MPsignalFW)) /* Bottom half of it */
- mtlr r6 /* Get it in the link register */
-
- blrl /* Call the handler - we'll only come back if this is an AST, */
- /* 'cause FW can't handle that */
- mfsprg r2,0 /* Restore the per_processor area */
+
;
; The following interrupts are the only ones that can be redriven
; by the higher level code or emulation routines.
;
-Redrive: cmplwi cr0,r3,T_IN_VAIN /* Did the signal handler eat the signal? */
- mr r11,r3 /* Move it to the right place */
- beq+ cr0,EatRupt /* Bail now if the signal handler processed the signal... */
+Redrive: cmplwi cr0,r11,T_IN_VAIN ; Did the signal handler eat the signal?
+ mfsprg r2,0 ; Get the per_proc block
+ beq+ cr0,EatRupt ; Bail now if we ate the rupt...
-/*
- * Here's where we check for the other fast-path exceptions: translation exceptions,
- * emulated instructions, etc.
- */
+;
+; Here ss where we check for the other fast-path exceptions: translation exceptions,
+; emulated instructions, etc.
+;
-noSIGP: cmplwi cr3,r11,T_ALTIVEC_ASSIST ; Check for an Altivec denorm assist
- cmplwi cr1,r11,T_PROGRAM /* See if we got a program exception */
- cmplwi cr2,r11,T_INSTRUCTION_ACCESS /* Check on an ISI */
+filter: cmplwi cr3,r11,T_ALTIVEC_ASSIST ; Check for an Altivec denorm assist
+ cmplwi cr4,r11,T_ALIGNMENT ; See if we got an alignment exception
+ cmplwi cr1,r11,T_PROGRAM ; See if we got a program exception
+ cmplwi cr2,r11,T_INSTRUCTION_ACCESS ; Check on an ISI
bne+ cr3,noAltivecAssist ; It is not an assist...
b EXT(AltivecAssist) ; It is an assist...
+
+ .align 5
noAltivecAssist:
+ bne+ cr4,noAlignAssist ; No alignment here...
+ b EXT(AlignAssist) ; Go try to emulate...
+
+ .align 5
+
+noAlignAssist:
bne+ cr1,noEmulate ; No emulation here...
b EXT(Emulate) ; Go try to emulate...
-noEmulate: cmplwi cr3,r11,T_CSWITCH /* Are we context switching */
- cmplwi r11,T_DATA_ACCESS /* Check on a DSI */
- beq- cr2,DSIorISI /* It's a PTE fault... */
- beq- cr3,conswtch /* It's a context switch... */
- bne+ PassUp /* It's not a PTE fault... */
+ .align 5
-/*
- * This call will either handle the fault, in which case it will not
- * return, or return to pass the fault up the line.
- */
+noEmulate: cmplwi cr3,r11,T_CSWITCH ; Are we context switching
+ cmplwi r11,T_DATA_ACCESS ; Check on a DSI
+ beq- cr2,DSIorISI ; It is a PTE fault...
+ beq- cr3,conswtch ; It is a context switch...
+ bne+ PassUp ; It is not a PTE fault...
+
+;
+; This call will either handle the fault, in which case it will not
+; return, or return to pass the fault up the line.
+;
-DSIorISI:
- lis r7,HIGH_ADDR(EXT(handlePF)) /* Top half of DSI handler */
- ori r7,r7,LOW_ADDR(EXT(handlePF)) /* Bottom half of it */
- mtlr r7 /* Get it in the link register */
- mr r3,r11 /* Move the 'rupt code */
+DSIorISI: mr r3,r11 ; Move the rupt code
- blrl /* See if we can handle this fault */
+ bl EXT(handlePF) ; See if we can handle this fault
lwz r0,savesrr1(r13) ; Get the MSR in use at exception time
- mfsprg r2, 0 /* Get back per_proc */
+ mfsprg r2,0 ; Get back per_proc
cmplwi cr1,r3,T_IN_VAIN ; Was it handled?
andi. r4,r0,lo16(MASK(MSR_RI)) ; See if the recover bit is on
- mr r11,r3 /* Make sure we can find this later */
+ mr r11,r3 ; Put interrupt code back into the right register
beq+ cr1,EatRupt ; Yeah, just blast back to the user...
- andc r0,r0,r4 ; Remove the recover bit
beq+ PassUp ; Not on, normal case...
+;
+; Here is where we handle the "recovery mode" stuff.
+; This is set by an emulation routine to trap any faults when it is fetching data or
+; instructions.
+;
+; If we get a fault, we turn off RI, set CR0_EQ to false, bump the PC, and set R0
+; and R1 to the DAR and DSISR, respectively.
+;
lwz r4,savesrr0(r13) ; Get the failing instruction address
lwz r5,savecr(r13) ; Get the condition register
- stw r0,savesrr1(r13) ; Save the result MSR
addi r4,r4,4 ; Skip failing instruction
+ lwz r6,savedar(r13) ; Get the DAR
rlwinm r5,r5,0,3,1 ; Clear CR0_EQ to let emulation code know we failed
- stw r4,savesrr0(r13) ; Save instruction address
- stw r4,savecr(r13) ; And the resume CR
+ lwz r7,savedsisr(r13) ; Grab the DSISR
+ stw r0,savesrr1(r13) ; Save the result MSR
+ stw r4,savesrr0(r13) ; Save resume address
+ stw r5,savecr(r13) ; And the resume CR
+ stw r6,saver0(r13) ; Pass back the DAR
+ stw r7,saver1(r13) ; Pass back the DSISR
b EatRupt ; Resume emulated code
-/*
- * Here is where we handle the context switch firmware call. The old
- * context has been saved, and the new savearea in in saver3. We'll just
- * muck around with the savearea pointers, and then join the exit routine
- */
-conswtch: lwz r28,SAVflags(r13) /* The the flags of the current */
- mr r29,r13 /* Save the save */
- rlwinm r30,r13,0,0,19 /* Get the start of the savearea block */
- lwz r5,saver3(r13) /* Switch to the new savearea */
- oris r28,r28,HIGH_ADDR(SAVattach) /* Turn on the attached flag */
- lwz r30,SACvrswap(r30) /* get real to virtual translation */
- mr r13,r5 /* Switch saveareas */
- xor r27,r29,r30 /* Flip to virtual */
- stw r28,SAVflags(r29) /* Stash it back */
- stw r27,saver3(r5) /* Push the new savearea to the switch to routine */
- b EatRupt /* Start 'er up... */
+;
+; Here is where we handle the context switch firmware call. The old
+; context has been saved, and the new savearea in in saver3. We will just
+; muck around with the savearea pointers, and then join the exit routine
+;
+
+ .align 5
+
+conswtch:
+ mr r29,r13 ; Save the save
+ rlwinm r30,r13,0,0,19 ; Get the start of the savearea block
+ lwz r5,saver3(r13) ; Switch to the new savearea
+ lwz r30,SACvrswap(r30) ; get real to virtual translation
+ mr r13,r5 ; Switch saveareas
+ xor r27,r29,r30 ; Flip to virtual
+ stw r27,saver3(r5) ; Push the new savearea to the switch to routine
+ b EatRupt ; Start it up...
;
; Handle machine check here.
;
; ?
;
+
+ .align 5
+
MachineCheck:
+
lwz r27,savesrr1(r13) ; ?
rlwinm. r11,r27,0,dcmck,dcmck ; ?
beq+ notDCache ; ?
sync ; ?
- li r11,T_IN_VAIN ; ?
b EatRupt ; ?
+ .align 5
notDCache:
;
stw r28,savesrr0(r13) ; Set the return point
stw r27,savesrr1(r13) ; Set the continued MSR
stw r30,saver3(r13) ; Set return code
- li r11,T_IN_VAIN ; Set new interrupt code
b EatRupt ; Yum, yum, eat it all up...
/*
LEXT(EmulExit)
- cmplwi r11,T_IN_VAIN /* Was it emulated? */
+ cmplwi r11,T_IN_VAIN ; Was it emulated?
lis r1,hi16(SAVredrive) ; Get redrive request
mfsprg r2,0 ; Restore the per_proc area
- beq+ EatRupt /* Yeah, just blast back to the user... */
+ beq+ EatRupt ; Yeah, just blast back to the user...
lwz r4,SAVflags(r13) ; Pick up the flags
and. r0,r4,r1 ; Check if redrive requested
beq+ PassUp ; No redrive, just keep on going...
- lwz r3,saveexception(r13) ; Restore exception code
stw r4,SAVflags(r13) ; Set the flags
b Redrive ; Redrive the exception...
-/* Jump into main handler code switching on VM at the same time */
+;
+; Jump into main handler code switching on VM at the same time.
+;
+; We assume kernel data is mapped contiguously in physical
+; memory, otherwise we would need to switch on (at least) virtual data.
+; SRs are already set up.
+;
+
+ .align 5
-/* We assume kernel data is mapped contiguously in physical
- * memory, otherwise we'd need to switch on (at least) virtual data.
- * SRs are already set up.
- */
PassUp: lis r2,hi16(EXT(exception_handlers)) ; Get exception vector address
ori r2,r2,lo16(EXT(exception_handlers)) ; And low half
- lwzx r6,r2,r11 /* Get the actual exception handler address */
-
-PassUpDeb: lwz r8,SAVflags(r13) /* Get the flags */
- mtsrr0 r6 /* Set up the handler address */
- oris r8,r8,HIGH_ADDR(SAVattach) /* Since we're passing it up, attach it */
- rlwinm r5,r13,0,0,19 /* Back off to the start of savearea block */
-
- mfmsr r3 /* Get our MSR */
- stw r8,SAVflags(r13) /* Pass up the flags */
- rlwinm r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1 /* Clear all but the trace bits */
- li r2,MSR_SUPERVISOR_INT_OFF /* Get our normal MSR value */
- lwz r5,SACvrswap(r5) /* Get real to virtual conversion */
- or r2,r2,r3 /* Keep the trace bits if they're on */
- mr r3,r11 /* Pass the exception code in the paramter reg */
- mtsrr1 r2 /* Set up our normal MSR value */
- xor r4,r13,r5 /* Pass up the virtual address of context savearea */
-
- rfi /* Launch the exception handler */
-
- .long 0 /* Leave these here gol durn it! */
+ lwzx r6,r2,r11 ; Get the actual exception handler address
+
+PassUpDeb: mtsrr0 r6 ; Set up the handler address
+ rlwinm r5,r13,0,0,19 ; Back off to the start of savearea block
+
+ mfmsr r3 ; Get our MSR
+ rlwinm r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1 ; Clear all but the trace bits
+ li r2,MSR_SUPERVISOR_INT_OFF ; Get our normal MSR value
+ lwz r5,SACvrswap(r5) ; Get real to virtual conversion
+ or r2,r2,r3 ; Keep the trace bits if they are on
+ mr r3,r11 ; Pass the exception code in the paramter reg
+ mtsrr1 r2 ; Set up our normal MSR value
+ xor r4,r13,r5 ; Pass up the virtual address of context savearea
+
+ rfi ; Launch the exception handler
+
+ .long 0 ; Leave these here gol durn it!
.long 0
.long 0
.long 0
* before we get here.
*
* Speaking of tomfoolery, this is where we synthesize interruptions
- * if any need to be.
+ * if we need to.
*/
.align 5
-EatRupt: mr r31,r13 /* Move the savearea pointer to the far end of the register set */
-
-EatRupt2: mfsprg r2,0 /* Get the per_proc block */
- dcbt 0,r31 ; Get this because we need it very soon
-
-#if TRCSAVE
- lwz r30,saver0(r31) ; (TEST/DEBUG) Get users R0
- lwz r20,saveexception(r31) ; (TEST/DEBUG) Returning from trace?
- xor r30,r20,r30 ; (TEST/DEBUG) Make code
- rlwinm r30,r30,1,0,31 ; (TEST/DEBUG) Make an easy test
- cmplwi cr5,r30,0x61 ; (TEST/DEBUG) See if this is a trace
-#endif
-
-/*
- * First we see if we are able to free the new savearea.
- * If it is not attached to anything, put it on the free list.
- * This is real dangerous, we haven't restored context yet...
- * So, the free savearea chain lock must stay until the bitter end!
- */
+EatRupt: mfsprg r29,0 ; Get the per_proc block back
+ mr r31,r13 ; Move the savearea pointer to the far end of the register set
+
+ lwz r30,quickfret(r29) ; Pick up the quick fret list, if any
-/*
- * It's dangerous here. We haven't restored anything from the current savearea yet.
- * And, we mark it the active one. So, if we get an exception in here, it is
- * unrecoverable. Unless we mess up, we can't get any kind of exception. So,
- * it is important to assay this code as only the purest of gold.
- *
- * But first, see if there is a savearea hanging off of quickfret. If so,
- * we release that one first and then come back for the other. We should rarely
- * see one, they appear when FPU or VMX context is discarded by either returning
- * to a higher exception level, or explicitly.
- *
- * A word about QUICKFRET: Multiple saveareas may be queued for release. It is
- * the responsibility of the queuer to insure that the savearea is not multiply
- * queued and that the appropriate inuse bits are reset.
- */
+ mfsprg r27,2 ; Get the processor features
+ lwz r21,savesrr1(r31) ; Get destination MSR
+
+erchkfret: mr. r3,r30 ; Any savearea to quickly release?
+ beq+ ernoqfret ; No quickfrets...
+ lwz r30,SAVprev(r30) ; Chain back now
+
+ bl EXT(save_ret_phys) ; Put it on the free list
+ stw r30,quickfret(r29) ; Dequeue previous guy (really, it is ok to wait until after the release)
+ b erchkfret ; Try the next one...
-
- mfsprg r27,2 ; Get the processor features
- lwz r1,savesrr1(r31) ; Get destination MSR
- mtcrf 0x60,r27 ; Set CRs with thermal facilities
- mr r18,r31 ; Save the savearea pointer
- rlwinm. r0,r1,0,MSR_EE_BIT,MSR_EE_BIT ; Are interruptions going to be enabled?
- lwz r19,PP_QUICKFRET(r2) ; Get the quick release savearea
+ .align 5
+
+ernoqfret: mtcrf 0x60,r27 ; Set CRs with thermal facilities
+ rlwinm. r0,r21,0,MSR_EE_BIT,MSR_EE_BIT ; Are interruptions going to be enabled?
crandc 31,pfThermalb,pfThermIntb ; See if we have both thermometer and not interrupt facility
- li r0,0 ; Get a zero
- crandc 31,31,cr0_eq ; Factor in enablement
- la r21,savesr0(r18) ; Point to the first thing we restore
+ la r21,saver0(r31) ; Point to the first thing we restore
+ crandc 31,cr0_eq,31 ; Factor in enablement
bf 31,tempisok ; No thermal checking needed...
;
andc r14,r14,r0 ; Keep low if high did not interrupt, zero if it did
bne+ tempisok ; Nope, temprature is in range
- li r3,T_THERMAL ; Time to emulate a thermal interruption
+ li r11,T_THERMAL ; Time to emulate a thermal interruption
or r14,r14,r15 ; Get contents of interrupting register
mr r13,r31 ; Make sure savearea is pointed to correctly
- stw r3,saveexception(r31) ; Restore exception code
+ stw r11,saveexception(r31) ; Set the exception code
stw r14,savedar(r31) ; Set the contents of the interrupting register into the dar
- b Redrive ; Go process this new interruption...
+;
+; This code is here to prevent a problem that will probably never happen. If we are
+; returning from an emulation routine (alignment, altivec assist, etc.) the SRs may
+; not be set to the proper kernel values. Then, if we were to emulate a thermal here,
+; we would end up running in the kernel with a bogus SR. So, to prevent
+; this unfortunate circumstance, we slam the SRs here. (I worry too much...)
+;
-tempisok: lis r30,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
- stw r0,PP_QUICKFRET(r2) /* Clear quickfret pointer */
- ori r30,r30,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
- dcbt 0,r21 /* Touch in the first thing */
-
-#if 0
- li r23,0 ; (TEST/DEBUG)
- rlwinm r14,r31,0,0,19 ; (TEST/DEBUG)
- lwz r21,SACflags(r14) ; (TEST/DEBUG)
- rlwinm r22,r21,24,24,31 ; (TEST/DEBUG)
- cmplwi r22,0x00EE ; (TEST/DEBUG)
- beq+ nodienodie1 ; (TEST/DEBUG)
-
-dodiedodie: li r1,0x666 ; (TEST/DEBUG)
- BREAKPOINT_TRAP ; (TEST/DEBUG)
-
-nodienodie1:
- mr r23,r19 ; (TEST/DEBUG)
-
-chkitagain: mr. r23,r23 ; (TEST/DEBUG)
- beq nodienodie2 ; (TEST/DEBUG)
- rlwinm r14,r23,0,0,19 ; (TEST/DEBUG)
- lwz r21,SACflags(r14) ; (TEST/DEBUG)
- rlwinm r22,r21,24,24,31 ; (TEST/DEBUG)
- cmplwi r22,0x00EE ; (TEST/DEBUG)
- bne- dodiedodie ; (TEST/DEBUG)
- lwz r23,SAVqfret(r23) ; (TEST/DEBUG)
- b chkitagain ; (TEST/DEBUG)
-
-nodienodie2:
-#endif
+ lis r30,hi16(KERNEL_SEG_REG0_VALUE) ; Get the high half of the kernel SR0 value
+ mtsr sr0,r30 ; Set the kernel SR0
+ addis r30,r30,0x0010 ; Point to the second segment of kernel
+ mtsr sr1,r30 ; Set the kernel SR1
+ addis r30,r30,0x0010 ; Point to the third segment of kernel
+ mtsr sr2,r30 ; Set the kernel SR2
+ addis r30,r30,0x0010 ; Point to the third segment of kernel
+ mtsr sr3,r30 ; Set the kernel SR3
+ b Redrive ; Go process this new interruption...
-#if TRCSAVE
- beq- cr5,trkill0 ; (TEST/DEBUG) Do not trace this type
- lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
- mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
- beq- trkill0 ; (TEST/DEBUG) yes...
- bl cte ; (TEST/DEBUG) Trace this
- stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
- stw r19,LTR_r2(r20) ; (TEST/DEBUG) Quickfret savearea
-trkill0:
-#endif
-rtlck: lwarx r22,0,r30 /* Grab the lock value */
- li r23,1 /* Use part of the delay time */
- mr. r22,r22 /* Is it locked? */
- bne- rtlcks /* Yeah, wait for it to clear... */
- stwcx. r23,0,r30 /* Try to seize that there durn lock */
- beq+ fretagain ; Got it...
- b rtlck /* Collision, try again... */
+tempisok: dcbt 0,r21 ; Touch in the first thing we need
-rtlcks: lwz r22,SVlock(r30) /* Get that lock in here */
- mr. r22,r22 /* Is it free yet? */
- beq+ rtlck /* Yeah, try for it again... */
- b rtlcks /* Sniff away... */
-
;
-; Lock gotten, toss the saveareas
+; Here we release the savearea.
;
-fretagain: isync ; Toss those prefetches
-#if TRCSAVE
- beq- cr5,trkill1 ; (TEST/DEBUG) Do not trace this type
- lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
- mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
- beq- trkill1 ; (TEST/DEBUG) yes...
- li r0,1 ; (TEST/DEBUG) ID number
- bl cte ; (TEST/DEBUG) Trace this
- stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
- stw r19,LTR_r2(r20) ; (TEST/DEBUG) Quickfret savearea
-trkill1:
-#endif
-
- mr. r18,r18 ; Are we actually done here?
- beq- donefret ; Yeah...
- mr. r31,r19 ; Is there a quickfret to do?
- beq+ noqfrt ; Nope...
- lwz r19,SAVqfret(r19) ; Yes, get the next in line
-#if TRCSAVE
- beq- cr5,trkill2 ; (TEST/DEBUG) Do not trace this type
- lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
- mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
- beq- trkill2 ; (TEST/DEBUG) yes...
- li r0,2 ; (TEST/DEBUG) ID number
- bl cte ; (TEST/DEBUG) Trace this
- stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
- stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea
- stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
-trkill2:
-#endif
- b doqfrt ; Go do it...
-
-noqfrt: mr r31,r18 ; Set the area to release
- li r18,0 ; Show we have done it
-#if TRCSAVE
- beq- cr5,trkill3 ; (TEST/DEBUG) Do not trace this type
- lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
- mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
- beq- trkill3 ; (TEST/DEBUG) yes...
- li r0,3 ; (TEST/DEBUG) ID number
- bl cte ; (TEST/DEBUG) Trace this
- stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
- stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea
- stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
-trkill3:
-#endif
-
-doqfrt: li r0,0 ; Get a constant 0
- lis r26,0x8000 /* Build a bit mask and assume first savearea */
- stw r0,SAVqfret(r31) ; Make sure back chain is unlinked
- lwz r28,SAVflags(r31) ; Get the flags for the old active one
-#if TRCSAVE
- beq- cr5,trkill4 ; (TEST/DEBUG) Do not trace this type
- lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
- mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
- beq- trkill4 ; (TEST/DEBUG) yes...
- li r0,4 ; (TEST/DEBUG) ID number
- bl cte ; (TEST/DEBUG) Trace this
- stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
- stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea
- stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
- stw r28,LTR_r4(r20) ; (TEST/DEBUG) Save current flags
-trkill4:
-#endif
- rlwinm r25,r31,21,31,31 /* Get position of savearea in block */
- andis. r28,r28,HIGH_ADDR(SAVinuse) /* See if we need to free it */
- srw r26,r26,r25 /* Get bit position to deallocate */
- rlwinm r29,r31,0,0,19 /* Round savearea pointer to even page address */
-
- bne- fretagain /* Still in use, we can't free this one... */
-
- lwz r23,SACalloc(r29) /* Get the allocation for this block */
- lwz r24,SVinuse(r30) /* Get the in use count */
- mr r28,r23 ; (TEST/DEBUG) save for trace
- or r23,r23,r26 /* Turn on our bit */
- subi r24,r24,1 /* Show that this one is free */
- cmplw r23,r26 /* Is our's the only one free? */
- stw r23,SACalloc(r29) /* Save it out */
- bne+ rstrest /* Nope, then the block is already on the free list */
-
- lwz r22,SVfree(r30) /* Get the old head of the free list */
- stw r29,SVfree(r30) /* Point the head at us now */
- stw r22,SACnext(r29) ; Point us to the old last
-
-rstrest: stw r24,SVinuse(r30) /* Set the in use count */
-#if TRCSAVE
- beq- cr5,trkill5 ; (TEST/DEBUG) Do not trace this type
- lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask
- mr. r14,r14 ; (TEST/DEBUG) Is it stopped?
- beq- trkill5 ; (TEST/DEBUG) yes...
- li r0,5 ; (TEST/DEBUG) ID number
- bl cte ; (TEST/DEBUG) Trace this
- stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea
- stw r19,LTR_r2(r20) ; (TEST/DEBUG) Next quickfret savearea
- stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss
- stw r28,LTR_srr1(r20) ; (TEST/DEBUG) Save the original allocation
- stw r23,LTR_dar(r20) ; (TEST/DEBUG) Save the new allocation
- stw r24,LTR_save(r20) ; (TEST/DEBUG) Save the new in use count
- stw r22,LTR_lr(r20) ; (TEST/DEBUG) Save the old top of free list
- stw r29,LTR_ctr(r20) ; (TEST/DEBUG) Save the new top of free list
-trkill5:
-#endif
- b fretagain ; Go finish up the rest...
-
+; Important!!!! The savearea is released before we are done with it. When the
+; local free savearea list (anchored at lclfree) gets too long, save_ret_phys
+; will trim the list, making the extra saveareas allocatable by another processor
+; The code in there must ALWAYS leave our savearea on the local list, otherwise
+; we could be very, very unhappy. The code there always queues the "just released"
+; savearea to the head of the local list. Then, if it needs to trim, it will
+; start with the SECOND savearea, leaving ours intact.
;
; Build the SR values depending upon destination. If we are going to the kernel,
; the SRs are almost all the way set up. SR14 (or the currently used copyin/out register)
; they are different that what was loaded last time (i.e., tasks have switched).
; We check the last loaded address space ID and if the same, we skip the loads.
; This is a performance gain because SR manipulations are slow.
+;
+; There is also the special case when MSR_RI is set. This happens when we are trying to
+; make a special user state access when we are in the kernel. If we take an exception when
+; during that, the SRs may have been modified. Therefore, we need to restore them to
+; what they were before the exception because they could be non-standard. We saved them
+; during exception entry, so we will just load them here.
;
- .align 5
-
-donefret: lwz r26,savesrr1(r31) ; Get destination state flags
- lwz r7,PP_USERPMAP(r2) ; Pick up the user pmap we may launch
+ mr r3,r31 ; Get the exiting savearea in parm register
+ bl EXT(save_ret_phys) ; Put it on the free list
+
+ li r3,savesrr1 ; Get offset to the srr1 value
+
+ lwarx r26,r3,r31 ; Get destination MSR and take reservation along the way (just so we can blow it away)
+ lwz r7,PP_USERPMAP(r29) ; Pick up the user pmap we may launch
+ rlwinm. r17,r26,0,MSR_RI_BIT,MSR_RI_BIT ; See if we are returning from a special fault
cmplw cr3,r14,r14 ; Set that we do not need to stop streams
- rlwinm. r17,r26,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are going to user or system
+
+ beq+ nSpecAcc ; Do not reload the kernel SRs if this is not a special access...
+
+ lwz r14,savesr0(r31) ; Get SR0 at fault time
+ mtsr sr0,r14 ; Set SR0
+ lwz r14,savesr1(r31) ; Get SR1 at fault time
+ mtsr sr1,r14 ; Set SR1
+ lwz r14,savesr2(r31) ; Get SR2 at fault time
+ mtsr sr2,r14 ; Set SR2
+ lwz r14,savesr3(r31) ; Get SR3 at fault timee
+ mtsr sr3,r14 ; Set SR3
+ b segsdone ; We are all set up now...
+
+ .align 5
+
+nSpecAcc: rlwinm. r17,r26,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are going to user or system
li r14,PMAP_SEGS ; Point to segments
bne+ gotouser ; We are going into user state...
.align 5
gotouser: dcbt r14,r7 ; Touch the segment register contents
- lwz r9,spcFlags(r2) ; Pick up the special flags
- lwz r16,PP_LASTPMAP(r2) ; Pick up the last loaded pmap
+ lwz r9,spcFlags(r29) ; Pick up the special flags
+ lwz r16,PP_LASTPMAP(r29) ; Pick up the last loaded pmap
addi r14,r14,32 ; Second half of pmap segments
rlwinm r9,r9,userProtKeybit-2,2,2 ; Isolate the user state protection key
lwz r15,PMAP_SPACE(r7) ; Get the primary space
oris r15,r15,hi16(SEG_REG_PROT) ; Set segment 0 SR value
mtcrf 0x0F,r13 ; Set CRs to correspond to the subordinate spaces
xor r15,r15,r9 ; Flip to proper segment register key
- lhz r9,PP_CPU_FLAGS(r2) ; Get the processor flags
+ lhz r9,PP_CPU_FLAGS(r29) ; Get the processor flags
addis r13,r15,0x0000 ; Get SR0 value
bf 16,nlsr0 ; No alternate here...
nlsr1: mtsr sr1,r13 ; Load up the SR
or r26,r26,r9 ; Flip on the BE bit for special trace if needed
- cmplw r7,r16 ; Are we running the same segs as last time?
+ cmplw cr3,r7,r16 ; Are we running the same segs as last time?
addis r13,r15,0x0020 ; Get SR2 value
bf 18,nlsr2 ; No alternate here...
nlsr14: mtsr sr14,r13 ; Load up the SR
- beq+ segsdone ; All done if same pmap as last time...
+ beq+ cr3,segsdone ; All done if same pmap as last time...
- stw r7,PP_LASTPMAP(r2) ; Remember what we just loaded
+ stw r7,PP_LASTPMAP(r29) ; Remember what we just loaded
addis r13,r15,0x0040 ; Get SR4 value
bf 20,nlsr4 ; No alternate here...
nlsr15: mtsr sr15,r13 ; Load up the SR
-segsdone: li r1,emfp0 ; Point to the fp savearea
+segsdone: stwcx. r26,r3,r31 ; Blow away any reservations we hold
+
+ li r21,emfp0 ; Point to the fp savearea
lwz r25,savesrr0(r31) ; Get the SRR0 to use
- la r28,saver6(r31) /* Point to the next line to use */
- dcbt r1,r2 ; Start moving in a work area
- lwz r0,saver0(r31) /* Restore */
- dcbt 0,r28 /* Touch it in */
- mr r29,r2 ; Save the per_proc
- lwz r1,saver1(r31) /* Restore */
- lwz r2,saver2(r31) /* Restore */
- la r28,saver14(r31) /* Point to the next line to get */
- lwz r3,saver3(r31) /* Restore */
+ la r28,saver8(r31) ; Point to the next line to use
+ dcbt r21,r29 ; Start moving in a work area
+ lwz r0,saver0(r31) ; Restore R0
+ dcbt 0,r28 ; Touch it in
+ lwz r1,saver1(r31) ; Restore R1
+ lwz r2,saver2(r31) ; Restore R2
+ la r28,saver16(r31) ; Point to the next line to get
+ lwz r3,saver3(r31) ; Restore R3
mtcrf 0x80,r27 ; Get facility availability flags (do not touch CR1-7)
- lwz r4,saver4(r31) /* Restore */
- mtsrr0 r25 /* Restore the SRR0 now */
- lwz r5,saver5(r31) /* Restore */
- mtsrr1 r26 /* Restore the SRR1 now */
- lwz r6,saver6(r31) /* Restore */
-
- dcbt 0,r28 /* Touch that next line on in */
- la r28,savexfpscrpad(r31) ; Point to the saved fpscr
-
- lwz r7,saver7(r31) /* Restore */
- dcbt 0,r28 ; Touch saved fpscr
- lwz r8,saver8(r31) /* Restore */
- lwz r9,saver9(r31) /* Restore */
- lwz r10,saver10(r31) /* Restore */
- lwz r11,saver11(r31) /* Restore */
- lwz r12,saver12(r31) /* Restore */
- lwz r13,saver13(r31) /* Restore */
- la r28,saver22(r31) /* Point to the next line to do */
- lwz r14,saver14(r31) /* Restore */
- lwz r15,saver15(r31) /* Restore */
-
-;
-; Note that floating point will be enabled from here on until the RFI
-;
-
- bf- pfFloatb,nofphere ; Skip if no floating point...
- mfmsr r27 ; Save the MSR
- ori r27,r27,lo16(MASK(MSR_FP)) ; Enable floating point
- mtmsr r27 ; Really enable
- isync
+ lwz r4,saver4(r31) ; Restore R4
+ mtsrr0 r25 ; Restore the SRR0 now
+ lwz r5,saver5(r31) ; Restore R5
+ mtsrr1 r26 ; Restore the SRR1 now
+ lwz r6,saver6(r31) ; Restore R6
+
+ dcbt 0,r28 ; Touch that next line on in
+ la r28,savevscr(r31) ; Point to the saved facility context
+
+ lwz r7,saver7(r31) ; Restore R7
+ lwz r8,saver8(r31) ; Restore R8
+ lwz r9,saver9(r31) ; Restore R9
+ mfmsr r26 ; Get the current MSR
+ dcbt 0,r28 ; Touch saved facility context
+ lwz r10,saver10(r31) ; Restore R10
+ lwz r11,saver11(r31) ; Restore R11
+ oris r26,r26,hi16(MASK(MSR_VEC)) ; Get the vector enable bit
+ lwz r12,saver12(r31) ; Restore R12
+ ori r26,r26,lo16(MASK(MSR_FP)) ; Add in the float enable
+ lwz r13,saver13(r31) ; Restore R13
+ la r28,saver24(r31) ; Point to the next line to do
+
+;
+; Note that floating point and vector will be enabled from here on until the RFI
+;
+
+ mtmsr r26 ; Turn on vectors and floating point
+ isync
+
+ dcbt 0,r28 ; Touch next line to do
+
+ lwz r14,saver14(r31) ; Restore R14
+ lwz r15,saver15(r31) ; Restore R15
+
+ bf pfAltivecb,noavec3 ; No Altivec on this CPU...
+
+ la r28,savevscr(r31) ; Point to the status area
+ stvxl v0,r21,r29 ; Save a vector register
+ lvxl v0,0,r28 ; Get the vector status
+ lwz r27,savevrsave(r31) ; Get the vrsave
+ mtvscr v0 ; Set the vector status
+
+ lvxl v0,r21,r29 ; Restore work vector register
+ beq+ cr3,noavec2 ; SRs have not changed, no need to stop the streams...
+ dssall ; Kill all data streams
+ sync
+
+noavec2: mtspr vrsave,r27 ; Set the vrsave
+
+noavec3: bf- pfFloatb,nofphere ; Skip if no floating point...
+
stfd f0,emfp0(r29) ; Save FP0
- lfd f0,savexfpscrpad(r31) ; Get the fpscr
+ lfd f0,savefpscrpad(r31) ; Get the fpscr
mtfsf 0xFF,f0 ; Restore fpscr
lfd f0,emfp0(r29) ; Restore the used register
-nofphere: dcbt 0,r28 /* Touch in another line of context */
-
- lwz r16,saver16(r31) /* Restore */
- lwz r17,saver17(r31) /* Restore */
- lwz r18,saver18(r31) /* Restore */
- lwz r19,saver19(r31) /* Restore */
- lwz r20,saver20(r31) /* Restore */
- lwz r21,saver21(r31) /* Restore */
- la r28,saver30(r31) /* Point to the final line */
- lwz r22,saver22(r31) /* Restore */
-
- dcbt 0,r28 /* Suck it in */
-
- lwz r23,saver23(r31) /* Restore */
- lwz r24,saver24(r31) /* Restore */
- lwz r25,saver25(r31) /* Restore */
- lwz r26,saver26(r31) /* Restore */
- lwz r27,saver27(r31) /* Restore */
-
- lwz r28,savecr(r31) /* Get CR to restore */
- bf pfAltivecb,noavec4 ; No vector on this machine
- lwz r29,savevrsave(r31) ; Get the vrsave
- beq+ cr3,noavec3 ; SRs have not changed, no need to stop the streams...
- dssall ; Kill all data streams
- ; The streams should be suspended
- ; already, and we do a bunch of
- ; dependent loads and a sync later
- ; so we should be cool.
-
-noavec3: mtspr vrsave,r29 ; Set the vrsave
-
-noavec4: lwz r29,savexer(r31) /* Get XER to restore */
- mtcr r28 /* Restore the CR */
- lwz r28,savelr(r31) /* Get LR to restore */
- mtxer r29 /* Restore the XER */
- lwz r29,savectr(r31) /* Get the CTR to restore */
- mtlr r28 /* Restore the LR */
- lwz r28,saver30(r31) /* Restore */
- mtctr r29 /* Restore the CTR */
- lwz r29,saver31(r31) /* Restore */
- mtsprg 2,r28 /* Save R30 */
- lwz r28,saver28(r31) /* Restore */
- mtsprg 3,r29 /* Save R31 */
- lwz r29,saver29(r31) /* Restore */
-
-#if PERFTIMES && DEBUG
- stmw r1,0x280(br0) ; Save all registers
- mfcr r20 ; Save the CR
- mflr r21 ; Save the LR
- mfsrr0 r9 ; Save SRR0
- mfsrr1 r11 ; Save SRR1
- mr r8,r0 ; Save R0
- li r3,69 ; Indicate interrupt
- mr r4,r11 ; Set MSR to log
- mr r5,r31 ; Get savearea to log
- bl EXT(dbgLog2) ; Cut log entry
- mr r0,r8 ; Restore R0
- mtsrr0 r9 ; Restore SRR0
- mtsrr1 r11 ; Restore SRR1
- mtlr r21 ; Restore the LR
- mtcr r20 ; Restore the CR
- lmw r1,0x280(br0) ; Restore all the rest
-#endif
+nofphere: lwz r16,saver16(r31) ; Restore R16
+ lwz r17,saver17(r31) ; Restore R17
+ lwz r18,saver18(r31) ; Restore R18
+ lwz r19,saver19(r31) ; Restore R19
+ lwz r20,saver20(r31) ; Restore R20
+ lwz r21,saver21(r31) ; Restore R21
+ lwz r22,saver22(r31) ; Restore R22
+
+ lwz r23,saver23(r31) ; Restore R23
+ lwz r24,saver24(r31) ; Restore R24
+ lwz r25,saver25(r31) ; Restore R25
+ lwz r26,saver26(r31) ; Restore R26
+ lwz r27,saver27(r31) ; Restore R27
+
+ lwz r28,savecr(r31) ; Get CR to restore
+
+ lwz r29,savexer(r31) ; Get XER to restore
+ mtcr r28 ; Restore the CR
+ lwz r28,savelr(r31) ; Get LR to restore
+ mtxer r29 ; Restore the XER
+ lwz r29,savectr(r31) ; Get the CTR to restore
+ mtlr r28 ; Restore the LR
+ lwz r28,saver30(r31) ; Get R30
+ mtctr r29 ; Restore the CTR
+ lwz r29,saver31(r31) ; Get R31
+ mtsprg 2,r28 ; Save R30 for later
+ lwz r28,saver28(r31) ; Restore R28
+ mtsprg 3,r29 ; Save R31 for later
+ lwz r29,saver29(r31) ; Restore R29
- li r31,0 /* Get set to clear lock */
- sync /* Make sure it's all out there */
- stw r31,SVlock(r30) /* Unlock it */
- mfsprg r30,2 /* Restore R30 */
mfsprg r31,0 ; Get per_proc
+ mfsprg r30,2 ; Restore R30
lwz r31,pfAvailable(r31) ; Get the feature flags
mtsprg 2,r31 ; Set the feature flags
- mfsprg r31,3 /* Restore R31 */
+ mfsprg r31,3 ; Restore R31
- rfi /* Click heels three times and think very hard that there's no place like home */
+ rfi ; Click heels three times and think very hard that there is no place like home...
- .long 0 /* For old 601 bug */
+ .long 0 ; Leave this here
.long 0
.long 0
.long 0
LEXT(exception_exit)
mfsprg r29,2 ; Get feature flags
- mfmsr r30 /* Get the current MSR */
+ mfmsr r30 ; Get the current MSR
mtcrf 0x04,r29 ; Set the features
- mr r31,r3 /* Get the savearea in the right register */
- andi. r30,r30,0x7FCF /* Turn off externals, IR, and DR */
+ rlwinm r30,r30,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
+ mr r31,r3 ; Get the savearea in the right register
+ rlwinm r30,r30,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
+ li r10,savesrr0 ; Point to one of the first things we touch in the savearea on exit
+ andi. r30,r30,0x7FCF ; Turn off externals, IR, and DR
lis r1,hi16(SAVredrive) ; Get redrive request
bt pfNoMSRirb,eeNoMSR ; No MSR...
mr r3,r30 ; Get new MSR
sc ; Set it
-eeNoMSRx:
+eeNoMSRx: dcbt r10,r31 ; Touch in the first stuff we restore
mfsprg r2,0 ; Get the per_proc block
lwz r4,SAVflags(r31) ; Pick up the flags
mr r13,r31 ; Put savearea here also
beq+ EatRupt ; No redrive, just exit...
- lwz r3,saveexception(r13) ; Restore exception code
+ lwz r11,saveexception(r13) ; Restore exception code
stw r4,SAVflags(r13) ; Set the flags
b Redrive ; Redrive the exception...
-;
-; Make trace entry for lowmem_vectors internal debug
-;
-#if TRCSAVE
-cte:
- lwz r20,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) ; Pick up the current trace entry
- lwz r16,LOW_ADDR(EXT(traceEnd)-EXT(ExceptionVectorsStart))(br0) ; Grab up the end of it all
- addi r17,r20,LTR_size ; Point to the next trace entry
- cmplw r17,r16 ; Do we need to wrap the trace table?
- li r15,32 ; Second line of entry
- bne+ ctenwrap ; We got a trace entry...
- lwz r17,LOW_ADDR(EXT(traceStart)-EXT(ExceptionVectorsStart))(br0) ; Wrap back to the top
-
-ctenwrap: stw r17,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) ; Set the next entry for the next guy
-
- bf- featL1ena,skipz8 ; L1 cache is disabled...
- dcbz 0,r20 ; Allocate cache for the entry
- dcbz r15,r20 ; Zap the second half
-skipz8:
-
-ctegetTB: mftbu r16 ; Get the upper timebase
- mftb r17 ; Get the lower timebase
- mftbu r15 ; Get the upper one again
- cmplw r16,r15 ; Did the top tick?
- bne- ctegetTB ; Yeah, need to get it again...
-
- li r15,0x111 ; Get the special trace ID code
- stw r0,LTR_r0(r20) ; Save R0 (usually used as an ID number
- stw r16,LTR_timeHi(r20) ; Set the upper part of TB
- mflr r16 ; Get the return point
- stw r17,LTR_timeLo(r20) ; Set the lower part of TB
- sth r15,LTR_excpt(r20) ; Save the exception type
- stw r16,LTR_srr0(r20) ; Save the return point
- blr ; Leave...
-#endif
/*
* Start of the trace table