]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ppc/Emulate64.s
xnu-792.12.6.tar.gz
[apple/xnu.git] / osfmk / ppc / Emulate64.s
index fff72fefb987d557e739c28484b90bec1f1d8fb8..a3c117d8c231ab83913ca4b293b62627c5410324 100644 (file)
@@ -1,26 +1,31 @@
 /*
  * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
- * 
- * 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
+ * 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.  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
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
+ *
+ * The Original Code and all software distributed under the License are 
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
+ * Please see the License for the specific language governing rights and 
  * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
+ *
+ * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
  */                                                                                                                                                                                    
 
 /* Emulate64.s
@@ -29,7 +34,6 @@
  */
  
 #include <sys/appleapiopts.h>
-#include <cpus.h>
 #include <ppc/asm.h>
 #include <ppc/proc_reg.h>
 #include <ppc/exception.h>
@@ -191,9 +195,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 +205,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
@@ -270,11 +274,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 +329,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 +337,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 +495,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 +531,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 +847,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