+;
+; Here is the swap for 64-bit machines
+;
+
+swap64: lwz r22,vmmXAFlgs(r27) ; Get the eXtended Architecture flags
+ ld r7,savesrr0(r30) ; Start moving context
+ ld r8,savesrr1(r30)
+ ld r9,saver0(r30)
+ cmplwi cr1,r14,T_SYSTEM_CALL ; Are we switching because of a system call?
+ ld r10,saver1(r30)
+ ld r11,saver2(r30)
+ rlwinm. r22,r22,0,0,0 ; Are we doing a 64-bit virtual machine?
+ ld r12,saver3(r30)
+ crnot vmmDoing64,cr0_eq ; Remember if this is a 64-bit VM
+ ld r13,saver4(r30)
+ la r6,vmmppcr6(r5) ; Point to second line
+ ld r14,saver5(r30)
+
+ dcbt 0,r6 ; Touch second line of context area
+
+ bt vmmDoing64,sw64x1 ; Skip to 64-bit stuff
+
+ lwz r15,vmmppcpc(r5) ; First line of context
+ lis r22,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
+ lwz r23,vmmppcmsr(r5)
+ ori r22,r22,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
+ lwz r17,vmmppcr0(r5)
+ lwz r18,vmmppcr1(r5)
+ and r23,r23,r22 ; Keep only the controllable bits
+ lwz r19,vmmppcr2(r5)
+ oris r23,r23,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
+ lwz r20,vmmppcr3(r5)
+ ori r23,r23,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
+ lwz r21,vmmppcr4(r5)
+ lwz r22,vmmppcr5(r5)
+
+ dcbt 0,r6 ; Touch third line of context area
+
+ stw r7,vmmppcpc(r5) ; Save emulator context into the context area
+ stw r8,vmmppcmsr(r5)
+ stw r9,vmmppcr0(r5)
+ stw r10,vmmppcr1(r5)
+ stw r11,vmmppcr2(r5)
+ stw r12,vmmppcr3(r5)
+ stw r13,vmmppcr4(r5)
+ stw r14,vmmppcr5(r5)
+
+;
+; Save the first 3 parameters if we are an SC (we will take care of the last later)
+;
+ bne+ cr1,sw64x1done ; Skip next if not an SC exception...
+ stw r12,return_params+0(r5) ; Save the first return
+ stw r13,return_params+4(r5) ; Save the second return
+ stw r14,return_params+8(r5) ; Save the third return
+ b sw64x1done ; We are done with this section...
+
+sw64x1: ld r15,vmmppcXpc(r5) ; First line of context
+ li r0,1 ; Get a 1 to turn on 64-bit
+ lis r22,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user (we will also allow 64-bit here)
+ sldi r0,r0,63 ; Get 64-bit bit
+ ld r23,vmmppcXmsr(r5)
+ ori r22,r22,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
+ ld r17,vmmppcXr0(r5)
+ or r22,r22,r0 ; Add the 64-bit bit
+ ld r18,vmmppcXr1(r5)
+ and r23,r23,r22 ; Keep only the controllable bits
+ ld r19,vmmppcXr2(r5)
+ oris r23,r23,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
+ ld r20,vmmppcXr3(r5)
+ ori r23,r23,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
+ ld r21,vmmppcXr4(r5)
+ ld r22,vmmppcXr5(r5)
+
+ dcbt 0,r6 ; Touch third line of context area
+
+ std r7,vmmppcXpc(r5) ; Save emulator context into the context area
+ std r8,vmmppcXmsr(r5)
+ std r9,vmmppcXr0(r5)
+ std r10,vmmppcXr1(r5)
+ std r11,vmmppcXr2(r5)
+ std r12,vmmppcXr3(r5)
+ std r13,vmmppcXr4(r5)
+ std r14,vmmppcXr5(r5)
+
+;
+; Save the first 3 parameters if we are an SC (we will take care of the last later)
+;
+ bne+ cr1,sw64x1done ; Skip next if not an SC exception...
+ std r12,return_paramsX+0(r5) ; Save the first return
+ std r13,return_paramsX+8(r5) ; Save the second return
+ std r14,return_paramsX+16(r5) ; Save the third return
+
+sw64x1done:
+ std r15,savesrr0(r30) ; Save vm context into the savearea
+ std r23,savesrr1(r30)
+ std r17,saver0(r30)
+ std r18,saver1(r30)
+ std r19,saver2(r30)
+ std r20,saver3(r30)
+ std r21,saver4(r30)
+ la r6,vmmppcr14(r5) ; Point to fourth line
+ std r22,saver5(r30)
+
+ dcbt 0,r6 ; Touch fourth line
+
+; Swap 8 registers
+
+ ld r7,saver6(r30) ; Read savearea
+ ld r8,saver7(r30)
+ ld r9,saver8(r30)
+ ld r10,saver9(r30)
+ ld r11,saver10(r30)
+ ld r12,saver11(r30)
+ ld r13,saver12(r30)
+ ld r14,saver13(r30)
+
+ bt vmmDoing64,sw64x2 ; Skip to 64-bit stuff
+
+ lwz r15,vmmppcr6(r5) ; Read vm context
+ lwz r24,vmmppcr7(r5)
+ lwz r17,vmmppcr8(r5)
+ lwz r18,vmmppcr9(r5)
+ lwz r19,vmmppcr10(r5)
+ lwz r20,vmmppcr11(r5)
+ lwz r21,vmmppcr12(r5)
+ lwz r22,vmmppcr13(r5)
+
+ stw r7,vmmppcr6(r5) ; Write context
+ stw r8,vmmppcr7(r5)
+ stw r9,vmmppcr8(r5)
+ stw r10,vmmppcr9(r5)
+ stw r11,vmmppcr10(r5)
+ stw r12,vmmppcr11(r5)
+ stw r13,vmmppcr12(r5)
+ la r6,vmmppcr22(r5) ; Point to fifth line
+ stw r14,vmmppcr13(r5)
+
+ dcbt 0,r6 ; Touch fifth line
+ b sw64x2done ; We are done with this section...
+
+sw64x2: ld r15,vmmppcXr6(r5) ; Read vm context
+ ld r24,vmmppcXr7(r5)
+ ld r17,vmmppcXr8(r5)
+ ld r18,vmmppcXr9(r5)
+ ld r19,vmmppcXr10(r5)
+ ld r20,vmmppcXr11(r5)
+ ld r21,vmmppcXr12(r5)
+ ld r22,vmmppcXr13(r5)
+
+ std r7,vmmppcXr6(r5) ; Write context
+ std r8,vmmppcXr7(r5)
+ std r9,vmmppcXr8(r5)
+ std r10,vmmppcXr9(r5)
+ std r11,vmmppcXr10(r5)
+ std r12,vmmppcXr11(r5)
+ std r13,vmmppcXr12(r5)
+ la r6,vmmppcXr22(r5) ; Point to fifth line
+ std r14,vmmppcXr13(r5)
+
+ dcbt 0,r6 ; Touch fifth line
+
+sw64x2done: std r15,saver6(r30) ; Write vm context
+ std r24,saver7(r30)
+ std r17,saver8(r30)
+ std r18,saver9(r30)
+ std r19,saver10(r30)
+ std r20,saver11(r30)
+ std r21,saver12(r30)
+ std r22,saver13(r30)
+
+; Swap 8 registers
+
+ ld r7,saver14(r30) ; Read savearea
+ ld r8,saver15(r30)
+ ld r9,saver16(r30)
+ ld r10,saver17(r30)
+ ld r11,saver18(r30)
+ ld r12,saver19(r30)
+ ld r13,saver20(r30)
+ ld r14,saver21(r30)
+
+ bt vmmDoing64,sw64x3 ; Skip to 64-bit stuff
+
+ lwz r15,vmmppcr14(r5) ; Read vm context
+ lwz r24,vmmppcr15(r5)
+ lwz r17,vmmppcr16(r5)
+ lwz r18,vmmppcr17(r5)
+ lwz r19,vmmppcr18(r5)
+ lwz r20,vmmppcr19(r5)
+ lwz r21,vmmppcr20(r5)
+ lwz r22,vmmppcr21(r5)
+
+ stw r7,vmmppcr14(r5) ; Write context
+ stw r8,vmmppcr15(r5)
+ stw r9,vmmppcr16(r5)
+ stw r10,vmmppcr17(r5)
+ stw r11,vmmppcr18(r5)
+ stw r12,vmmppcr19(r5)
+ stw r13,vmmppcr20(r5)
+ la r6,vmmppcr30(r5) ; Point to sixth line
+ stw r14,vmmppcr21(r5)
+
+ dcbt 0,r6 ; Touch sixth line
+ b sw64x3done ; Done with this section...
+
+sw64x3: ld r15,vmmppcXr14(r5) ; Read vm context
+ ld r24,vmmppcXr15(r5)
+ ld r17,vmmppcXr16(r5)
+ ld r18,vmmppcXr17(r5)
+ ld r19,vmmppcXr18(r5)
+ ld r20,vmmppcXr19(r5)
+ ld r21,vmmppcXr20(r5)
+ ld r22,vmmppcXr21(r5)
+
+ std r7,vmmppcXr14(r5) ; Write context
+ std r8,vmmppcXr15(r5)
+ std r9,vmmppcXr16(r5)
+ std r10,vmmppcXr17(r5)
+ std r11,vmmppcXr18(r5)
+ std r12,vmmppcXr19(r5)
+ std r13,vmmppcXr20(r5)
+ la r6,vmmppcXr30(r5) ; Point to sixth line
+ std r14,vmmppcXr21(r5)
+
+ dcbt 0,r6 ; Touch sixth line
+
+sw64x3done: std r15,saver14(r30) ; Write vm context
+ std r24,saver15(r30)
+ std r17,saver16(r30)
+ std r18,saver17(r30)
+ std r19,saver18(r30)
+ std r20,saver19(r30)
+ std r21,saver20(r30)
+ std r22,saver21(r30)
+
+; Swap 8 registers
+
+ ld r7,saver22(r30) ; Read savearea
+ ld r8,saver23(r30)
+ ld r9,saver24(r30)
+ ld r10,saver25(r30)
+ ld r11,saver26(r30)
+ ld r12,saver27(r30)
+ ld r13,saver28(r30)
+ ld r14,saver29(r30)
+
+ bt vmmDoing64,sw64x4 ; Skip to 64-bit stuff
+
+ lwz r15,vmmppcr22(r5) ; Read vm context
+ lwz r24,vmmppcr23(r5)
+ lwz r17,vmmppcr24(r5)
+ lwz r18,vmmppcr25(r5)
+ lwz r19,vmmppcr26(r5)
+ lwz r20,vmmppcr27(r5)
+ lwz r21,vmmppcr28(r5)
+ lwz r22,vmmppcr29(r5)
+
+ stw r7,vmmppcr22(r5) ; Write context
+ stw r8,vmmppcr23(r5)
+ stw r9,vmmppcr24(r5)
+ stw r10,vmmppcr25(r5)
+ stw r11,vmmppcr26(r5)
+ stw r12,vmmppcr27(r5)
+ stw r13,vmmppcr28(r5)
+ la r6,vmmppcvscr(r5) ; Point to seventh line
+ stw r14,vmmppcr29(r5)
+ dcbt 0,r6 ; Touch seventh line
+ b sw64x4done ; Done with this section...
+
+sw64x4: ld r15,vmmppcXr22(r5) ; Read vm context
+ ld r24,vmmppcXr23(r5)
+ ld r17,vmmppcXr24(r5)
+ ld r18,vmmppcXr25(r5)
+ ld r19,vmmppcXr26(r5)
+ ld r20,vmmppcXr27(r5)
+ ld r21,vmmppcXr28(r5)
+ ld r22,vmmppcXr29(r5)
+
+ std r7,vmmppcXr22(r5) ; Write context
+ std r8,vmmppcXr23(r5)
+ std r9,vmmppcXr24(r5)
+ std r10,vmmppcXr25(r5)
+ std r11,vmmppcXr26(r5)
+ std r12,vmmppcXr27(r5)
+ std r13,vmmppcXr28(r5)
+ la r6,vmmppcvscr(r5) ; Point to seventh line
+ std r14,vmmppcXr29(r5)
+
+ dcbt 0,r6 ; Touch seventh line
+
+sw64x4done: std r15,saver22(r30) ; Write vm context
+ std r24,saver23(r30)
+ std r17,saver24(r30)
+ std r18,saver25(r30)
+ std r19,saver26(r30)
+ std r20,saver27(r30)
+ std r21,saver28(r30)
+ std r22,saver29(r30)
+
+; Swap 8 registers
+
+ ld r7,saver30(r30) ; Read savearea
+ ld r8,saver31(r30)
+ lwz r9,savecr(r30)
+ ld r10,savexer(r30)
+ ld r11,savelr(r30)
+ ld r12,savectr(r30)
+ lwz r14,savevrsave(r30)
+
+ bt vmmDoing64,sw64x5 ; Skip to 64-bit stuff
+
+ lwz r15,vmmppcr30(r5) ; Read vm context
+ lwz r24,vmmppcr31(r5)
+ lwz r17,vmmppccr(r5)
+ lwz r18,vmmppcxer(r5)
+ lwz r19,vmmppclr(r5)
+ lwz r20,vmmppcctr(r5)
+ lwz r22,vmmppcvrsave(r5)
+
+ stw r7,vmmppcr30(r5) ; Write context
+ stw r8,vmmppcr31(r5)
+ stw r9,vmmppccr(r5)
+ stw r10,vmmppcxer(r5)
+ stw r11,vmmppclr(r5)
+ stw r12,vmmppcctr(r5)
+ stw r14,vmmppcvrsave(r5)
+ b sw64x5done ; Done here...
+
+sw64x5: ld r15,vmmppcXr30(r5) ; Read vm context
+ ld r24,vmmppcXr31(r5)
+ lwz r17,vmmppcXcr(r5)
+ ld r18,vmmppcXxer(r5)
+ ld r19,vmmppcXlr(r5)
+ ld r20,vmmppcXctr(r5)
+ lwz r22,vmmppcXvrsave(r5)
+
+ std r7,vmmppcXr30(r5) ; Write context
+ std r8,vmmppcXr31(r5)
+ stw r9,vmmppcXcr(r5)
+ std r10,vmmppcXxer(r5)
+ std r11,vmmppcXlr(r5)
+ std r12,vmmppcXctr(r5)
+ stw r14,vmmppcXvrsave(r5)
+
+sw64x5done: std r15,saver30(r30) ; Write vm context
+ std r24,saver31(r30)
+ stw r17,savecr(r30)
+ std r18,savexer(r30)
+ std r19,savelr(r30)
+ std r20,savectr(r30)
+ stw r22,savevrsave(r30)
+
+; Swap 8 registers
+
+ lwz r7,savevscr+0(r30) ; Read savearea
+ lwz r8,savevscr+4(r30)
+ lwz r9,savevscr+8(r30)
+ lwz r10,savevscr+12(r30)
+ lwz r11,savefpscrpad(r30)
+ lwz r12,savefpscr(r30)
+
+ lwz r15,vmmppcvscr+0(r5) ; Read vm context
+ lwz r24,vmmppcvscr+4(r5)
+ lwz r17,vmmppcvscr+8(r5)
+ lwz r18,vmmppcvscr+12(r5)
+ lwz r19,vmmppcfpscrpad(r5)
+ lwz r20,vmmppcfpscr(r5)
+
+ stw r7,vmmppcvscr+0(r5) ; Write context
+ stw r8,vmmppcvscr+4(r5)
+ stw r9,vmmppcvscr+8(r5)
+ stw r10,vmmppcvscr+12(r5)
+ stw r11,vmmppcfpscrpad(r5)
+ stw r12,vmmppcfpscr(r5)
+
+ stw r15,savevscr+0(r30) ; Write vm context
+ stw r24,savevscr+4(r30)
+ stw r17,savevscr+8(r30)
+ stw r18,savevscr+12(r30)
+ stw r19,savefpscrpad(r30)
+ stw r20,savefpscr(r30)
+
+
+;
+; Cobble up the exception return code and save any specific return values
+;
+
+ lwz r7,saveexception(r30) ; Pick up the exception code
+ rlwinm r8,r7,30,24,31 ; Convert exception to return code
+ cmplwi r7,T_DATA_ACCESS ; Was this a DSI?
+ stw r8,return_code(r5) ; Save the exit code
+ cmplwi cr1,r7,T_INSTRUCTION_ACCESS ; Exiting because of an ISI?
+ beq+ swapDSI64 ; Yeah...
+ cmplwi r7,T_ALIGNMENT ; Alignment exception?
+ beq+ cr1,swapISI64 ; We had an ISI...
+ cmplwi cr1,r7,T_SYSTEM_CALL ; Exiting because of an system call?
+ beq+ swapDSI64 ; An alignment exception looks like a DSI...
+ beq+ cr1,swapSC64 ; We had a system call...
+
+ blr ; Return...
+
+;
+; Set exit returns for a DSI or alignment exception
+;
+
+swapDSI64: ld r10,savedar(r30) ; Get the DAR
+ lwz r7,savedsisr(r30) ; and the DSISR
+ bt vmmDoing64,sw64DSI ; Skip to 64-bit stuff...
+
+
+ stw r10,return_params+0(r5) ; Save DAR as first return parm
+ stw r7,return_params+4(r5) ; Save DSISR as second return parm
+ blr ; Return...
+
+sw64DSI: std r10,return_paramsX+0(r5) ; Save DAR as first return parm
+ std r7,return_paramsX+8(r5) ; Save DSISR as second return parm (note that this is expanded to 64 bits)
+ blr ; Return...
+
+;
+; Set exit returns for a ISI
+;
+
+swapISI64: bt vmmDoing64,sw64ISI ; Skip to 64-bit stuff...
+ lwz r7,vmmppcmsr(r5) ; Get the SRR1 value
+ lwz r10,vmmppcpc(r5) ; Get the PC as failing address
+ rlwinm r7,r7,0,1,4 ; Save the bits that match the DSISR
+ stw r10,return_params+0(r5) ; Save PC as first return parm
+ stw r7,return_params+4(r5) ; Save the pseudo-DSISR as second return parm
+ blr ; Return...
+
+sw64ISI: ld r7,vmmppcXmsr(r5) ; Get the SRR1 value
+ ld r10,vmmppcXpc(r5) ; Get the PC as failing address
+ rlwinm r7,r7,0,1,4 ; Save the bits that match the DSISR
+ std r10,return_paramsX+0(r5) ; Save PC as first return parm
+ std r7,return_paramsX+8(r5) ; Save the pseudo-DSISR as second return parm
+ blr ; Return...
+
+;
+; Set exit returns for a system call (note: we did the first 3 earlier)
+; Do we really need to pass parameters back here????
+;
+
+swapSC64: bt vmmDoing64,sw64SC ; Skip to 64-bit stuff...
+ lwz r10,vmmppcr6(r5) ; Get the fourth paramter
+ stw r10,return_params+12(r5) ; Save it
+ blr ; Return...
+
+sw64SC: ld r10,vmmppcXr6(r5) ; Get the fourth paramter
+ std r10,return_paramsX+24(r5) ; Save it
+ blr ; Return...
+
+;
+; vmmFamGuestResume:
+; Restore Guest context from Fam mode.
+;
+
+vmmFamGuestResume:
+ mfsprg r10,1 ; Get the current activation
+ lwz r10,ACT_PER_PROC(r10) ; Get the per_proc block
+ lwz r27,vmmCEntry(r3) ; Get the context that is active
+ lwz r4,VMMXAFlgs(r10) ; Get the eXtended Architecture flags
+ rlwinm. r4,r4,0,0,0 ; Are we doing a 64-bit virtual machine?
+ lwz r15,spcFlags(r10) ; Get per_proc special flags
+ mr r26,r3 ; Save the activation pointer
+ lwz r20,vmmContextKern(r27) ; Get the comm area
+ rlwinm r15,r15,0,FamVMmodebit+1,FamVMmodebit-1 ; Clear FamVMmodebit
+ stw r15,spcFlags(r10) ; Update the special flags
+ bne fgrX
+ lwz r7,famguestpc(r20) ; Load famguest ctx pc
+ bf++ vmmMapDone,fgrNoMap ; No mapping done for this space.
+ lwz r3,SAVflags(r30) ; Pick up the savearea flags
+ lwz r2,vmmLastMap(r28) ; Get the last mapped address
+ lwz r6,vmmLastMap+4(r28) ; Get the last mapped address
+ li r4,T_DATA_ACCESS ; Change to DSI fault
+ oris r3,r3,hi16(SAVredrive) ; Set exception redrive
+ stw r2,savedar(r30) ; Set the DAR to the last thing we mapped
+ stw r6,savedar+4(r30) ; Set the DAR to the last thing we mapped
+ stw r3,SAVflags(r30) ; Turn on the redrive request
+ lis r2,hi16(MASK(DSISR_HASH)) ; Set PTE/DBAT miss
+ stw r4,saveexception(r30) ; Say we need to emulate a DSI
+ li r0,0 ; Clear
+ stw r2,savedsisr(r30) ; Pretend we have a PTE miss
+ stb r0,vmmGFlags+3(r28) ; Show that the redrive has been taken care of
+fgrNoMap:
+ lwz r4,savesrr1+4(r30) ; Get the saved MSR value
+ stw r7,savesrr0+4(r30) ; Set savearea pc
+ lwz r5,famguestmsr(r20) ; Load famguest ctx msr
+ lis r6,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
+ ori r6,r6,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
+ and r5,r5,r6 ; Keep only the controllable bits
+ oris r5,r5,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
+ ori r5,r5,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
+ rlwimi r5,r4,0,MSR_FP_BIT,MSR_FP_BIT ; Propagate guest FP
+ rlwimi r5,r4,0,MSR_VEC_BIT,MSR_VEC_BIT ; Propagate guest Vector
+ stw r5,savesrr1+4(r30) ; Set savearea srr1
+ lwz r4,famguestr0(r20) ; Load famguest ctx r0
+ lwz r5,famguestr1(r20) ; Load famguest ctx r1
+ lwz r6,famguestr2(r20) ; Load famguest ctx r2
+ lwz r7,famguestr3(r20) ; Load famguest ctx r3
+ stw r4,saver0+4(r30) ; Set savearea r0
+ stw r5,saver1+4(r30) ; Set savearea r1
+ stw r6,saver2+4(r30) ; Set savearea r2
+ stw r7,saver3+4(r30) ; Set savearea r3
+ lwz r4,famguestr4(r20) ; Load famguest ctx r4
+ lwz r5,famguestr5(r20) ; Load famguest ctx r5
+ lwz r6,famguestr6(r20) ; Load famguest ctx r6
+ lwz r7,famguestr7(r20) ; Load famguest ctx r7
+ stw r4,saver4+4(r30) ; Set savearea r4
+ stw r5,saver5+4(r30) ; Set savearea r5
+ stw r6,saver6+4(r30) ; Set savearea r6
+ stw r7,saver7+4(r30) ; Set savearea r7
+ b fgrret
+fgrX:
+ ld r7,famguestXpc(r20) ; Load famguest ctx pc
+ bf++ vmmMapDone,fgrXNoMap ; No mapping done for this space.
+ lwz r3,SAVflags(r30) ; Pick up the savearea flags
+ ld r2,vmmLastMap(r28) ; Get the last mapped address
+ li r4,T_DATA_ACCESS ; Change to DSI fault
+ oris r3,r3,hi16(SAVredrive) ; Set exception redrive
+ std r2,savedar(r30) ; Set the DAR to the last thing we mapped
+ stw r3,SAVflags(r30) ; Turn on the redrive request
+ lis r2,hi16(MASK(DSISR_HASH)) ; Set PTE/DBAT miss
+ stw r4,saveexception(r30) ; Say we need to emulate a DSI
+ li r0,0 ; Clear
+ stw r2,savedsisr(r30) ; Pretend we have a PTE miss
+ stb r0,vmmGFlags+3(r28) ; Show that the redrive has been taken care of
+fgrXNoMap:
+ ld r4,savesrr1(r30) ; Get the saved MSR value
+ std r7,savesrr0(r30) ; Set savearea pc
+ ld r5,famguestXmsr(r20) ; Load famguest ctx msr
+ lis r6,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
+ ori r6,r6,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
+ and r5,r5,r6 ; Keep only the controllable bits
+ oris r5,r5,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
+ ori r5,r5,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
+ rlwimi r5,r4,0,MSR_FP_BIT,MSR_FP_BIT ; Propagate guest FP
+ rlwimi r5,r4,0,MSR_VEC_BIT,MSR_VEC_BIT ; Propagate guest Vector
+ std r5,savesrr1(r30) ; Set savearea srr1
+ ld r4,famguestXr0(r20) ; Load famguest ctx r0
+ ld r5,famguestXr1(r20) ; Load famguest ctx r1
+ ld r6,famguestXr2(r20) ; Load famguest ctx r2
+ ld r7,famguestXr3(r20) ; Load famguest ctx r3
+ std r4,saver0(r30) ; Set savearea r0
+ std r5,saver1(r30) ; Set savearea r1
+ std r6,saver2(r30) ; Set savearea r2
+ std r7,saver3(r30) ; Set savearea r3
+ ld r4,famguestXr4(r20) ; Load famguest ctx r4
+ ld r5,famguestXr5(r20) ; Load famguest ctx r5
+ ld r6,famguestXr6(r20) ; Load famguest ctx r6
+ ld r7,famguestXr7(r20) ; Load famguest ctx r7
+ std r4,saver4(r30) ; Set savearea r4
+ std r5,saver5(r30) ; Set savearea r5
+ std r6,saver6(r30) ; Set savearea r6
+ std r7,saver7(r30) ; Set savearea r7
+fgrret:
+ li r3,1 ; Show normal exit with check for AST
+ mr r16,r26 ; Restore the thread pointer
+ b EXT(ppcscret) ; Go back to handler...
+
+;
+; FAM Intercept exception handler
+;
+
+ .align 5
+ .globl EXT(vmm_fam_exc)
+
+LEXT(vmm_fam_exc)
+ lwz r4,VMMXAFlgs(r2) ; Get the eXtended Architecture flags
+ lwz r1,pfAvailable(r2) ; Get the CPU features flags
+ rlwinm. r4,r4,0,0,0 ; Are we doing a 64-bit virtual machine?
+ bne fexcX
+ lwz r4,saver4+4(r13) ; Load savearea r4
+ cmplwi r11,T_ALIGNMENT ; Alignment exception?
+ lwz r3,VMMareaPhys(r2) ; Load phys state page addr
+ mtcrf 0x02,r1 ; Move pf64Bit to its normal place in CR6
+ cmplwi cr1,r11,T_PROGRAM ; Exiting because of an PRG?
+ bt++ pf64Bitb,fexcVMareaPhys64 ; Go do this on a 64-bit machine...
+ slwi r3,r3,12 ; Change ppnum to physical address
+ b fexcVMareaPhysres
+fexcVMareaPhys64:
+ mtxer r5 ; Restore xer
+ lwz r5,saver5+4(r13) ; Load savearea r5
+ lwz r6,saver6+4(r13) ; Load savearea r6
+ sldi r3,r3,12 ; Change ppnum to physical address
+fexcVMareaPhysres:
+ stw r4,famguestr4(r3) ; Save r4 in famguest ctx
+ stw r5,famguestr5(r3) ; Save r5 in famguest ctx
+ stw r6,famguestr6(r3) ; Save r6 in famguest ctx
+ stw r7,famguestr7(r3) ; Save r7 in famguest ctx
+ lwz r4,saver0+4(r13) ; Load savearea r0
+ lwz r5,saver1+4(r13) ; Load savearea r1
+ lwz r6,saver2+4(r13) ; Load savearea r2
+ lwz r7,saver3+4(r13) ; Load savearea r3
+ stw r4,famguestr0(r3) ; Save r0 in famguest ctx
+ stw r5,famguestr1(r3) ; Save r1 in famguest ctx
+ stw r6,famguestr2(r3) ; Save r2 in famguest ctx
+ stw r7,famguestr3(r3) ; Save r3 in famguest ctx
+ lwz r4,spcFlags(r2) ; Load per_proc spcFlags
+ oris r4,r4,hi16(FamVMmode) ; Set FAM mode
+ stw r4,spcFlags(r2) ; Update per_proc spcFlags
+ mfsrr0 r2 ; Get the interrupt srr0
+ mfsrr1 r4 ; Get the interrupt srr1
+ stw r2,famguestpc(r3) ; Save srr0 in famguest ctx
+ stw r4,famguestmsr(r3) ; Save srr1 in famguest ctx
+ li r6,lo16(MASK(MSR_FE0)|MASK(MSR_SE)|MASK(MSR_BE)|MASK(MSR_FE1))
+ andc r6,r4,r6 ; Clear SE BE FE0 FE1
+ mtsrr1 r6 ; Set srr1
+ mr r6,r3 ; Set r6 with phys state page addr
+ rlwinm r7,r11,30,24,31 ; Convert exception to return code
+ beq+ cr1,fexcPRG ; We had a program exception...
+ bne+ fexcret
+ ; We had an Alignment...
+ mfdar r3 ; Load dar
+ mfdsisr r4 ; Load dsisr
+ stw r3,famparam+0x4(r6) ; Set famparam 1 with dar
+ stw r4,famparam+0x8(r6) ; Set famparam 2 with dsir
+ b fexcret ;
+fexcPRG:
+ stw r4,famparam+0x4(r6) ; Set famparam 1 with srr1
+ mr r3,r4 ; Set r3 with dsisr
+ lwz r4,famguestr4(r6) ; Load r4 from famguest context
+fexcret:
+ lwz r5,famguestr5(r6) ; Load r5 from famguest context
+ lwz r13,famhandler(r6) ; Load user address to resume
+ stw r2,famparam(r6) ; Set famparam 0 with srr0
+ stw r7,famdispcode(r6) ; Save the exit code
+ lwz r1,famrefcon(r6) ; load refcon
+ bt++ pf64Bitb,fexcrfi64 ; Go do this on a 64-bit machine...
+ mtcr r0 ; Restore cr
+ mtsrr0 r13 ; Load srr0
+ mr r0,r7 ; Set dispatch code
+ lwz r7,famguestr7(r6) ; Load r7 from famguest context
+ lwz r6,famguestr6(r6) ; Load r6 from famguest context
+ mfsprg r13,2 ; Restore r13
+ mfsprg r11,3 ; Restore r11
+ rfi
+fexcrfi64:
+ mtcr r0 ; Restore cr
+ mtsrr0 r13 ; Load srr0
+ mr r0,r7 ; Set dispatch code
+ lwz r7,famguestr7(r6) ; Load r7 from famguest context
+ lwz r6,famguestr6(r6) ; Load r6 from famguest context
+ mfsprg r13,2 ; Restore r13
+ mfsprg r11,3 ; Restore r11
+ rfid
+fexcX:
+ mtxer r5 ; Restore xer
+ ld r4,saver4(r13) ; Load savearea r4
+ ld r5,saver5(r13) ; Load savearea r5
+ ld r6,saver6(r13) ; Load savearea r6
+ cmplwi r11,T_ALIGNMENT ; Alignment exception?
+ lwz r3,VMMareaPhys(r2) ; Load phys state page addr
+ mtcrf 0x02,r1 ; Move pf64Bit to its normal place in CR6
+ cmplwi cr1,r11,T_PROGRAM ; Exiting because of an PRG?
+ sldi r3,r3,12 ; Change ppnum to physical address
+ std r4,famguestXr4(r3) ; Save r4 in famguest ctx
+ std r5,famguestXr5(r3) ; Save r5 in famguest ctx
+ std r6,famguestXr6(r3) ; Save r6 in famguest ctx
+ std r7,famguestXr7(r3) ; Save r7 in famguest ctx
+ ld r4,saver0(r13) ; Load savearea r0
+ ld r5,saver1(r13) ; Load savearea r1
+ ld r6,saver2(r13) ; Load savearea r2
+ ld r7,saver3(r13) ; Load savearea r3
+ std r4,famguestXr0(r3) ; Save r0 in famguest ctx
+ std r5,famguestXr1(r3) ; Save r1 in famguest ctx
+ std r6,famguestXr2(r3) ; Save r2 in famguest ctx
+ std r7,famguestXr3(r3) ; Save r3 in famguest ctx
+ lwz r4,spcFlags(r2) ; Load per_proc spcFlags
+ oris r4,r4,hi16(FamVMmode) ; Set FAM mode
+ stw r4,spcFlags(r2) ; Update per_proc spcFlags
+ mfsrr0 r2 ; Get the interrupt srr0
+ mfsrr1 r4 ; Get the interrupt srr1
+ std r2,famguestXpc(r3) ; Save srr0 in famguest ctx
+ std r4,famguestXmsr(r3) ; Save srr1 in famguest ctx
+ li r6,lo16(MASK(MSR_FE0)|MASK(MSR_SE)|MASK(MSR_BE)|MASK(MSR_FE1))
+ andc r6,r4,r6 ; Clear SE BE FE0 FE1
+ mtsrr1 r6 ; Set srr1
+ mr r6,r3 ; Set r6 with phys state page addr
+ rlwinm r7,r11,30,24,31 ; Convert exception to return code
+ beq+ cr1,fexcXPRG ; We had a program exception...
+ bne+ fexcXret
+ ; We had an Alignment...
+ mfdar r3 ; Load dar
+ mfdsisr r4 ; Load dsisr
+ std r3,famparamX+0x8(r6) ; Set famparam 1 with dar
+ std r4,famparamX+0x10(r6) ; Set famparam 2 with dsir
+ b fexcXret
+fexcXPRG:
+ std r4,famparamX+0x8(r6) ; Set famparam 1 with srr1
+ mr r3,r4 ; Set r3 with dsisr
+ ld r4,famguestXr4(r6) ; Load r4 from famguest context
+fexcXret:
+ ld r5,famguestXr5(r6) ; Load r5 from famguest context
+ ld r13,famhandlerX(r6) ; Load user address to resume
+ std r2,famparamX(r6) ; Set famparam 0 with srr0
+ std r7,famdispcodeX(r6) ; Save the exit code
+ ld r1,famrefconX(r6) ; load refcon
+ mtcr r0 ; Restore cr
+ mtsrr0 r13 ; Load srr0
+ mr r0,r7 ; Set dispatch code
+ ld r7,famguestXr7(r6) ; Load r7 from famguest context
+ ld r6,famguestXr6(r6) ; Load r6 from famguest context
+ mfsprg r13,2 ; Restore r13
+ mfsprg r11,3 ; Restore r11
+ rfid
+
+;
+; FAM Intercept DSI ISI fault handler
+;
+
+ .align 5
+ .globl EXT(vmm_fam_pf)
+
+LEXT(vmm_fam_pf)
+ lwz r4,VMMXAFlgs(r2) ; Get the eXtended Architecture flags
+ lwz r3,VMMareaPhys(r2) ; Load phys state page addr
+ rlwinm. r4,r4,0,0,0 ; Are we doing a 64-bit virtual machine?
+ bne fpfX
+ lwz r4,saver0+4(r13) ; Load savearea r0
+ lwz r5,saver1+4(r13) ; Load savearea r1
+ lwz r6,saver2+4(r13) ; Load savearea r2
+ lwz r7,saver3+4(r13) ; Load savearea r3
+ bt++ pf64Bitb,fpfVMareaPhys64 ; Go do this on a 64-bit machine...
+ slwi r3,r3,12 ; Change ppnum to physical address
+ b fpfVMareaPhysret
+fpfVMareaPhys64:
+ sldi r3,r3,12 ; Change ppnum to physical address
+fpfVMareaPhysret:
+ stw r4,famguestr0(r3) ; Save r0 in famguest
+ stw r5,famguestr1(r3) ; Save r1 in famguest
+ stw r6,famguestr2(r3) ; Save r2 in famguest
+ stw r7,famguestr3(r3) ; Save r3 in famguest
+ lwz r4,saver4+4(r13) ; Load savearea r0
+ lwz r5,saver5+4(r13) ; Load savearea r1
+ lwz r6,saver6+4(r13) ; Load savearea r2
+ lwz r7,saver7+4(r13) ; Load savearea r3
+ stw r4,famguestr4(r3) ; Save r4 in famguest
+ lwz r4,spcFlags(r2) ; Load spcFlags
+ stw r5,famguestr5(r3) ; Save r5 in famguest
+ lwz r5,savesrr0+4(r13) ; Get the interrupt srr0
+ stw r6,famguestr6(r3) ; Save r6 in famguest
+ lwz r6,savesrr1+4(r13) ; Load srr1
+ oris r4,r4,hi16(FamVMmode) ; Set FAM mode
+ stw r7,famguestr7(r3) ; Save r7 in famguest
+ stw r4,spcFlags(r2) ; Update spcFlags
+ lwz r1,famrefcon(r3) ; Load refcon
+ lwz r2,famhandler(r3) ; Load famhandler to resume
+ stw r5,famguestpc(r3) ; Save srr0
+ stw r5,saver2+4(r13) ; Store srr0 in savearea r2
+ stw r5,famparam(r3) ; Store srr0 in fam param 0
+ stw r6,famguestmsr(r3) ; Save srr1 in famguestmsr
+ cmplwi cr1,r11,T_INSTRUCTION_ACCESS ; Was this a ISI?
+ rlwinm r7,r11,30,24,31 ; Convert exception to return code
+ beq+ cr1,fpfISI ; We had an ISI...
+; fpfDSI
+ lwz r6,savedar+4(r13) ; Load dar from savearea
+ lwz r4,savedsisr(r13) ; Load dsisr from savearea
+ stw r6,famparam+0x4(r3) ; Store dar in fam param 1
+ stw r6,saver3+4(r13) ; Store dar in savearea r3
+ stw r4,famparam+0x8(r3) ; Store dsisr in fam param 2
+ stw r4,saver4+4(r13) ; Store dsisr in savearea r4
+ b fpfret
+fpfISI:
+ rlwinm r6,r6,0,1,4 ; Save the bits that match the DSISR
+ stw r6,famparam+0x4(r3) ; Store srr1 in fam param 1
+ stw r6,saver3+4(r13) ; Store srr1 in savearea r3
+fpfret:
+ stw r7,saver0+4(r13) ; Set dispatch code
+ stw r7,famdispcode(r3) ; Set dispatch code
+ stw r1,saver1+4(r13) ; Store refcon in savearea r1
+ stw r2,savesrr0+4(r13) ; Store famhandler in srr0
+ blr
+fpfX:
+ ld r4,saver0(r13) ; Load savearea r0
+ ld r5,saver1(r13) ; Load savearea r1
+ ld r6,saver2(r13) ; Load savearea r2
+ ld r7,saver3(r13) ; Load savearea r3
+ sldi r3,r3,12 ; Change ppnum to physical address
+ std r4,famguestXr0(r3) ; Save r0 in famguest
+ std r5,famguestXr1(r3) ; Save r1 in famguest
+ std r6,famguestXr2(r3) ; Save r2 in famguest
+ std r7,famguestXr3(r3) ; Save r3 in famguest
+ ld r4,saver4(r13) ; Load savearea r0
+ ld r5,saver5(r13) ; Load savearea r1
+ ld r6,saver6(r13) ; Load savearea r2
+ ld r7,saver7(r13) ; Load savearea r3
+ std r4,famguestXr4(r3) ; Save r4 in famguest
+ lwz r4,spcFlags(r2) ; Load spcFlags
+ std r5,famguestXr5(r3) ; Save r5 in famguest
+ ld r5,savesrr0(r13) ; Get the interrupt srr0
+ std r6,famguestXr6(r3) ; Save r6 in famguest
+ ld r6,savesrr1(r13) ; Load srr1
+ oris r4,r4,hi16(FamVMmode) ; Set FAM mode
+ std r7,famguestXr7(r3) ; Save r7 in famguest
+ stw r4,spcFlags(r2) ; Update spcFlags
+ ld r1,famrefconX(r3) ; Load refcon
+ ld r2,famhandlerX(r3) ; Load famhandler to resume
+ std r5,famguestXpc(r3) ; Save srr0
+ std r5,saver2(r13) ; Store srr0 in savearea r2
+ std r5,famparamX(r3) ; Store srr0 in fam param 0
+ std r6,famguestXmsr(r3) ; Save srr1 in famguestmsr
+ cmplwi cr1,r11,T_INSTRUCTION_ACCESS ; Was this a ISI?
+ rlwinm r7,r11,30,24,31 ; Convert exception to return code
+ beq+ cr1,fpfXISI ; We had an ISI...
+; fpfXDSI
+ ld r6,savedar(r13) ; Load dar from savearea
+ lwz r4,savedsisr(r13) ; Load dsisr from savearea
+ std r6,famparamX+0x8(r3) ; Store dar in fam param 1
+ std r6,saver3(r13) ; Store dar in savearea r3
+ std r4,famparamX+0x10(r3) ; Store dsisr in fam param 2
+ std r4,saver4(r13) ; Store dsisr in savearea r4
+ b fpfXret
+fpfXISI:
+ rlwinm r6,r6,0,1,4 ; Save the bits that match the DSISR
+ std r6,famparamX+0x8(r3) ; Store srr1 in fam param 1
+ std r6,saver3(r13) ; Store srr1 in savearea r3
+fpfXret:
+ std r7,saver0(r13) ; Set dispatch code
+ std r7,famdispcodeX(r3) ; Set dispatch code
+ std r1,saver1(r13) ; Store refcon in savearea r1
+ std r2,savesrr0(r13) ; Store famhandler in srr0
+ blr
+
+/*
+ * Ultra Fast Path FAM syscalls
+ *
+ * The UFT FAMs are those from kvmmResumeGuest to kvmmSetGuestRegister, inclusive.
+ * We get here directly from the syscall vector, with interrupts and translation off,
+ * 64-bit mode on if supported, and all registers live except:
+ *
+ * r13 = holds caller's cr
+ * sprg2 = holds caller's r13
+ * sprg3 = holds caller's r11
+ * cr2 = set on (r3==kvmmSetGuestRegister)
+ * cr5 = set on (r3==kvmmResumeGuest)
+ */
+
+ .align 5
+ .globl EXT(vmm_ufp)
+
+LEXT(vmm_ufp)
+ mfsprg r3,0 ; Get the per_proc area
+ mr r11,r13 ; Move saved cr to r11
+ lwz r13,VMMXAFlgs(r3) ; Get the eXtended Architecture flags
+ rlwinm. r13,r13,0,0,0 ; Are we doing a 64-bit virtual machine?
+
+ lwz r13,pfAvailable(r3) ; Get feature flags
+ mtcrf 0x02,r13 ; Put pf64Bitb etc in cr6
+ lwz r13,VMMareaPhys(r3) ; Load fast assist area
+ bt++ pf64Bitb,ufpVMareaPhys64 ; Go do this on a 64-bit machine...
+ slwi r13,r13,12 ; Change ppnum to physical address
+ b ufpVMareaPhysret
+ufpVMareaPhys64:
+ sldi r13,r13,12 ; Change ppnum to physical address
+ufpVMareaPhysret:
+ bne ufpX ; go handle a 64-bit virtual machine
+
+ bt cr5_eq,ufpResumeGuest ; if kvmmResumeGuest, branch to ResumeGuest
+ cmplwi cr5,r4,7 ; First argument in range? (ie, 0-7)
+ bgt cr5,ufpVMret ; Return if not in the range
+ slwi r4,r4,2 ; multiply index by 4
+ la r3,famguestr0(r13) ; Load the base address
+ bt cr2_eq,ufpSetGuestReg ; Set/get selector
+; ufpGetGuestReg
+ lwzx r3,r4,r3 ; Load the guest register
+ b ufpVMret ; Return
+ufpSetGuestReg:
+ stwx r5,r4,r3 ; Update the guest register
+ li r3,0 ; Set return value
+ b ufpVMret ; Return
+ufpResumeGuest:
+ lwz r7,spcFlags(r3) ; Pick up the special flags
+ mtsrr0 r4 ; Set srr0
+ rlwinm. r6,r6,0,vmmKeyb,vmmKeyb ; Check vmmKeyb in maskCntrl
+ rlwinm r7,r7,0,FamVMmodebit+1,FamVMmodebit-1 ; Clear FamVMmodebit
+ stw r7,spcFlags(r3) ; Update the special flags
+ mfsrr1 r6 ; Get the current MSR value
+
+ lwz r4,famguestmsr(r13) ; Load guest srr1
+ lis r1,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
+ ori r1,r1,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
+ and r4,r4,r1 ; Keep only the controllable bits
+ oris r4,r4,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
+ ori r4,r4,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
+ rlwimi r4,r6,0,MSR_FP_BIT,MSR_FP_BIT ; Propagate guest FP
+ rlwimi r4,r6,0,MSR_VEC_BIT,MSR_VEC_BIT ; Propagate guest Vector
+ beq ufpnokey ; Branch if not key switch
+ mr r2,r7 ; Save r7
+ rlwimi r7,r5,32+vmmKeyb-userProtKeybit,userProtKeybit,userProtKeybit ; Set the protection key
+ cmpw cr0,r7,r2 ; Is userProtKeybit changed?
+ beq ufpnokey ; No, go to ResumeGuest_nokey
+ mr r5,r3 ; Get the per_proc area
+ stw r7,spcFlags(r3) ; Update the special flags
+
+ bt++ pf64Bitb,ufpsave64 ; Go do this on a 64-bit machine...
+
+ lwz r3,next_savearea+4(r5) ; Get the exception save area
+ stw r8,saver8+4(r3) ; Save r8
+ stw r9,saver9+4(r3) ; Save r9
+ stw r10,saver10+4(r3) ; Save r10
+ stw r11,saver11+4(r3) ; Save r11
+ stw r12,saver12+4(r3) ; Save r12
+ stw r13,saver13+4(r3) ; Save r12
+ stw r14,saver14+4(r3) ; Save r14
+ stw r15,saver15+4(r3) ; Save r15
+ stw r16,saver16+4(r3) ; Save r16
+ stw r17,saver17+4(r3) ; Save r17
+ stw r18,saver18+4(r3) ; Save r18
+ stw r19,saver19+4(r3) ; Save r19
+ stw r20,saver20+4(r3) ; Save r20
+ stw r21,saver21+4(r3) ; Save r21
+ stw r22,saver22+4(r3) ; Save r22
+ stw r23,saver23+4(r3) ; Save r23
+ stw r24,saver24+4(r3) ; Save r24
+ stw r25,saver25+4(r3) ; Save r25
+ stw r26,saver26+4(r3) ; Save r26
+ stw r27,saver27+4(r3) ; Save r27
+ stw r28,saver28+4(r3) ; Save r28
+ stw r29,saver29+4(r3) ; Save r29
+ stw r30,saver30+4(r3) ; Save r30
+ stw r31,saver31+4(r3) ; Save r31
+ b ufpsaveres ; Continue
+
+ufpsave64:
+ ld r3,next_savearea(r5) ; Get the exception save area
+ std r8,saver8(r3) ; Save r8
+ std r9,saver9(r3) ; Save r9
+ std r10,saver10(r3) ; Save r10
+ std r11,saver11(r3) ; Save r11
+ std r12,saver12(r3) ; Save r12
+ std r13,saver13(r3) ; Save r12
+ std r14,saver14(r3) ; Save r14
+ std r15,saver15(r3) ; Save r15
+ std r16,saver16(r3) ; Save r16
+ std r17,saver17(r3) ; Save r17
+ std r18,saver18(r3) ; Save r18
+ std r19,saver19(r3) ; Save r19
+ std r20,saver20(r3) ; Save r20
+ std r21,saver21(r3) ; Save r21
+ std r22,saver22(r3) ; Save r22
+ std r23,saver23(r3) ; Save r23
+ std r24,saver24(r3) ; Save r24
+ std r25,saver25(r3) ; Save r25
+ std r26,saver26(r3) ; Save r26
+ std r27,saver27(r3) ; Save r27
+ std r28,saver28(r3) ; Save r28
+ std r29,saver29(r3) ; Save r29
+ mfxer r2 ; Get xer
+ std r30,saver30(r3) ; Save r30
+ std r31,saver31(r3) ; Save r31
+ std r2,savexer(r3) ; Save xer
+
+ufpsaveres:
+ mflr r20 ; Get lr
+ li r2,1 ; Set to 1
+ stw r7,spcFlags(r5) ; Update the special flags
+ mr r13,r3 ; Set current savearea
+ mr r21,r4 ; Save r4
+ sth r2,ppInvSeg(r5) ; Force a reload of the SRs
+ mr r29,r5 ; Get the per_proc area
+ mr r3,r4 ; Set MSR value we going to
+ bl EXT(switchSegs) ; Go handle the segment registers/STB
+ mr r3,r13 ; Set current savearea
+ mr r4,r21 ; Restore r4
+ mtlr r20 ; Set lr
+
+ bt++ pf64Bitb,ufprestore64 ; Go do this on a 64-bit machine...
+ lwz r8,saver8+4(r3) ; Load r8
+ lwz r9,saver9+4(r3) ; Load r9
+ lwz r10,saver10+4(r3) ; Load r10
+ lwz r11,saver11+4(r3) ; Load r11
+ lwz r12,saver12+4(r3) ; Load r12
+ lwz r13,saver13+4(r3) ; Load r12
+ lwz r14,saver14+4(r3) ; Load r14
+ lwz r15,saver15+4(r3) ; Load r15
+ lwz r16,saver16+4(r3) ; Load r16
+ lwz r17,saver17+4(r3) ; Load r17
+ lwz r18,saver18+4(r3) ; Load r18
+ lwz r19,saver19+4(r3) ; Load r19
+ lwz r20,saver20+4(r3) ; Load r20
+ lwz r21,saver21+4(r3) ; Load r21
+ lwz r22,saver22+4(r3) ; Load r22
+ lwz r23,saver23+4(r3) ; Load r23
+ lwz r24,saver24+4(r3) ; Load r24
+ lwz r25,saver25+4(r3) ; Load r25
+ lwz r26,saver26+4(r3) ; Load r26
+ lwz r27,saver27+4(r3) ; Load r27
+ lwz r28,saver28+4(r3) ; Load r28
+ lwz r29,saver29+4(r3) ; Load r29
+ lwz r30,saver30+4(r3) ; Load r30
+ lwz r31,saver31+4(r3) ; Load r31
+ b ufpnokey ; Continue
+ufprestore64:
+ ld r2,savexer(r3) ; Load xer
+ ld r8,saver8(r3) ; Load r8
+ ld r9,saver9(r3) ; Load r9
+ ld r10,saver10(r3) ; Load r10
+ mtxer r2 ; Restore xer
+ ld r11,saver11(r3) ; Load r11
+ ld r12,saver12(r3) ; Load r12
+ ld r13,saver13(r3) ; Load r12
+ ld r14,saver14(r3) ; Load r14
+ ld r15,saver15(r3) ; Load r15
+ ld r16,saver16(r3) ; Load r16
+ ld r17,saver17(r3) ; Load r17
+ ld r18,saver18(r3) ; Load r18
+ ld r19,saver19(r3) ; Load r19
+ ld r20,saver20(r3) ; Load r20
+ ld r21,saver21(r3) ; Load r21
+ ld r22,saver22(r3) ; Load r22
+ ld r23,saver23(r3) ; Load r23
+ ld r24,saver24(r3) ; Load r24
+ ld r25,saver25(r3) ; Load r25
+ ld r26,saver26(r3) ; Load r26
+ ld r27,saver27(r3) ; Load r27
+ ld r28,saver28(r3) ; Load r28
+ ld r29,saver29(r3) ; Load r29
+ ld r30,saver30(r3) ; Load r30
+ ld r31,saver31(r3) ; Load r31
+ufpnokey:
+ mfsprg r3,0 ; Get the per_proc area
+ mtsrr1 r4 ; Set srr1
+ lwz r0,famguestr0(r13) ; Load r0
+ lwz r1,famguestr1(r13) ; Load r1
+ lwz r2,famguestr2(r13) ; Load r2
+ lwz r3,famguestr3(r13) ; Load r3
+ lwz r4,famguestr4(r13) ; Load r4
+ lwz r5,famguestr5(r13) ; Load r5
+ lwz r6,famguestr6(r13) ; Load r6
+ lwz r7,famguestr7(r13) ; Load r7
+ufpVMret:
+ mfsprg r13,2 ; Restore R13
+ bt++ pf64Bitb,ufpVMrfi64 ; Go do this on a 64-bit machine...
+ mtcrf 0xFF,r11 ; Restore CR
+ mfsprg r11,3 ; Restore R11
+ rfi ; All done, go back...
+ufpVMrfi64:
+ mtcrf 0xFF,r11 ; Restore CR
+ mfsprg r11,3 ; Restore R11
+ rfid
+
+ufpX: ; here if virtual machine is 64-bit
+ bt cr5_eq,ufpXResumeGuest ; if kvmmResumeGuest, branch to ResumeGuest
+ cmplwi cr5,r4,7 ; Is first arg in range 0-7?
+ bgt cr5,ufpXVMret ; Return if not in the range
+ slwi r4,r4,3 ; multiply index by 8
+ la r3,famguestXr0(r13) ; Load the base address
+ bt cr2_eq,ufpXSetGuestReg ; Set/get selector
+; ufpXGetGuestReg
+ ldx r3,r4,r3 ; Load the guest register
+ b ufpXVMret ; Return
+ufpXSetGuestReg:
+ stdx r5,r4,r3 ; Update the guest register
+ li r3,0 ; Set return value
+ b ufpXVMret ; Return
+ufpXResumeGuest:
+ lwz r7,spcFlags(r3) ; Pick up the special flags
+ mtsrr0 r4 ; Set srr0
+ rlwinm. r6,r6,0,vmmKeyb,vmmKeyb ; Check vmmKeyb in maskCntrl
+ rlwinm r7,r7,0,FamVMmodebit+1,FamVMmodebit-1 ; Clear FamVMmodebit
+ stw r7,spcFlags(r3) ; Update the special flags
+ mfsrr1 r6 ; Get the current MSR value
+
+ ld r4,famguestXmsr(r13) ; Load guest srr1
+ lis r1,hi16(MSR_IMPORT_BITS) ; Get the MSR bits that are controllable by user
+ ori r1,r1,lo16(MSR_IMPORT_BITS) ; Get the rest of the MSR bits that are controllable by user
+ and r4,r4,r1 ; Keep only the controllable bits
+ oris r4,r4,hi16(MSR_EXPORT_MASK_SET) ; Force on the required bits
+ ori r4,r4,lo16(MSR_EXPORT_MASK_SET) ; Force on the other required bits
+ rlwimi r4,r6,0,MSR_FP_BIT,MSR_FP_BIT ; Propagate guest FP
+ rlwimi r4,r6,0,MSR_VEC_BIT,MSR_VEC_BIT ; Propagate guest Vector
+ beq ufpXnokey ; Branch if not key switch
+ mr r2,r7 ; Save r7
+ rlwimi r7,r5,32+vmmKeyb-userProtKeybit,userProtKeybit,userProtKeybit ; Set the protection key
+ cmpw cr0,r7,r2 ; Is userProtKeybit changed?
+ beq ufpXnokey ; No, go to ResumeGuest_nokey
+ mr r5,r3 ; Get the per_proc area
+ stw r7,spcFlags(r3) ; Update the special flags
+
+ ld r3,next_savearea(r5) ; Get the exception save area
+ std r8,saver8(r3) ; Save r8
+ std r9,saver9(r3) ; Save r9
+ std r10,saver10(r3) ; Save r10
+ std r11,saver11(r3) ; Save r11
+ std r12,saver12(r3) ; Save r12
+ std r13,saver13(r3) ; Save r12
+ std r14,saver14(r3) ; Save r14
+ std r15,saver15(r3) ; Save r15
+ std r16,saver16(r3) ; Save r16
+ std r17,saver17(r3) ; Save r17
+ std r18,saver18(r3) ; Save r18
+ std r19,saver19(r3) ; Save r19
+ std r20,saver20(r3) ; Save r20
+ std r21,saver21(r3) ; Save r21
+ std r22,saver22(r3) ; Save r22
+ std r23,saver23(r3) ; Save r23
+ std r24,saver24(r3) ; Save r24
+ std r25,saver25(r3) ; Save r25
+ std r26,saver26(r3) ; Save r26
+ std r27,saver27(r3) ; Save r27
+ std r28,saver28(r3) ; Save r28
+ std r29,saver29(r3) ; Save r29
+ mfxer r2 ; Get xer
+ std r30,saver30(r3) ; Save r30
+ std r31,saver31(r3) ; Save r31
+ std r2,savexer(r3) ; Save xer
+
+ mflr r20 ; Get lr
+ li r2,1 ; Set to 1
+ stw r7,spcFlags(r5) ; Update the special flags
+ mr r13,r3 ; Set current savearea
+ mr r21,r4 ; Save r4
+ sth r2,ppInvSeg(r5) ; Force a reload of the SRs
+ mr r29,r5 ; Get the per_proc area
+ mr r3,r4 ; Set MSR value we going to
+ bl EXT(switchSegs) ; Go handle the segment registers/STB
+ mr r3,r13 ; Set current savearea
+ mr r4,r21 ; Restore r4
+ mtlr r20 ; Set lr
+
+ ld r2,savexer(r3) ; Load xer
+ ld r8,saver8(r3) ; Load r8
+ ld r9,saver9(r3) ; Load r9
+ ld r10,saver10(r3) ; Load r10
+ mtxer r2 ; Restore xer
+ ld r11,saver11(r3) ; Load r11
+ ld r12,saver12(r3) ; Load r12
+ ld r13,saver13(r3) ; Load r12
+ ld r14,saver14(r3) ; Load r14
+ ld r15,saver15(r3) ; Load r15
+ ld r16,saver16(r3) ; Load r16
+ ld r17,saver17(r3) ; Load r17
+ ld r18,saver18(r3) ; Load r18
+ ld r19,saver19(r3) ; Load r19
+ ld r20,saver20(r3) ; Load r20
+ ld r21,saver21(r3) ; Load r21
+ ld r22,saver22(r3) ; Load r22
+ ld r23,saver23(r3) ; Load r23
+ ld r24,saver24(r3) ; Load r24
+ ld r25,saver25(r3) ; Load r25
+ ld r26,saver26(r3) ; Load r26
+ ld r27,saver27(r3) ; Load r27
+ ld r28,saver28(r3) ; Load r28
+ ld r29,saver29(r3) ; Load r29
+ ld r30,saver30(r3) ; Load r30
+ ld r31,saver31(r3) ; Load r31
+ufpXnokey:
+ mtsrr1 r4 ; Set srr1
+ ld r0,famguestXr0(r13) ; Load r0
+ ld r1,famguestXr1(r13) ; Load r1
+ ld r2,famguestXr2(r13) ; Load r2
+ ld r3,famguestXr3(r13) ; Load r3
+ ld r4,famguestXr4(r13) ; Load r4
+ ld r5,famguestXr5(r13) ; Load r5
+ ld r6,famguestXr6(r13) ; Load r6
+ ld r7,famguestXr7(r13) ; Load r7
+ufpXVMret:
+ mfsprg r13,2 ; Restore R13
+ mtcrf 0xFF,r11 ; Restore CR
+ mfsprg r11,3 ; Restore R11
+ rfid
+