X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/55e303ae13a4cf49d70f2294092726f2fffb9ef2..c331a0bec715536613c8dd5f34a4e115d5b15824:/osfmk/ppc/Emulate64.s diff --git a/osfmk/ppc/Emulate64.s b/osfmk/ppc/Emulate64.s index fff72fefb..2e7854d3f 100644 --- a/osfmk/ppc/Emulate64.s +++ b/osfmk/ppc/Emulate64.s @@ -1,16 +1,19 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2007 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Emulate64.s @@ -29,7 +32,6 @@ */ #include -#include #include #include #include @@ -191,9 +193,7 @@ a64NotEmulated: // This routine supports all legal permutations of alignment interrupts occuring in user or // supervisor mode, 32 or 64-bit addressing, and translation on or off. We do not emulate // instructions that go past the end of an address space, such as "LHZ -1(0)"; we just pass -// along the alignment exception rather than wrap around to byte 0. (Treatment of address -// space wrap is a moot point in Mac OS X, since we do not map either the last page or -// page 0.) +// along the alignment exception rather than wrap around to byte 0. // // First, check for a few special cases such as virtual machines, etc. @@ -203,11 +203,13 @@ LEXT(AlignAssist64) crset kAlignment // mark as alignment interrupt a64AlignAssistJoin: // join here from program interrupt handler + li r0,0 // Get a 0 mfsprg r31,0 // get the per_proc data ptr mcrf cr3,cr6 // save feature flags here... lwz r21,spcFlags(r31) // grab the special flags ld r29,savesrr1(r13) // get the MSR etc at the fault ld r28,savesrr0(r13) // get the EA of faulting instruction + stw r0,savemisc3(r13) // Assume we will handle this ok mfmsr r26 // save MSR at entry rlwinm. r0,r21,0,runningVMbit,runningVMbit // Are we running a VM? lwz r19,dgFlags(0) // Get the diagnostics flags @@ -227,8 +229,8 @@ a64AlignAssistJoin: // join here from program interrupt handler // r29 = SRR1 (ie, MSR at interrupt) // Note that EE and IR are always off, and SF is always on in this code. - rlwinm r3,r29,0,MSR_DR_BIT,MSR_DR_BIT // was translation on at fault? - rlwimi r3,r3,32-MSR_RI_BIT+MSR_DR_BIT,MSR_RI_BIT,MSR_RI_BIT // if DR was set, set RI too + rlwinm r3,r29,31,MSR_DR_BIT,MSR_DR_BIT // Move instruction translate bit to DR + rlwimi r3,r3,32-MSR_RI_BIT+MSR_DR_BIT,MSR_RI_BIT,MSR_RI_BIT // if DR is now set, set RI too or r25,r26,r3 // assemble MSR to use accessing target space @@ -253,6 +255,10 @@ a64AlignAssistJoin: // join here from program interrupt handler rlwinm. r0,r19,0,enaNotifyEMb,enaNotifyEMb // Should we notify? crnot kNotify,cr0_eq + rlwinm r3,r29,0,MSR_DR_BIT,MSR_DR_BIT // was data translation on at fault? + rlwimi r3,r3,32-MSR_RI_BIT+MSR_DR_BIT,MSR_RI_BIT,MSR_RI_BIT // if DR is now set, set RI too + or r25,r26,r3 // assemble MSR to use accessing target space + // Hash the intruction into a 5-bit value "AAAAB" used to index the branch table, and a // 1-bit kUpdate flag, as follows: @@ -270,11 +276,12 @@ a64AlignAssistJoin: // join here from program interrupt handler // // When we "bctr" to the opcode-specific reoutine, the following are all set up: // MSR = EE and IR off, SF and FP on +// r12 = full 64-bit EA (r17 is clamped EA) // r13 = save-area pointer (physical) // r14 = ptr to saver0 in save-area (ie, to base of GPRs) // r15 = 0x00000000FFFFFFFF if 32-bit mode fault, 0xFFFFFFFFFFFFFFFF if 64 // r16 = RA * 8 (ie, reg# not reg value) -// r17 = EA +// r17 = EA, clamped to 32 bits if 32-bit mode fault (see also r12) // r18 = (RA|0) (reg value) // r19 = -1 if X-form, 0 if D-form // r20 = faulting instruction @@ -324,7 +331,7 @@ a64GotInstruction: // here from program interrupt with instruction in r20 sradi r15,r29,32 // propogate SF bit from SRR1 (MSR_SF, which is bit 0) andc r18,r18,r24 // r18 <- (RA|0) mtcrf 0x02,r21 // move opcode bits 24-27 to CR6 (kUpdate is bit 25) - add r17,r18,r12 // r17 <- EA, which might need to be clamped to 32 bits + add r12,r18,r12 // r12 <- 64-bit EA mtctr r30 // set up branch address oris r15,r15,0xFFFF // start to fill low word of r15 with 1s @@ -332,7 +339,7 @@ a64GotInstruction: // here from program interrupt with instruction in r20 lis r22,ha16(EXT(aaFPopTable)) // start to compute address of floating pt table ori r15,r15,0xFFFF // now bits 32-63 of r15 are 1s addi r22,r22,lo16(EXT(aaFPopTable)) - and r17,r17,r15 // clamp EA to 32 bits if necessary + and r17,r12,r15 // clamp EA to 32 bits if fault occured in 32-bit mode rlwimi r22,r21,2,22,26 // move RT into aaFPopTable address (which is 1KB aligned) bf-- kAlignment,a64HandleProgramInt // return to Program Interrupt handler @@ -490,27 +497,30 @@ a64Stwbrx: // Load doubleword (ld[u], ldx[u]), also lwa. a64LdLwa: // these are DS form: ld=0, ldu=1, and lwa=2 - andi. r0,r20,2 // ld[u] or lwa? (test bit 30 of DS field) + mtcrf 0x01,r20 // move DS field to cr7 rlwinm r3,r20,0,30,31 // must adjust EA by subtracting DS field - sub r17,r17,r3 - and r17,r17,r15 // re-clamp to 32 bits if necessary - bne a64Lwa // handle lwa + sub r12,r12,r3 // subtract from full 64-bit EA + and r17,r12,r15 // then re-clamp to 32 bits if necessary + bt 30,a64Lwa // handle lwa + crmove kUpdate,31 // if opcode bit 31 is set, it is ldu so set update flag a64Ldx: bl a64Load8Bytes // load 8 bytes from user space into r30 stdx r30,r14,r21 // update register file b a64UpdateCheck // update RA if necessary and exit -// Store doubleword (stdx[u], std[u]) +// Store doubleword (stdx[u], std[u], stwcx) a64StdxStwcx: bf-- 30,a64PassAlong // stwcx, so pass along alignment exception b a64Stdx // was stdx -a64StdStfiwx: +a64StdStfiwx: // if DS form: 0=std, 1=stdu, 2-3=undefined bt 30,a64Stfiwx // handle stfiwx - rlwinm. r3,r20,0,30,31 // must adjust EA by subtracting DS field - sub r17,r17,r3 - and r17,r17,r15 // re-clamp to 32 bits if necessary + rlwinm r3,r20,0,30,31 // must adjust EA by subtracting DS field + mtcrf 0x01,r20 // move DS field to cr7 + sub r12,r12,r3 // subtract from full 64-bit EA + and r17,r12,r15 // then re-clamp to 32 bits if necessary + crmove kUpdate,31 // if DS==1, then it is update form a64Stdx: ldx r30,r14,r21 // get RT bl a64Store8Bytes // store RT into user space @@ -523,21 +533,21 @@ a64DcbzDcbz128: andis. r0,r20,0x0020 // bit 10 set? li r3,0 // get a 0 to store li r0,4 // assume 32-bit version, store 8 bytes 4x - li r4,_COMM_PAGE_BASE_ADDRESS rldicr r17,r17,0,63-5 // 32-byte align EA + li r4,_COMM_PAGE_BASE_ADDRESS beq a64DcbzSetup // it was the 32-byte version rldicr r17,r17,0,63-7 // zero low 7 bits of EA li r0,16 // store 8 bytes 16x a64DcbzSetup: - xor r4,r4,r28 // was dcbz in the commpage(s)? + sub r4,r28,r4 // get instruction offset from start of commpage and r4,r4,r15 // mask off high-order bits if 32-bit mode - srdi. r4,r4,12 // check SRR0 - bne a64NotCommpage // not in commpage + cmpldi r4,_COMM_PAGE_AREA_USED // did fault occur in commpage area? + bge a64NotCommpage // not in commpage rlwinm. r4,r29,0,MSR_PR_BIT,MSR_PR_BIT // did fault occur in user mode? beq-- a64NotCommpage // do not zero cr7 if kernel got alignment exception lwz r4,savecr(r13) // if we take a dcbz{128} in the commpage... rlwinm r4,r4,0,0,27 // ...clear user's cr7... - stw r4,savecr(r13) // ...as a flag for _COMM_PAGE_BIGCOPY + stw r4,savecr(r13) // ...as a flag for commpage code a64NotCommpage: mtctr r0 cmpw r0,r0 // turn cr0 beq on so we can check for DSIs @@ -839,12 +849,14 @@ a64ExitEm: b a64Exit // Join standard exit routine... a64PassAlong: // unhandled exception, just pass it along + li r0,1 // Set that the alignment/program exception was not emulated crset kNotify // return T_ALIGNMENT or T_PROGRAM + stw r0,savemisc3(r13) // Set that emulation was not done crclr kTrace // not a trace interrupt b a64Exit1 a64UpdateCheck: // successfully emulated, may be update form bf kUpdate,a64Exit // update? - stdx r17,r14,r16 // yes, store EA into RA + stdx r12,r14,r16 // yes, store 64-bit EA into RA a64Exit: // instruction successfully emulated addi r28,r28,4 // bump SRR0 past the emulated instruction li r30,T_IN_VAIN // eat the interrupt since we emulated it @@ -886,7 +898,7 @@ a64RedriveAsISI: // this DSI happened fetching the opcode (r1==DSISR r4==D mtmsr r26 // turn DR back off isync // wait for it to happen li r30,T_INSTRUCTION_ACCESS - rlwimi r29,r1,0,0,4 // insert the fault type from DSI's DSISR + rlwimi r29,r1,0,1,4 // insert the fault type from DSI's DSISR std r29,savesrr1(r13) // update SRR1 to look like an ISI b a64Redrive