/*
- * 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
* 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
*/
#include <sys/appleapiopts.h>
-#include <cpus.h>
#include <ppc/asm.h>
#include <ppc/proc_reg.h>
#include <ppc/exception.h>
// 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.
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
// 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
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:
//
// 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
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
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
// 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
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
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
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