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