]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
e5568f75 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. | |
1c79356b | 11 | * |
e5568f75 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 | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
e5568f75 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. | |
1c79356b A |
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 | /* | |
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 | ||
66 | ENTRY(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 |