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