]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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. | |
11 | * | |
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 | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
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. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
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 | ||
57 | ENTRY(atomic_switch_syscall, TAG_NO_FRAME_USED) | |
58 | ||
59 | /* | |
60 | * Here's where we check for special Blue Box fast traps | |
61 | * If we don't recognize the syscall, we'll go back to regular processing | |
62 | */ | |
63 | cmpwi r0,-1 ; Is it NKIsPreemptiveTask | |
64 | beq- isBBpretask ; It is a fast syscall... | |
65 | cmpwi r0,-2 ; Is it kcNKIsPreemptiveTaskEnv | |
66 | bne- nofastSC ; Not a fast syscall... | |
67 | ||
68 | ; kcNKIsPreemptiveTaskEnv return task.taskEnv in r0 | |
69 | ||
70 | lwz r23, ACT_MACT_BTE(r13) ; Get the taskEnv | |
71 | stw r23, saver0(r4) ; Return the taskEnv in R0 | |
72 | ||
73 | isBBpretask: ; answer the question is this a preemptive task ? | |
74 | rlwinm r6,r26,0,0,19 ; Start of page is bttd | |
75 | lwz r1,BTTD_INTERRUPT_VECTOR(r6) ; Get interrupt vector | |
76 | lwz r6, savecr(r4) ; Get the current CCRs | |
77 | cmpwi r1,0 ; Is this a preemptive thread ? | |
78 | rlwinm r6,r6,0,cr0_eq+1,cr0_eq-1 ; Clear CR0 EQ bit | |
79 | bne notpretask ; Only the cooperative thread has an interrupt vector | |
80 | oris r6,r6,(0x8000 >> cr0_eq) ; Set CR0[eq] if task is preemptive. | |
81 | notpretask: | |
82 | stw r6, savecr(r4) ; Save the new current CCRs | |
83 | ||
84 | b EXT(fastexit) ; Take the fast path exit... | |
85 | ||
86 | nofastSC: | |
87 | li r5, BTTD_SYSCALL_VECTOR | |
88 | b .L_CallPseudoKernel | |
89 | ||
90 | ENTRY(atomic_switch_trap, TAG_NO_FRAME_USED) | |
91 | ||
92 | /* | |
93 | ** functions 0-15 -> Call PseudoKernel | |
94 | ** 16 -> Exit PseudoKernel | |
95 | */ | |
96 | ||
97 | cmplwi cr7,r24,BB_RFI_TRAP ; Is this an RFI? | |
98 | beq cr7,.L_ExitPseudoKernel ; Yes... | |
99 | ||
100 | li r5, BTTD_TRAP_VECTOR | |
101 | ||
102 | /****************************************************************************** | |
103 | * void CallPseudoKernel ( int vector, thread_act_t * act, BEDA_t * beda, savearea *sv ) | |
104 | * | |
105 | * This op provides a means of invoking the BlueBox PseudoKernel from a | |
106 | * system (68k) or native (PPC) context while changing BlueBox interruption | |
107 | * state atomically. As an added bonus, this op leaves all but R1/PC of the user | |
108 | * state registers intact. R1/PC are saved in a per thread save area, the base of | |
109 | * which is located in the bbDescAddr member of the thread_act structure. | |
110 | * | |
111 | * This op is invoked from the Emulator Trap dispatch table or from a System | |
112 | * Call when Mach SCs have been disabled. A vectorindex is passed in to indicate | |
113 | * which vector should be taken. | |
114 | * | |
115 | * If this op is invoked from the Emulator Trap dispatch table, the kernel is | |
116 | * aware of starting address of this table. It used the users PC (SRR0) | |
117 | * and the start of the Trap dispatch table address to verify the trap exception | |
118 | * as a atomic_switch trap. If a trap exception is verified as a atomic_switch | |
119 | * trap we enter here with the following registers loaded. | |
120 | * | |
121 | * Input registers are: | |
122 | * r5 = Vector to take | |
123 | * r13 = Current thread context data | |
124 | * r26 = Base address of BlueBox exception data area in kernel address space | |
125 | * r4 = Current context savearea (do not modify) | |
126 | * | |
127 | ******************************************************************************/ | |
128 | ||
129 | .L_CallPseudoKernel: | |
130 | ||
131 | rlwinm r6,r26,0,0,19 ; Start of page is bttd | |
132 | lwz r7,ACT_MACT_SPF(r13) ; Get special flags | |
133 | lwz r1,BTTD_INTERRUPT_VECTOR(r6) ; Get interrupt vector | |
134 | rlwinm r7,r7,0,bbNoMachSCbit+1,bbNoMachSCbit-1 | |
135 | ; Reactivate Mach SCs | |
136 | lwz r8,BTTD_INTCONTROLWORD(r6) ; Get Interrupt Control Word | |
137 | cmpwi r1,0 ; Is this a preemptive thread ? | |
138 | stw r7,ACT_MACT_SPF(r13) ; Update special flags | |
139 | beq .L_CallFromPreemptiveThread ; No int vector means preemptive thread | |
140 | ||
141 | rlwinm r1,r8,0,INTSTATEMASK_B,INTSTATEMASK_E | |
142 | ; Extract current Interrupt state | |
143 | rlwinm r8,r8,0,INTSTATEMASK_E+1,INTSTATEMASK_B-1 | |
144 | ; Clear current interrupt state | |
145 | xoris r2,r1,SYSCONTEXTSTATE ; Setup for System Context check | |
146 | lwz r1,savecr(r4) ; Load current CR bits | |
147 | cmpwi r2,0 ; Check if state is System Context? | |
148 | oris r8,r8,PSEUDOKERNELSTATE ; Update state for entering the PK | |
149 | bne .L_CallFromAlternateContext ; No, then do not save CR2 bits | |
150 | ||
151 | rlwimi r8,r1,32-INTCR2TOBACKUPSHIFT,INTBACKUPCR2MASK_B,INTBACKUPCR2MASK_E | |
152 | ; Insert live CR2 in ICW BackupCR2 | |
153 | .L_CallFromAlternateContext: | |
154 | ||
155 | stw r8,BTTD_INTCONTROLWORD(r6) ; Update ICW | |
156 | ||
157 | .L_CallFromPreemptiveThread: | |
158 | ||
159 | lwz r1,savesrr0(r4) ; Get current PC | |
160 | lwz r2,saver1(r4) ; Get current R1 | |
161 | lwz r3,savesrr1(r4) ; Get current MSR | |
162 | stw r1,BEDA_SRR0(r26) ; Save current PC | |
163 | rlwinm r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1 | |
164 | ; Clear SE|BE bits in MSR | |
165 | stw r2,BEDA_SPRG1(r26) ; Save current R1 | |
166 | stw r3,savesrr1(r4) ; Load new MSR | |
167 | ||
168 | lwz r1,BEDA_SPRG0(r26) ; Get replacement R1 | |
169 | lwzx r2,r5,r6 ; Load vector address | |
170 | stw r3,BEDA_SRR1(r26) ; Update saved MSR | |
171 | stw r1,saver1(r4) ; Load up new R1 | |
172 | stw r2,savesrr0(r4) ; Save vector as PC | |
173 | ||
174 | b EXT(fastexit) ; Go back and take the fast path exit... | |
175 | ||
176 | /****************************************************************************** | |
177 | * void ExitPseudoKernel ( thread_act_t * act, BEDA_t * beda, savearea * sv ) | |
178 | * | |
179 | * This op provides a means of exiting from the BlueBox PseudoKernel to a | |
180 | * user context. This op attempts to simulate an RFI for the returning | |
181 | * Traps (atomic_switch_trap) and SysCalls (atomic_switch_syscall). Only the | |
182 | * Blue Thread handling interrupts is allowed to atomically change | |
183 | * interruption state and handle pending interrupts. | |
184 | * | |
185 | * If an interrupt is pending and we are returning to the alternate context, | |
186 | * the exit is aborted and we return to an pending interrupt handler in the | |
187 | * Blue Box pseudokernel. | |
188 | * | |
189 | * It also allows the MSR's FE0, FE1, BE and SE bits to updated for the user | |
190 | * and completes the PPC register loading. | |
191 | * | |
192 | * Input registers are: | |
193 | * r4 = Current context savearea (do not modify) | |
194 | * r13 = Pointer to the current active thread's data | |
195 | * r26 = Base address of BlueBox Data in kernel address space | |
196 | * | |
197 | ******************************************************************************/ | |
198 | ||
199 | .L_ExitPseudoKernel: | |
200 | ||
201 | rlwinm r6,r26,0,0,19 ; Start of page is bttd | |
202 | lwz r7,ACT_MACT_SPF(r13) ; Get special flags | |
203 | lwz r2,BTTD_INTERRUPT_VECTOR(r6) ; Get the interrupt vector | |
204 | lwz r1,BEDA_SPRG1(r26) ; Get saved CTR | |
205 | oris r7,r7,(0x8000 >> bbNoMachSCbit) ; Disable Mach SCs for Blue Box | |
206 | ||
207 | cmpwi r2,0 ; Is this a preemptive thread | |
208 | stw r1,savectr(r4) ; Update CTR | |
209 | beq .L_ExitFromPreemptiveThread | |
210 | ||
211 | lwz r8,BTTD_INTCONTROLWORD(r6) ; Get ICW | |
212 | lwz r1,BTTD_NEWEXITSTATE(r6) ; New interrupt state | |
213 | lwz r2,BTTD_TESTINTMASK(r6) ; Get pending interrupt mask | |
214 | lis r3,SYSCONTEXTSTATE ; Setup for check in system context | |
215 | rlwimi r8,r1,0,INTSTATEMASK_B,INTSTATEMASK_E | |
216 | ; Insert new state | |
217 | cmplw cr1,r1,r3 ; System context ? | |
218 | and. r2,r8,r2 ; Any pending interrupt? | |
219 | lwz r1,savecr(r4) ; Get current CR | |
220 | ||
221 | beq cr1,.L_ExitToSystemContext ; We are in system context | |
222 | beq .L_ExitUpdateRuptControlWord ; We do not have a pending interrupt | |
223 | ||
224 | lwz r2,saver1(r4) ; Get current R1 | |
225 | lwz r1,BEDA_SPRG0(r26) ; Get replacement R1 | |
226 | stw r2,BEDA_SPRG1(r26) ; Save current R1 | |
227 | stw r1,saver1(r4) ; Load up new R1 | |
228 | lwz r3,BTTD_PENDINGINT_VECTOR(r6) ; Get pending interrupt PC | |
229 | b .L_ExitAbortExit ; Abort and Exit | |
230 | ||
231 | .L_ExitToSystemContext: | |
232 | rlwimi r1,r8,INTCR2TOBACKUPSHIFT,INTCR2MASK_B,INTCR2MASK_E | |
233 | ; Insert live CR2 into backup CR2 | |
234 | .L_ExitUpdateRuptControlWord: | |
235 | stw r8,BTTD_INTCONTROLWORD(r6) ; Update ICW | |
236 | stw r1,savecr(r4) ; Update CR | |
237 | ||
238 | .L_ExitFromPreemptiveThread: | |
239 | lwz r2,savesrr1(r4) ; Get current MSR | |
240 | lwz r1,BEDA_SRR1(r26) ; Get new MSR | |
241 | stw r7,ACT_MACT_SPF(r13) ; Update special flags | |
242 | rlwimi r2,r1,0,MSR_FE0_BIT,MSR_FE1_BIT | |
243 | ; Insert FE0,FE1,SE,BE bits | |
244 | lwz r3,BEDA_SRR0(r26) ; Get new PC | |
245 | stw r2,savesrr1(r4) ; Update MSR | |
246 | ||
247 | .L_ExitAbortExit: | |
248 | stw r3,savesrr0(r4) ; Update PC | |
249 | ||
250 | b EXT(fastexit) ; Go back and take the fast path exit... | |
251 |