]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/atomic_switch.s
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / ppc / atomic_switch.s
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 #include <ppc/asm.h>
26 #include <ppc/proc_reg.h>
27 #include <ppc/exception.h>
28 #include <mach/ppc/vm_param.h>
29 #include <assym.s>
30
31 /*
32 * Classic atomic switch and fast trap code
33 * Written by: Mark Gorlinsky
34 */
35
36 /*
37 **
38 ** Blue Box Fast Trap entry
39 **
40 **
41 ** The registers at entry are as hw_exceptions left them. Which means
42 ** that the Blue Box data area is pointed to be R26.
43 **
44 ** We exit here through the fast path exit point in hw_exceptions. That means that
45 ** upon exit, R4 must not change. It is the savearea with the current user context
46 ** to restore.
47 **
48 ** Input registers are:
49 ** r0 = Syscall number
50 ** r4 = Current context savearea (do not modify)
51 ** r13 = THREAD_TOP_ACT pointer
52 ** r26 = base of ACT_MACH_BDA in kernel address space
53 ** -- for Traps --
54 ** r24 = Index into TWI table (x4)
55 **
56 **
57 */
58
59
60 ENTRY(atomic_switch_syscall, TAG_NO_FRAME_USED)
61
62 /*
63 * Note: the BlueBox fast path system calls (-1 and -2) we handled as
64 * an ultra-fast trap in lowmem_vectors.
65 */
66 li r5, BTTD_SYSCALL_VECTOR
67 b .L_CallPseudoKernel
68
69 ENTRY(atomic_switch_trap, TAG_NO_FRAME_USED)
70
71 /*
72 ** functions 0-15 -> Call PseudoKernel
73 ** 16 -> Exit PseudoKernel
74 */
75
76 cmplwi cr7,r24,BB_RFI_TRAP ; Is this an RFI?
77 beq cr7,.L_ExitPseudoKernel ; Yes...
78
79 li r5, BTTD_TRAP_VECTOR
80
81 /******************************************************************************
82 * void CallPseudoKernel ( int vector, thread_act_t * act, BEDA_t * beda, savearea *sv )
83 *
84 * This op provides a means of invoking the BlueBox PseudoKernel from a
85 * system (68k) or native (PPC) context while changing BlueBox interruption
86 * state atomically. As an added bonus, this op leaves all but R1/PC of the user
87 * state registers intact. R1/PC are saved in a per thread save area, the base of
88 * which is located in the bbDescAddr member of the thread_act structure.
89 *
90 * This op is invoked from the Emulator Trap dispatch table or from a System
91 * Call when Mach SCs have been disabled. A vectorindex is passed in to indicate
92 * which vector should be taken.
93 *
94 * If this op is invoked from the Emulator Trap dispatch table, the kernel is
95 * aware of starting address of this table. It used the users PC (SRR0)
96 * and the start of the Trap dispatch table address to verify the trap exception
97 * as a atomic_switch trap. If a trap exception is verified as a atomic_switch
98 * trap we enter here with the following registers loaded.
99 *
100 * Input registers are:
101 * r5 = Vector to take
102 * r13 = Current thread context data
103 * r26 = Base address of BlueBox exception data area in kernel address space
104 * r4 = Current context savearea (do not modify)
105 *
106 ******************************************************************************/
107
108 .L_CallPseudoKernel:
109
110 mfsprg r2,0 ; Get the per_proc
111 rlwinm r6,r26,0,0,19 ; Start of page is bttd
112 lwz r7,ACT_MACT_SPF(r13) ; Get special flags
113 lwz r1,BTTD_INTERRUPT_VECTOR(r6) ; Get interrupt vector
114 rlwinm r7,r7,0,bbNoMachSCbit+1,bbNoMachSCbit-1
115 ; Reactivate Mach SCs
116 lwz r8,BTTD_INTCONTROLWORD(r6) ; Get Interrupt Control Word
117 cmpwi r1,0 ; Is this a preemptive thread ?
118 stw r7,ACT_MACT_SPF(r13) ; Update special flags
119 stw r7,spcFlags(r2) ; Update per_proc version
120 beq .L_CallFromPreemptiveThread ; No int vector means preemptive thread
121
122 rlwinm r1,r8,0,INTSTATEMASK_B,INTSTATEMASK_E
123 ; Extract current Interrupt state
124 rlwinm r8,r8,0,INTSTATEMASK_E+1,INTSTATEMASK_B-1
125 ; Clear current interrupt state
126 xoris r2,r1,SYSCONTEXTSTATE ; Setup for System Context check
127 lwz r1,savecr(r4) ; Load current CR bits
128 cmpwi r2,0 ; Check if state is System Context?
129 oris r8,r8,PSEUDOKERNELSTATE ; Update state for entering the PK
130 bne .L_CallFromAlternateContext ; No, then do not save CR2 bits
131
132 rlwimi r8,r1,32-INTCR2TOBACKUPSHIFT,INTBACKUPCR2MASK_B,INTBACKUPCR2MASK_E
133 ; Insert live CR2 in ICW BackupCR2
134 .L_CallFromAlternateContext:
135
136 stw r8,BTTD_INTCONTROLWORD(r6) ; Update ICW
137
138 .L_CallFromPreemptiveThread:
139
140 lwz r1,savesrr0(r4) ; Get current PC
141 lwz r2,saver1(r4) ; Get current R1
142 lwz r3,savesrr1(r4) ; Get current MSR
143 stw r1,BEDA_SRR0(r26) ; Save current PC
144 rlwinm r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1
145 ; Clear SE|BE bits in MSR
146 stw r2,BEDA_SPRG1(r26) ; Save current R1
147 stw r3,savesrr1(r4) ; Load new MSR
148
149 lwz r1,BEDA_SPRG0(r26) ; Get replacement R1
150 lwzx r2,r5,r6 ; Load vector address
151 stw r3,BEDA_SRR1(r26) ; Update saved MSR
152 stw r1,saver1(r4) ; Load up new R1
153 stw r2,savesrr0(r4) ; Save vector as PC
154
155 b EXT(fastexit) ; Go back and take the fast path exit...
156
157 /******************************************************************************
158 * void ExitPseudoKernel ( thread_act_t * act, BEDA_t * beda, savearea * sv )
159 *
160 * This op provides a means of exiting from the BlueBox PseudoKernel to a
161 * user context. This op attempts to simulate an RFI for the returning
162 * Traps (atomic_switch_trap) and SysCalls (atomic_switch_syscall). Only the
163 * Blue Thread handling interrupts is allowed to atomically change
164 * interruption state and handle pending interrupts.
165 *
166 * If an interrupt is pending and we are returning to the alternate context,
167 * the exit is aborted and we return to an pending interrupt handler in the
168 * Blue Box pseudokernel.
169 *
170 * It also allows the MSR's FE0, FE1, BE and SE bits to updated for the user
171 * and completes the PPC register loading.
172 *
173 * Input registers are:
174 * r4 = Current context savearea (do not modify)
175 * r13 = Pointer to the current active thread's data
176 * r26 = Base address of BlueBox Data in kernel address space
177 *
178 ******************************************************************************/
179
180 .L_ExitPseudoKernel:
181
182 rlwinm r6,r26,0,0,19 ; Start of page is bttd
183 lwz r7,ACT_MACT_SPF(r13) ; Get special flags
184 lwz r2,BTTD_INTERRUPT_VECTOR(r6) ; Get the interrupt vector
185 lwz r1,BEDA_SPRG1(r26) ; Get saved CTR
186 ori r7,r7,(0x8000 >> (bbNoMachSCbit - 16)) ; Disable Mach SCs for Blue Box
187
188 cmpwi r2,0 ; Is this a preemptive thread
189 stw r1,savectr(r4) ; Update CTR
190 beq .L_ExitFromPreemptiveThread
191
192 lwz r8,BTTD_INTCONTROLWORD(r6) ; Get ICW
193 lwz r1,BTTD_NEWEXITSTATE(r6) ; New interrupt state
194 lwz r2,BTTD_TESTINTMASK(r6) ; Get pending interrupt mask
195 lis r3,SYSCONTEXTSTATE ; Setup for check in system context
196 rlwimi r8,r1,0,INTSTATEMASK_B,INTSTATEMASK_E
197 ; Insert new state
198 cmplw cr1,r1,r3 ; System context ?
199 and. r2,r8,r2 ; Any pending interrupt?
200 lwz r1,savecr(r4) ; Get current CR
201
202 beq cr1,.L_ExitToSystemContext ; We are in system context
203 beq .L_ExitUpdateRuptControlWord ; We do not have a pending interrupt
204
205 lwz r2,saver1(r4) ; Get current R1
206 lwz r1,BEDA_SPRG0(r26) ; Get replacement R1
207 stw r2,BEDA_SPRG1(r26) ; Save current R1
208 stw r1,saver1(r4) ; Load up new R1
209 lwz r3,BTTD_PENDINGINT_VECTOR(r6) ; Get pending interrupt PC
210 b .L_ExitAbortExit ; Abort and Exit
211
212 .L_ExitToSystemContext:
213 rlwimi r1,r8,INTCR2TOBACKUPSHIFT,INTCR2MASK_B,INTCR2MASK_E
214 ; Insert live CR2 into backup CR2
215 .L_ExitUpdateRuptControlWord:
216 stw r8,BTTD_INTCONTROLWORD(r6) ; Update ICW
217 stw r1,savecr(r4) ; Update CR
218
219 .L_ExitFromPreemptiveThread:
220 mfsprg r3,0 ; Get the per_proc
221 lwz r2,savesrr1(r4) ; Get current MSR
222 lwz r1,BEDA_SRR1(r26) ; Get new MSR
223 stw r7,ACT_MACT_SPF(r13) ; Update special flags
224 stw r7,spcFlags(r3) ; Update per_proc version
225 rlwimi r2,r1,0,MSR_FE0_BIT,MSR_FE1_BIT
226 ; Insert FE0,FE1,SE,BE bits
227 lwz r3,BEDA_SRR0(r26) ; Get new PC
228 stw r2,savesrr1(r4) ; Update MSR
229
230 .L_ExitAbortExit:
231 stw r3,savesrr0(r4) ; Update PC
232
233 b EXT(fastexit) ; Go back and take the fast path exit...
234