]>
Commit | Line | Data |
---|---|---|
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 | cmplwi r24,0x3C ; (BRINGUP) | |
82 | bne .L_CallPseudoKernel ; (BRINGUP) | |
83 | nop ; (BRINGUP) | |
84 | ||
85 | /****************************************************************************** | |
86 | * void CallPseudoKernel ( int vector, thread_act_t * act, BEDA_t * beda, savearea *sv ) | |
87 | * | |
88 | * This op provides a means of invoking the BlueBox PseudoKernel from a | |
89 | * system (68k) or native (PPC) context while changing BlueBox interruption | |
90 | * state atomically. As an added bonus, this op leaves all but R1/PC of the user | |
91 | * state registers intact. R1/PC are saved in a per thread save area, the base of | |
92 | * which is located in the bbDescAddr member of the thread_act structure. | |
93 | * | |
94 | * This op is invoked from the Emulator Trap dispatch table or from a System | |
95 | * Call when Mach SCs have been disabled. A vectorindex is passed in to indicate | |
96 | * which vector should be taken. | |
97 | * | |
98 | * If this op is invoked from the Emulator Trap dispatch table, the kernel is | |
99 | * aware of starting address of this table. It used the users PC (SRR0) | |
100 | * and the start of the Trap dispatch table address to verify the trap exception | |
101 | * as a atomic_switch trap. If a trap exception is verified as a atomic_switch | |
102 | * trap we enter here with the following registers loaded. | |
103 | * | |
104 | * Input registers are: | |
105 | * r5 = Vector to take | |
106 | * r13 = Current thread context data | |
107 | * r26 = Base address of BlueBox exception data area in kernel address space | |
108 | * r4 = Current context savearea (do not modify) | |
109 | * | |
110 | ******************************************************************************/ | |
111 | ||
112 | .L_CallPseudoKernel: | |
113 | ||
114 | mfsprg r2,0 ; Get the per_proc | |
115 | rlwinm r6,r26,0,0,19 ; Start of page is bttd | |
116 | lwz r7,ACT_MACT_SPF(r13) ; Get special flags | |
117 | lwz r1,BTTD_INTERRUPT_VECTOR(r6) ; Get interrupt vector | |
118 | rlwinm r7,r7,0,bbNoMachSCbit+1,bbNoMachSCbit-1 | |
119 | ; Reactivate Mach SCs | |
120 | lwz r8,BTTD_INTCONTROLWORD(r6) ; Get Interrupt Control Word | |
121 | cmpwi r1,0 ; Is this a preemptive thread ? | |
122 | stw r7,ACT_MACT_SPF(r13) ; Update special flags | |
123 | stw r7,spcFlags(r2) ; Update per_proc version | |
124 | beq .L_CallFromPreemptiveThread ; No int vector means preemptive thread | |
125 | ||
126 | rlwinm r1,r8,0,INTSTATEMASK_B,INTSTATEMASK_E | |
127 | ; Extract current Interrupt state | |
128 | rlwinm r8,r8,0,INTSTATEMASK_E+1,INTSTATEMASK_B-1 | |
129 | ; Clear current interrupt state | |
130 | xoris r2,r1,SYSCONTEXTSTATE ; Setup for System Context check | |
131 | lwz r1,savecr(r4) ; Load current CR bits | |
132 | cmpwi r2,0 ; Check if state is System Context? | |
133 | oris r8,r8,PSEUDOKERNELSTATE ; Update state for entering the PK | |
134 | bne .L_CallFromAlternateContext ; No, then do not save CR2 bits | |
135 | ||
136 | rlwimi r8,r1,32-INTCR2TOBACKUPSHIFT,INTBACKUPCR2MASK_B,INTBACKUPCR2MASK_E | |
137 | ; Insert live CR2 in ICW BackupCR2 | |
138 | .L_CallFromAlternateContext: | |
139 | ||
140 | stw r8,BTTD_INTCONTROLWORD(r6) ; Update ICW | |
141 | ||
142 | .L_CallFromPreemptiveThread: | |
143 | ||
144 | lwz r1,savesrr0+4(r4) ; Get current PC | |
145 | lwz r2,saver1+4(r4) ; Get current R1 | |
146 | lwz r3,savesrr1+4(r4) ; Get current MSR | |
147 | stw r1,BEDA_SRR0(r26) ; Save current PC | |
148 | rlwinm r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1 | |
149 | ; Clear SE|BE bits in MSR | |
150 | stw r2,BEDA_SPRG1(r26) ; Save current R1 | |
151 | stw r3,savesrr1+4(r4) ; Load new MSR | |
152 | ||
153 | lwz r1,BEDA_SPRG0(r26) ; Get replacement R1 | |
154 | lwzx r2,r5,r6 ; Load vector address | |
155 | stw r3,BEDA_SRR1(r26) ; Update saved MSR | |
156 | stw r1,saver1+4(r4) ; Load up new R1 | |
157 | stw r2,savesrr0+4(r4) ; Save vector as PC | |
158 | ||
159 | b EXT(fastexit) ; Go back and take the fast path exit... | |
160 | ||
161 | /****************************************************************************** | |
162 | * void ExitPseudoKernel ( thread_act_t * act, BEDA_t * beda, savearea * sv ) | |
163 | * | |
164 | * This op provides a means of exiting from the BlueBox PseudoKernel to a | |
165 | * user context. This op attempts to simulate an RFI for the returning | |
166 | * Traps (atomic_switch_trap) and SysCalls (atomic_switch_syscall). Only the | |
167 | * Blue Thread handling interrupts is allowed to atomically change | |
168 | * interruption state and handle pending interrupts. | |
169 | * | |
170 | * If an interrupt is pending and we are returning to the alternate context, | |
171 | * the exit is aborted and we return to an pending interrupt handler in the | |
172 | * Blue Box pseudokernel. | |
173 | * | |
174 | * It also allows the MSR's FE0, FE1, BE and SE bits to updated for the user | |
175 | * and completes the PPC register loading. | |
176 | * | |
177 | * Input registers are: | |
178 | * r4 = Current context savearea (do not modify) | |
179 | * r13 = Pointer to the current active thread's data | |
180 | * r26 = Base address of BlueBox Data in kernel address space | |
181 | * | |
182 | ******************************************************************************/ | |
183 | ||
184 | .L_ExitPseudoKernel: | |
185 | ||
186 | rlwinm r6,r26,0,0,19 ; Start of page is bttd | |
187 | lwz r7,ACT_MACT_SPF(r13) ; Get special flags | |
188 | lwz r2,BTTD_INTERRUPT_VECTOR(r6) ; Get the interrupt vector | |
189 | lwz r1,BEDA_SPRG1(r26) ; Get saved CTR | |
190 | ori r7,r7,(0x8000 >> (bbNoMachSCbit - 16)) ; Disable Mach SCs for Blue Box | |
191 | ||
192 | cmpwi r2,0 ; Is this a preemptive thread | |
193 | stw r1,savectr+4(r4) ; Update CTR | |
194 | beq .L_ExitFromPreemptiveThread | |
195 | ||
196 | lwz r8,BTTD_INTCONTROLWORD(r6) ; Get ICW | |
197 | lwz r1,BTTD_NEWEXITSTATE(r6) ; New interrupt state | |
198 | lwz r2,BTTD_TESTINTMASK(r6) ; Get pending interrupt mask | |
199 | lis r3,SYSCONTEXTSTATE ; Setup for check in system context | |
200 | rlwimi r8,r1,0,INTSTATEMASK_B,INTSTATEMASK_E | |
201 | ; Insert new state | |
202 | cmplw cr1,r1,r3 ; System context ? | |
203 | and. r2,r8,r2 ; Any pending interrupt? | |
204 | lwz r1,savecr(r4) ; Get current CR | |
205 | ||
206 | beq cr1,.L_ExitToSystemContext ; We are in system context | |
207 | beq .L_ExitUpdateRuptControlWord ; We do not have a pending interrupt | |
208 | ||
209 | lwz r2,saver1+4(r4) ; Get current R1 | |
210 | lwz r1,BEDA_SPRG0(r26) ; Get replacement R1 | |
211 | stw r2,BEDA_SPRG1(r26) ; Save current R1 | |
212 | stw r1,saver1+4(r4) ; Load up new R1 | |
213 | lwz r3,BTTD_PENDINGINT_VECTOR(r6) ; Get pending interrupt PC | |
214 | b .L_ExitAbortExit ; Abort and Exit | |
215 | ||
216 | .L_ExitToSystemContext: | |
217 | rlwimi r1,r8,INTCR2TOBACKUPSHIFT,INTCR2MASK_B,INTCR2MASK_E | |
218 | ; Insert live CR2 into backup CR2 | |
219 | .L_ExitUpdateRuptControlWord: | |
220 | stw r8,BTTD_INTCONTROLWORD(r6) ; Update ICW | |
221 | stw r1,savecr(r4) ; Update CR | |
222 | ||
223 | .L_ExitFromPreemptiveThread: | |
224 | mfsprg r3,0 ; Get the per_proc | |
225 | lwz r2,savesrr1+4(r4) ; Get current MSR | |
226 | lwz r1,BEDA_SRR1(r26) ; Get new MSR | |
227 | stw r7,ACT_MACT_SPF(r13) ; Update special flags | |
228 | stw r7,spcFlags(r3) ; Update per_proc version | |
229 | rlwimi r2,r1,0,MSR_FE0_BIT,MSR_FE1_BIT | |
230 | ; Insert FE0,FE1,SE,BE bits | |
231 | lwz r3,BEDA_SRR0(r26) ; Get new PC | |
232 | stw r2,savesrr1+4(r4) ; Update MSR | |
233 | ||
234 | .L_ExitAbortExit: | |
235 | stw r3,savesrr0+4(r4) ; Update PC | |
236 | ||
237 | b EXT(fastexit) ; Go back and take the fast path exit... | |
238 |