]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
de355530 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 | * |
de355530 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, | |
de355530 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 | /* | |
23 | * @OSF_COPYRIGHT@ | |
24 | */ | |
25 | ||
26 | #include <ppc/asm.h> | |
27 | #include <ppc/proc_reg.h> | |
28 | #include <cpus.h> | |
29 | #include <assym.s> | |
30 | #include <debug.h> | |
31 | #include <mach/ppc/vm_param.h> | |
32 | #include <ppc/exception.h> | |
9bccf70c | 33 | #include <ppc/savearea.h> |
1c79356b A |
34 | |
35 | #define FPVECDBG 0 | |
36 | #define GDDBG 0 | |
37 | ||
38 | .text | |
39 | ||
40 | /* | |
41 | * void load_context(thread_t thread) | |
42 | * | |
43 | * Load the context for the first kernel thread, and go. | |
44 | * | |
45 | * NOTE - if DEBUG is set, the former routine is a piece | |
46 | * of C capable of printing out debug info before calling the latter, | |
47 | * otherwise both entry points are identical. | |
48 | */ | |
49 | ||
9bccf70c A |
50 | .align 5 |
51 | .globl EXT(load_context) | |
52 | ||
53 | LEXT(load_context) | |
54 | ||
55 | .globl EXT(Load_context) | |
56 | ||
57 | LEXT(Load_context) | |
1c79356b A |
58 | |
59 | /* | |
60 | * Since this is the first thread, we came in on the interrupt | |
61 | * stack. The first thread never returns, so there is no need to | |
de355530 | 62 | e worry about saving its frame, hence we can reset the istackptr |
1c79356b A |
63 | * back to the saved_state structure at it's top |
64 | */ | |
65 | ||
66 | ||
67 | /* | |
68 | * get new thread pointer and set it into the active_threads pointer | |
69 | * | |
70 | */ | |
71 | ||
72 | mfsprg r6,0 | |
73 | lwz r0,PP_INTSTACK_TOP_SS(r6) | |
1c79356b | 74 | stw r0,PP_ISTACKPTR(r6) |
9bccf70c | 75 | stw r3,PP_ACTIVE_THREAD(r6) |
1c79356b A |
76 | |
77 | /* Find the new stack and store it in active_stacks */ | |
78 | ||
79 | lwz r12,PP_ACTIVE_STACKS(r6) | |
80 | lwz r1,THREAD_KERNEL_STACK(r3) | |
81 | lwz r9,THREAD_TOP_ACT(r3) /* Point to the active activation */ | |
de355530 | 82 | mtsprg 1,r9 |
1c79356b A |
83 | stw r1,0(r12) |
84 | li r0,0 /* Clear a register */ | |
de355530 A |
85 | lwz r8,ACT_MACT_PCB(r9) /* Get the savearea used */ |
86 | rlwinm r7,r8,0,0,19 /* Switch to savearea base */ | |
87 | lwz r11,SAVprev(r8) /* Get the previous savearea */ | |
1c79356b | 88 | mfmsr r5 /* Since we are passing control, get our MSR values */ |
de355530 A |
89 | lwz r1,saver1(r8) /* Load new stack pointer */ |
90 | stw r0,saver3(r8) /* Make sure we pass in a 0 for the continuation */ | |
91 | lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */ | |
1c79356b | 92 | stw r0,FM_BACKPTR(r1) /* zero backptr */ |
de355530 A |
93 | stw r5,savesrr1(r8) /* Pass our MSR to the new guy */ |
94 | xor r3,r7,r8 /* Get the physical address of the new context save area */ | |
1c79356b A |
95 | stw r11,ACT_MACT_PCB(r9) /* Unstack our savearea */ |
96 | b EXT(exception_exit) /* Go end it all... */ | |
97 | ||
98 | /* struct thread_shuttle *Switch_context(struct thread_shuttle *old, | |
99 | * void (*cont)(void), | |
100 | * struct thread_shuttle *new) | |
101 | * | |
102 | * Switch from one thread to another. If a continuation is supplied, then | |
103 | * we do not need to save callee save registers. | |
104 | * | |
105 | */ | |
106 | ||
107 | /* void Call_continuation( void (*continuation)(void), vm_offset_t stack_ptr) | |
108 | */ | |
109 | ||
9bccf70c A |
110 | .align 5 |
111 | .globl EXT(Call_continuation) | |
112 | ||
113 | LEXT(Call_continuation) | |
114 | ||
115 | mtlr r3 | |
116 | mr r1, r4 /* Load new stack pointer */ | |
117 | blr /* Jump to the continuation */ | |
1c79356b A |
118 | |
119 | /* | |
120 | * Get the old kernel stack, and store into the thread structure. | |
121 | * See if a continuation is supplied, and skip state save if so. | |
de355530 A |
122 | * NB. Continuations are no longer used, so this test is omitted, |
123 | * as should the second argument, but it is in generic code. | |
124 | * We always save state. This does not hurt even if continuations | |
125 | * are put back in. | |
1c79356b A |
126 | */ |
127 | ||
128 | /* Context switches are double jumps. We pass the following to the | |
129 | * context switch firmware call: | |
130 | * | |
de355530 | 131 | * R3 = switchee's savearea |
1c79356b A |
132 | * R4 = old thread |
133 | * R5 = new SRR0 | |
134 | * R6 = new SRR1 | |
135 | * | |
136 | * savesrr0 is set to go to switch_in | |
137 | * savesrr1 is set to uninterruptible with translation on | |
138 | */ | |
139 | ||
140 | ||
9bccf70c A |
141 | .align 5 |
142 | .globl EXT(Switch_context) | |
1c79356b | 143 | |
9bccf70c A |
144 | LEXT(Switch_context) |
145 | ||
146 | mfsprg r12,0 ; Get the per_proc block | |
147 | lwz r10,PP_ACTIVE_STACKS(r12) ; Get the pointer to the current stack | |
1c79356b | 148 | #if DEBUG |
de355530 A |
149 | lwz r11,PP_ISTACKPTR(r12) ; (DEBUG/TRACE) make sure we are not |
150 | mr. r11,r11 ; (DEBUG/TRACE) on the interrupt | |
151 | bne+ notonintstack ; (DEBUG/TRACE) stack | |
1c79356b A |
152 | BREAKPOINT_TRAP |
153 | notonintstack: | |
154 | #endif | |
de355530 A |
155 | stw r4,THREAD_CONTINUATION(r3) ; Set continuation into the thread |
156 | cmpwi cr1,r4,0 ; used waaaay down below | |
9bccf70c | 157 | lwz r7,0(r10) ; Get the current stack |
de355530 A |
158 | /* |
159 | * Make the new thread the current thread. | |
160 | */ | |
161 | ||
9bccf70c | 162 | stw r7,THREAD_KERNEL_STACK(r3) ; Remember the current stack in the thread (do not need???) |
de355530 A |
163 | stw r5, PP_ACTIVE_THREAD(r12) ; Make the new thread current |
164 | ||
165 | lwz r11,THREAD_KERNEL_STACK(r5) ; Get the new stack pointer | |
166 | ||
167 | lwz r5,THREAD_TOP_ACT(r5) ; Get the new activation | |
168 | mtsprg 1,r5 | |
1c79356b | 169 | lwz r7,CTHREAD_SELF(r5) ; Pick up the user assist word |
de355530 A |
170 | lwz r8,ACT_MACT_PCB(r5) ; Get the PCB for the new guy |
171 | ||
172 | #if 0 | |
173 | lwz r0,SAVflags(r8) ; (TEST/DEBUG) | |
174 | rlwinm r0,r0,24,24,31 ; (TEST/DEBUG) | |
175 | cmplwi r0,SAVempty ; (TEST/DEBUG) | |
176 | bne+ nnnn ; (TEST/DEBUG) | |
177 | b . ; (TEST/DEBUG) | |
178 | nnnn: ; (TEST/DEBUG) | |
179 | #endif | |
9bccf70c | 180 | |
de355530 | 181 | stw r11,0(r10) ; Save the new kernel stack address |
9bccf70c | 182 | stw r7,UAW(r12) ; Save the assist word for the "ultra fast path" |
de355530 A |
183 | |
184 | lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment | |
185 | ||
1c79356b A |
186 | lwz r7,ACT_MACT_SPF(r5) ; Get the special flags |
187 | ||
de355530 | 188 | lwz r10,ACT_KLOADED(r5) |
9bccf70c | 189 | stw r11,ppbbTaskEnv(r12) ; Save the bb task env |
de355530 A |
190 | li r0,0 |
191 | cmpwi cr0,r10,0 | |
192 | lwz r10,PP_ACTIVE_KLOADED(r12) | |
9bccf70c | 193 | stw r7,spcFlags(r12) ; Set per_proc copy of the special flags |
de355530 | 194 | beq cr0,.L_sw_ctx_not_kld |
1c79356b | 195 | |
de355530 A |
196 | stw r5,0(r10) |
197 | b .L_sw_ctx_cont | |
198 | ||
199 | .L_sw_ctx_not_kld: | |
200 | stw r0,0(r10) /* act_kloaded = 0 */ | |
201 | ||
202 | .L_sw_ctx_cont: | |
203 | lis r10,hi16(EXT(trcWork)) ; Get top of trace mask | |
204 | rlwinm r7,r8,0,0,19 /* Switch to savearea base */ | |
205 | ori r10,r10,lo16(EXT(trcWork)) ; Get bottom of mask | |
206 | lwz r11,SAVprev(r8) /* Get the previous of the switchee's savearea */ | |
207 | lwz r10,traceMask(r10) ; Get the enabled traces | |
1c79356b | 208 | lis r0,hi16(CutTrace) ; Trace FW call |
de355530 | 209 | mr. r10,r10 ; Any tracing going on? |
1c79356b | 210 | ori r0,r0,lo16(CutTrace) ; Trace FW call |
de355530 | 211 | beq+ cswNoTrc ; No trace today, dude... |
1c79356b A |
212 | mr r10,r3 ; Save across trace |
213 | lwz r2,THREAD_TOP_ACT(r3) ; Trace old activation | |
214 | mr r3,r11 ; Trace prev savearea | |
215 | sc ; Cut trace entry of context switch | |
216 | mr r3,r10 ; Restore | |
217 | ||
de355530 A |
218 | cswNoTrc: mfmsr r6 /* Get the MSR because the switched to thread should inherit it */ |
219 | lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */ | |
220 | stw r11,ACT_MACT_PCB(r5) /* Dequeue the savearea we're switching to */ | |
221 | ||
222 | rlwinm r6,r6,0,MSR_FP_BIT+1,MSR_FP_BIT-1 /* Turn off the FP */ | |
223 | lwz r2,curctx(r5) ; Grab our current context pointer | |
224 | rlwinm r6,r6,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 /* Turn off the vector */ | |
225 | mr r4,r3 /* Save our old thread to pass back */ | |
226 | ||
227 | lhz r0,PP_CPU_NUMBER(r12) ; Get our CPU number | |
9bccf70c A |
228 | lwz r10,FPUowner(r12) ; Grab the owner of the FPU |
229 | lwz r9,VMXowner(r12) ; Grab the owner of the vector | |
230 | cmplw r10,r2 ; Do we have the live float context? | |
231 | lwz r10,FPUlevel(r2) ; Get the live level | |
232 | cmplw cr5,r9,r2 ; Do we have the live vector context? | |
de355530 | 233 | bne+ cswnofloat ; Float is not ours... |
9bccf70c A |
234 | |
235 | cmplw r10,r11 ; Is the level the same? | |
236 | lwz r5,FPUcpu(r2) ; Get the owning cpu | |
de355530 | 237 | bne+ cswnofloat ; Level not the same, this is not live... |
9bccf70c A |
238 | |
239 | cmplw r5,r0 ; Still owned by this cpu? | |
240 | lwz r10,FPUsave(r2) ; Get the level | |
de355530 | 241 | bne+ cswnofloat ; CPU claimed by someone else... |
9bccf70c A |
242 | |
243 | mr. r10,r10 ; Is there a savearea here? | |
244 | ori r6,r6,lo16(MASK(MSR_FP)) ; Enable floating point | |
245 | ||
de355530 | 246 | beq- cswnofloat ; No savearea to check... |
9bccf70c A |
247 | |
248 | lwz r3,SAVlevel(r10) ; Get the level | |
de355530 | 249 | lwz r5,SAVprev(r10) ; Get the previous of this savearea |
9bccf70c A |
250 | cmplw r3,r11 ; Is it for the current level? |
251 | ||
de355530 | 252 | bne+ cswnofloat ; Nope... |
9bccf70c A |
253 | |
254 | stw r5,FPUsave(r2) ; Pop off this savearea | |
de355530 A |
255 | rlwinm r5,r10,0,0,19 ; Move back to start of page |
256 | lwz r5,SACvrswap(r5) ; Get the virtual to real conversion | |
257 | la r9,quickfret(r12) ; Point to the quickfret chain header | |
258 | xor r5,r10,r5 ; Convert savearea address to real | |
9bccf70c A |
259 | |
260 | #if FPVECDBG | |
261 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
262 | li r2,0x4401 ; (TEST/DEBUG) | |
263 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
264 | sc ; (TEST/DEBUG) | |
265 | lhz r0,PP_CPU_NUMBER(r12) ; (TEST/DEBUG) | |
266 | #endif | |
267 | ||
de355530 A |
268 | ; |
269 | ; Note: we need to do the atomic operation here because, even though | |
270 | ; it is impossible with the current implementation, that we may take a | |
271 | ; PTE miss between the load of the quickfret anchor and the subsequent | |
272 | ; store. The interrupt handler will dequeue everything on the list and | |
273 | ; we could end up using stale data. I do not like doing this... | |
274 | ; | |
275 | ||
276 | cswfpudq: lwarx r3,0,r9 ; Pick up the old chain head | |
277 | stw r3,SAVprev(r10) ; Move it to the current guy | |
278 | stwcx. r5,0,r9 ; Save it | |
279 | bne- cswfpudq ; Someone chaged the list... | |
280 | ||
281 | cswnofloat: bne+ cr5,cswnovect ; Vector is not ours... | |
9bccf70c A |
282 | |
283 | lwz r10,VMXlevel(r2) ; Get the live level | |
284 | ||
285 | cmplw r10,r11 ; Is the level the same? | |
286 | lwz r5,VMXcpu(r2) ; Get the owning cpu | |
de355530 | 287 | bne+ cswnovect ; Level not the same, this is not live... |
9bccf70c A |
288 | |
289 | cmplw r5,r0 ; Still owned by this cpu? | |
290 | lwz r10,VMXsave(r2) ; Get the level | |
de355530 | 291 | bne+ cswnovect ; CPU claimed by someone else... |
9bccf70c A |
292 | |
293 | mr. r10,r10 ; Is there a savearea here? | |
294 | oris r6,r6,hi16(MASK(MSR_VEC)) ; Enable vector | |
295 | ||
de355530 | 296 | beq- cswnovect ; No savearea to check... |
9bccf70c A |
297 | |
298 | lwz r3,SAVlevel(r10) ; Get the level | |
de355530 | 299 | lwz r5,SAVprev(r10) ; Get the previous of this savearea |
9bccf70c A |
300 | cmplw r3,r11 ; Is it for the current level? |
301 | ||
de355530 | 302 | bne+ cswnovect ; Nope... |
9bccf70c A |
303 | |
304 | stw r5,VMXsave(r2) ; Pop off this savearea | |
de355530 A |
305 | rlwinm r5,r10,0,0,19 ; Move back to start of page |
306 | lwz r5,SACvrswap(r5) ; Get the virtual to real conversion | |
307 | la r9,quickfret(r12) ; Point to the quickfret chain header | |
308 | xor r5,r10,r5 ; Convert savearea address to real | |
9bccf70c A |
309 | |
310 | #if FPVECDBG | |
311 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
312 | li r2,0x4501 ; (TEST/DEBUG) | |
313 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
314 | sc ; (TEST/DEBUG) | |
315 | #endif | |
316 | ||
de355530 A |
317 | ; |
318 | ; Note: we need to do the atomic operation here because, even though | |
319 | ; it is impossible with the current implementation, that we may take a | |
320 | ; PTE miss between the load of the quickfret anchor and the subsequent | |
321 | ; store. The interrupt handler will dequeue everything on the list and | |
322 | ; we could end up using stale data. I do not like doing this... | |
323 | ; | |
9bccf70c | 324 | |
de355530 A |
325 | cswvecdq: lwarx r3,0,r9 ; Pick up the old chain head |
326 | stw r3,SAVprev(r10) ; Move it to the current guy | |
327 | stwcx. r5,0,r9 ; Save it | |
328 | bne- cswvecdq ; Someone chaged the list... | |
329 | ||
330 | cswnovect: lis r9,hi16(EXT(switch_in)) /* Get top of switch in routine */ | |
331 | lwz r5,savesrr0(r8) /* Set up the new SRR0 */ | |
332 | ori r9,r9,lo16(EXT(switch_in)) /* Bottom half of switch in */ | |
9bccf70c | 333 | lis r0,hi16(SwitchContextCall) /* Top part of switch context */ |
de355530 A |
334 | stw r9,savesrr0(r8) /* Make us jump to the switch in routine */ |
335 | ||
1c79356b | 336 | li r10,MSR_SUPERVISOR_INT_OFF /* Get the switcher's MSR */ |
de355530 A |
337 | lwz r9,SAVflags(r8) /* Get the flags */ |
338 | stw r10,savesrr1(r8) /* Set up for switch in */ | |
d7e50217 | 339 | rlwinm r9,r9,0,15,13 /* Reset the syscall flag */ |
de355530 A |
340 | ori r0,r0,lo16(SwitchContextCall) /* Bottom part of switch context */ |
341 | xor r3,r7,r8 /* Get the physical address of the new context save area */ | |
1c79356b | 342 | stw r9,SAVflags(r8) /* Set the flags */ |
9bccf70c A |
343 | |
344 | bne cr1,swtchtocont ; Switch to the continuation | |
1c79356b A |
345 | sc /* Switch to the new context */ |
346 | ||
347 | /* We come back here in the new thread context | |
348 | * R4 was set to hold the old thread pointer, but switch_in will put it into | |
349 | * R3 where it belongs. | |
350 | */ | |
351 | blr /* Jump into the new thread */ | |
9bccf70c A |
352 | |
353 | ; | |
354 | ; This is where we go when a continuation is set. We are actually | |
355 | ; killing off the old context of the new guy so we need to pop off | |
356 | ; any float or vector states for the ditched level. | |
357 | ; | |
358 | ; Note that we do the same kind of thing a chkfac in hw_exceptions.s | |
359 | ; | |
360 | ||
1c79356b | 361 | |
9bccf70c | 362 | swtchtocont: |
de355530 A |
363 | stw r5,savesrr0(r8) ; Set the pc |
364 | stw r6,savesrr1(r8) ; Set the next MSR to use | |
365 | stw r4,saver3(r8) ; Make sure we pass back the old thread | |
9bccf70c A |
366 | |
367 | b EXT(exception_exit) ; Blocking on continuation, toss old context... | |
1c79356b A |
368 | |
369 | ||
370 | ||
371 | /* | |
372 | * All switched to threads come here first to clean up the old thread. | |
373 | * We need to do the following contortions because we need to keep | |
374 | * the LR clean. And because we need to manipulate the savearea chain | |
375 | * with translation on. If we could, this should be done in lowmem_vectors | |
376 | * before translation is turned on. But we can't, dang it! | |
377 | * | |
de355530 | 378 | * R3 = switcher's savearea |
1c79356b A |
379 | * saver4 = old thread in switcher's save |
380 | * saver5 = new SRR0 in switcher's save | |
381 | * saver6 = new SRR1 in switcher's save | |
382 | ||
383 | ||
384 | */ | |
385 | ||
9bccf70c A |
386 | |
387 | .align 5 | |
388 | .globl EXT(switch_in) | |
389 | ||
390 | LEXT(switch_in) | |
d7e50217 | 391 | |
de355530 A |
392 | lwz r4,saver4(r3) /* Get the old thread */ |
393 | lwz r9,THREAD_TOP_ACT(r4) /* Get the switched from ACT */ | |
394 | lwz r5,saver5(r3) /* Get the srr0 value */ | |
395 | lwz r10,ACT_MACT_PCB(r9) /* Get the top PCB on the old thread */ | |
396 | lwz r6,saver6(r3) /* Get the srr1 value */ | |
1c79356b | 397 | |
de355530 A |
398 | stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */ |
399 | stw r10,SAVprev(r3) /* Chain on the old one */ | |
1c79356b | 400 | |
de355530 A |
401 | mr r3,r4 /* Pass back the old thread */ |
402 | ||
403 | mtsrr0 r5 /* Set return point */ | |
404 | mtsrr1 r6 /* Set return MSR */ | |
405 | rfi /* Jam... */ | |
406 | .long 0 | |
407 | .long 0 | |
408 | .long 0 | |
409 | .long 0 | |
410 | .long 0 | |
411 | .long 0 | |
412 | .long 0 | |
413 | .long 0 | |
1c79356b A |
414 | |
415 | ||
416 | ||
417 | /* | |
9bccf70c | 418 | * void fpu_save(facility_context ctx) |
1c79356b | 419 | * |
9bccf70c A |
420 | * Note that there are some oddities here when we save a context we are using. |
421 | * It is really not too cool to do this, but what the hey... Anyway, | |
422 | * we turn fpus and vecs off before we leave., The oddity is that if you use fpus after this, the | |
423 | * savearea containing the context just saved will go away. So, bottom line is | |
424 | * that don't use fpus until after you are done with the saved context. | |
1c79356b | 425 | */ |
9bccf70c A |
426 | .align 5 |
427 | .globl EXT(fpu_save) | |
1c79356b | 428 | |
9bccf70c A |
429 | LEXT(fpu_save) |
430 | ||
431 | ||
432 | mfmsr r0 ; Get the MSR | |
de355530 A |
433 | rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off |
434 | rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now | |
9bccf70c | 435 | ori r2,r2,MASK(MSR_FP) ; Enable the floating point feature for now also |
de355530 | 436 | rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off |
9bccf70c | 437 | mtmsr r2 ; Set the MSR |
1c79356b | 438 | isync |
9bccf70c A |
439 | |
440 | mfsprg r6,0 ; Get the per_processor block | |
441 | lwz r12,FPUowner(r6) ; Get the context ID for owner | |
442 | ||
1c79356b | 443 | #if FPVECDBG |
9bccf70c A |
444 | mr r7,r0 ; (TEST/DEBUG) |
445 | li r4,0 ; (TEST/DEBUG) | |
446 | mr r10,r3 ; (TEST/DEBUG) | |
447 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
448 | mr. r3,r12 ; (TEST/DEBUG) | |
449 | li r2,0x6F00 ; (TEST/DEBUG) | |
450 | li r5,0 ; (TEST/DEBUG) | |
de355530 | 451 | beq- noowneryet ; (TEST/DEBUG) |
9bccf70c A |
452 | lwz r4,FPUlevel(r12) ; (TEST/DEBUG) |
453 | lwz r5,FPUsave(r12) ; (TEST/DEBUG) | |
454 | ||
455 | noowneryet: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
456 | sc ; (TEST/DEBUG) | |
457 | mr r0,r7 ; (TEST/DEBUG) | |
458 | mr r3,r10 ; (TEST/DEBUG) | |
1c79356b | 459 | #endif |
9bccf70c A |
460 | mflr r2 ; Save the return address |
461 | ||
462 | fsretry: mr. r12,r12 ; Anyone own the FPU? | |
463 | lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number | |
de355530 | 464 | beq- fsret ; Nobody owns the FPU, no save required... |
1c79356b | 465 | |
9bccf70c | 466 | cmplw cr1,r3,r12 ; Is the specified context live? |
1c79356b | 467 | |
9bccf70c | 468 | isync ; Force owner check first |
1c79356b | 469 | |
9bccf70c | 470 | lwz r9,FPUcpu(r12) ; Get the cpu that context was last on |
de355530 | 471 | bne- cr1,fsret ; No, it is not... |
1c79356b | 472 | |
9bccf70c | 473 | cmplw cr1,r9,r11 ; Was the context for this processor? |
de355530 | 474 | beq- cr1,fsgoodcpu ; Facility last used on this processor... |
0b4e3aa0 | 475 | |
9bccf70c | 476 | b fsret ; Someone else claimed it... |
1c79356b | 477 | |
9bccf70c | 478 | .align 5 |
1c79356b | 479 | |
9bccf70c A |
480 | fsgoodcpu: lwz r3,FPUsave(r12) ; Get the current FPU savearea for the thread |
481 | lwz r9,FPUlevel(r12) ; Get our current level indicator | |
1c79356b | 482 | |
9bccf70c A |
483 | cmplwi cr1,r3,0 ; Have we ever saved this facility context? |
484 | beq- cr1,fsneedone ; Never saved it, so go do it... | |
1c79356b | 485 | |
9bccf70c A |
486 | lwz r8,SAVlevel(r3) ; Get the level this savearea is for |
487 | cmplw cr1,r9,r8 ; Correct level? | |
de355530 | 488 | beq- cr1,fsret ; The current level is already saved, bail out... |
1c79356b | 489 | |
9bccf70c A |
490 | fsneedone: bl EXT(save_get) ; Get a savearea for the context |
491 | ||
492 | mfsprg r6,0 ; Get back per_processor block | |
493 | li r4,SAVfloat ; Get floating point tag | |
494 | lwz r12,FPUowner(r6) ; Get back our thread | |
495 | stb r4,SAVflags+2(r3) ; Mark this savearea as a float | |
496 | mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it... | |
de355530 | 497 | beq- fsbackout ; If disowned, just toss savearea... |
9bccf70c | 498 | lwz r4,facAct(r12) ; Get the activation associated with live context |
de355530 | 499 | mtlr r2 ; Restore return |
9bccf70c A |
500 | lwz r8,FPUsave(r12) ; Get the current top floating point savearea |
501 | stw r4,SAVact(r3) ; Indicate the right activation for this context | |
502 | lwz r9,FPUlevel(r12) ; Get our current level indicator again | |
503 | stw r3,FPUsave(r12) ; Set this as the most current floating point context | |
de355530 | 504 | stw r8,SAVprev(r3) ; And then chain this in front |
1c79356b | 505 | |
9bccf70c | 506 | stw r9,SAVlevel(r3) ; Show level in savearea |
1c79356b | 507 | |
de355530 A |
508 | ; |
509 | ; Save the current FPU state into the PCB of the thread that owns it. | |
510 | ; | |
511 | ||
512 | la r11,savefp0(r3) ; Point to the 1st line | |
513 | dcbz 0,r11 ; Allocate the first savearea line | |
514 | ||
515 | la r11,savefp4(r3) ; Point to the 2nd line | |
516 | stfd f0,savefp0(r3) | |
517 | dcbz 0,r11 ; Allocate it | |
518 | stfd f1,savefp1(r3) | |
519 | stfd f2,savefp2(r3) | |
520 | la r11,savefp8(r3) ; Point to the 3rd line | |
521 | stfd f3,savefp3(r3) | |
522 | dcbz 0,r11 ; Allocate it | |
523 | stfd f4,savefp4(r3) | |
524 | stfd f5,savefp5(r3) | |
525 | stfd f6,savefp6(r3) | |
526 | la r11,savefp12(r3) ; Point to the 4th line | |
527 | stfd f7,savefp7(r3) | |
528 | dcbz 0,r11 ; Allocate it | |
529 | stfd f8,savefp8(r3) | |
530 | stfd f9,savefp9(r3) | |
531 | stfd f10,savefp10(r3) | |
532 | la r11,savefp16(r3) ; Point to the 5th line | |
533 | stfd f11,savefp11(r3) | |
534 | dcbz 0,r11 ; Allocate it | |
535 | stfd f12,savefp12(r3) | |
536 | stfd f13,savefp13(r3) | |
537 | stfd f14,savefp14(r3) | |
538 | la r11,savefp20(r3) ; Point to the 6th line | |
539 | stfd f15,savefp15(r3) | |
540 | stfd f16,savefp16(r3) | |
541 | stfd f17,savefp17(r3) | |
542 | stfd f18,savefp18(r3) | |
543 | la r11,savefp24(r3) ; Point to the 7th line | |
544 | stfd f19,savefp19(r3) | |
545 | dcbz 0,r11 ; Allocate it | |
546 | stfd f20,savefp20(r3) | |
547 | stfd f21,savefp21(r3) | |
548 | stfd f22,savefp22(r3) | |
549 | la r11,savefp28(r3) ; Point to the 8th line | |
550 | stfd f23,savefp23(r3) | |
551 | dcbz 0,r11 ; Allocate it | |
552 | stfd f24,savefp24(r3) | |
553 | stfd f25,savefp25(r3) | |
554 | stfd f26,savefp26(r3) | |
555 | stfd f27,savefp27(r3) | |
556 | stfd f28,savefp28(r3) | |
557 | ||
558 | stfd f29,savefp29(r3) | |
559 | stfd f30,savefp30(r3) | |
560 | stfd f31,savefp31(r3) | |
561 | ||
9bccf70c | 562 | fsret: mtmsr r0 ; Put interrupts on if they were and floating point off |
1c79356b A |
563 | isync |
564 | ||
565 | blr | |
566 | ||
de355530 A |
567 | fsbackout: mr r12,r0 ; Save the original MSR |
568 | b EXT(save_ret_join) ; Toss savearea and return from there... | |
9bccf70c | 569 | |
1c79356b A |
570 | /* |
571 | * fpu_switch() | |
572 | * | |
573 | * Entered to handle the floating-point unavailable exception and | |
574 | * switch fpu context | |
575 | * | |
576 | * This code is run in virtual address mode on with interrupts off. | |
577 | * | |
578 | * Upon exit, the code returns to the users context with the floating | |
579 | * point facility turned on. | |
580 | * | |
581 | * ENTRY: VM switched ON | |
582 | * Interrupts OFF | |
583 | * State is saved in savearea pointed to by R4. | |
584 | * All other registers are free. | |
585 | * | |
586 | */ | |
587 | ||
9bccf70c A |
588 | .align 5 |
589 | .globl EXT(fpu_switch) | |
590 | ||
591 | LEXT(fpu_switch) | |
592 | ||
1c79356b | 593 | #if DEBUG |
1c79356b A |
594 | lis r3,hi16(EXT(fpu_trap_count)) ; Get address of FP trap counter |
595 | ori r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter | |
596 | lwz r1,0(r3) | |
597 | addi r1,r1,1 | |
598 | stw r1,0(r3) | |
1c79356b A |
599 | #endif /* DEBUG */ |
600 | ||
9bccf70c A |
601 | mfsprg r26,0 ; Get the per_processor block |
602 | mfmsr r19 ; Get the current MSR | |
1c79356b | 603 | |
9bccf70c A |
604 | mr r25,r4 ; Save the entry savearea |
605 | lwz r22,FPUowner(r26) ; Get the thread that owns the FPU | |
606 | lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread | |
607 | ori r19,r19,lo16(MASK(MSR_FP)) ; Enable the floating point feature | |
608 | lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running | |
1c79356b | 609 | |
9bccf70c | 610 | mtmsr r19 ; Enable floating point instructions |
1c79356b | 611 | isync |
1c79356b | 612 | |
9bccf70c A |
613 | lwz r27,ACT_MACT_PCB(r17) ; Get the current level |
614 | lwz r29,curctx(r17) ; Grab the current context anchor of the current thread | |
0b4e3aa0 | 615 | |
9bccf70c A |
616 | ; R22 has the "old" context anchor |
617 | ; R29 has the "new" context anchor | |
0b4e3aa0 | 618 | |
1c79356b | 619 | #if FPVECDBG |
9bccf70c A |
620 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
621 | li r2,0x7F01 ; (TEST/DEBUG) | |
622 | mr r3,r22 ; (TEST/DEBUG) | |
623 | mr r5,r29 ; (TEST/DEBUG) | |
624 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
625 | sc ; (TEST/DEBUG) | |
1c79356b | 626 | #endif |
9bccf70c A |
627 | |
628 | lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number | |
1c79356b | 629 | |
9bccf70c | 630 | fswretry: mr. r22,r22 ; See if there is any live FP status |
1c79356b | 631 | |
9bccf70c | 632 | beq- fsnosave ; No live context, so nothing to save... |
1c79356b | 633 | |
9bccf70c | 634 | isync ; Make sure we see this in the right order |
1c79356b | 635 | |
9bccf70c A |
636 | lwz r30,FPUsave(r22) ; Get the top savearea |
637 | cmplw cr2,r22,r29 ; Are both old and new the same context? | |
638 | lwz r18,FPUcpu(r22) ; Get the last CPU we ran on | |
639 | cmplwi cr1,r30,0 ; Anything saved yet? | |
640 | cmplw r18,r16 ; Make sure we are on the right processor | |
641 | lwz r31,FPUlevel(r22) ; Get the context level | |
1c79356b | 642 | |
9bccf70c A |
643 | bne- fsnosave ; No, not on the same processor... |
644 | ||
1c79356b | 645 | ; |
9bccf70c A |
646 | ; Check to see if the live context has already been saved. |
647 | ; Also check to see if all we are here just to re-enable the MSR | |
648 | ; and handle specially if so. | |
1c79356b | 649 | ; |
9bccf70c A |
650 | |
651 | cmplw r31,r27 ; See if the current and active levels are the same | |
652 | crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same | |
653 | li r3,0 ; Clear this | |
1c79356b | 654 | |
9bccf70c A |
655 | beq- fsthesame ; New and old are the same, just go enable... |
656 | ||
657 | beq- cr1,fsmstsave ; Not saved yet, go do it... | |
1c79356b | 658 | |
9bccf70c | 659 | lwz r11,SAVlevel(r30) ; Get the level of top saved context |
1c79356b | 660 | |
9bccf70c A |
661 | cmplw r31,r11 ; Are live and saved the same? |
662 | ||
1c79356b | 663 | #if FPVECDBG |
9bccf70c A |
664 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
665 | li r2,0x7F02 ; (TEST/DEBUG) | |
666 | mr r3,r30 ; (TEST/DEBUG) | |
667 | mr r5,r31 ; (TEST/DEBUG) | |
668 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
669 | sc ; (TEST/DEBUG) | |
1c79356b | 670 | #endif |
9bccf70c A |
671 | |
672 | beq+ fsnosave ; Same level, so already saved... | |
673 | ||
1c79356b | 674 | |
9bccf70c A |
675 | fsmstsave: stw r3,FPUowner(r26) ; Kill the context now |
676 | eieio ; Make sure everyone sees it | |
677 | bl EXT(save_get) ; Go get a savearea | |
678 | ||
de355530 A |
679 | la r11,savefp0(r3) ; Point to the 1st line in new savearea |
680 | lwz r12,facAct(r22) ; Get the activation associated with the context | |
681 | dcbz 0,r11 ; Allocate cache | |
d7e50217 | 682 | stw r3,FPUsave(r22) ; Set this as the latest context savearea for the thread |
de355530 A |
683 | |
684 | stw r30,SAVprev(r3) ; Point us to the old context | |
9bccf70c A |
685 | stw r31,SAVlevel(r3) ; Tag our level |
686 | li r7,SAVfloat ; Get the floating point ID | |
687 | stw r12,SAVact(r3) ; Make sure we point to the right guy | |
688 | stb r7,SAVflags+2(r3) ; Set that we have a floating point save area | |
1c79356b | 689 | |
1c79356b | 690 | #if FPVECDBG |
9bccf70c A |
691 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
692 | li r2,0x7F03 ; (TEST/DEBUG) | |
693 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
694 | sc ; (TEST/DEBUG) | |
1c79356b A |
695 | #endif |
696 | ||
de355530 A |
697 | ; |
698 | ; Now we will actually save the old context | |
699 | ; | |
700 | ||
701 | la r11,savefp4(r3) ; Point to the 2nd line | |
702 | stfd f0,savefp0(r3) | |
703 | dcbz 0,r11 ; Allocate cache | |
704 | stfd f1,savefp1(r3) | |
705 | stfd f2,savefp2(r3) | |
706 | la r11,savefp8(r3) ; Point to the 3rd line | |
707 | stfd f3,savefp3(r3) | |
708 | dcbz 0,r11 ; Allocate cache | |
709 | stfd f4,savefp4(r3) | |
710 | stfd f5,savefp5(r3) | |
711 | stfd f6,savefp6(r3) | |
712 | la r11,savefp12(r3) ; Point to the 4th line | |
713 | stfd f7,savefp7(r3) | |
714 | dcbz 0,r11 ; Allocate cache | |
715 | stfd f8,savefp8(r3) | |
716 | stfd f9,savefp9(r3) | |
717 | stfd f10,savefp10(r3) | |
718 | la r11,savefp16(r3) ; Point to the 5th line | |
719 | stfd f11,savefp11(r3) | |
720 | dcbz 0,r11 ; Allocate cache | |
721 | stfd f12,savefp12(r3) | |
722 | stfd f13,savefp13(r3) | |
723 | stfd f14,savefp14(r3) | |
724 | la r11,savefp20(r3) ; Point to the 6th line | |
725 | stfd f15,savefp15(r3) | |
726 | dcbz 0,r11 ; Allocate cache | |
727 | stfd f16,savefp16(r3) | |
728 | stfd f17,savefp17(r3) | |
729 | stfd f18,savefp18(r3) | |
730 | la r11,savefp24(r3) ; Point to the 7th line | |
731 | stfd f19,savefp19(r3) | |
732 | dcbz 0,r11 ; Allocate cache | |
733 | stfd f20,savefp20(r3) | |
734 | ||
735 | stfd f21,savefp21(r3) | |
736 | stfd f22,savefp22(r3) | |
737 | la r11,savefp28(r3) ; Point to the 8th line | |
738 | stfd f23,savefp23(r3) | |
739 | dcbz 0,r11 ; allocate it | |
740 | stfd f24,savefp24(r3) | |
741 | stfd f25,savefp25(r3) | |
742 | stfd f26,savefp26(r3) | |
743 | stfd f27,savefp27(r3) | |
744 | dcbz 0,r11 ; allocate it | |
745 | stfd f28,savefp28(r3) | |
746 | stfd f29,savefp29(r3) | |
747 | stfd f30,savefp30(r3) | |
748 | stfd f31,savefp31(r3) | |
1c79356b | 749 | |
1c79356b A |
750 | ; |
751 | ; The context is all saved now and the facility is free. | |
752 | ; | |
9bccf70c | 753 | ; If we do not we need to fill the registers with junk, because this level has |
1c79356b A |
754 | ; never used them before and some thieving bastard could hack the old values |
755 | ; of some thread! Just imagine what would happen if they could! Why, nothing | |
756 | ; would be safe! My God! It is terrifying! | |
757 | ; | |
758 | ||
0b4e3aa0 | 759 | |
9bccf70c A |
760 | fsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one |
761 | lwz r19,FPUcpu(r29) ; Get the last CPU we ran on | |
762 | lwz r14,FPUsave(r29) ; Point to the top of the "new" context stack | |
0b4e3aa0 | 763 | |
9bccf70c A |
764 | stw r16,FPUcpu(r29) ; Claim context for us |
765 | eieio | |
0b4e3aa0 | 766 | |
1c79356b | 767 | #if FPVECDBG |
9bccf70c A |
768 | lwz r13,FPUlevel(r29) ; (TEST/DEBUG) |
769 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
770 | li r2,0x7F04 ; (TEST/DEBUG) | |
771 | mr r1,r15 ; (TEST/DEBUG) | |
772 | mr r3,r14 ; (TEST/DEBUG) | |
773 | mr r5,r13 ; (TEST/DEBUG) | |
774 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
775 | sc ; (TEST/DEBUG) | |
1c79356b | 776 | #endif |
9bccf70c A |
777 | |
778 | lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc | |
779 | mulli r19,r19,ppSize ; Find offset to the owner per_proc | |
780 | ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc | |
781 | li r16,FPUowner ; Displacement to float owner | |
782 | add r19,r18,r19 ; Point to the owner per_proc | |
de355530 | 783 | li r0,0 |
9bccf70c A |
784 | |
785 | fsinvothr: lwarx r18,r16,r19 ; Get the owner | |
de355530 A |
786 | cmplw r18,r29 ; Does he still have this context? |
787 | bne fsinvoths ; Nope... | |
788 | stwcx. r0,r16,r19 ; Try to invalidate it | |
789 | bne- fsinvothr ; Try again if there was a collision... | |
9bccf70c | 790 | |
de355530 | 791 | fsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load? |
9bccf70c A |
792 | la r11,savefp0(r14) ; Point to first line to bring in |
793 | stw r15,FPUlevel(r29) ; Set the "new" active level | |
794 | eieio | |
795 | stw r29,FPUowner(r26) ; Mark us as having the live context | |
1c79356b | 796 | |
de355530 | 797 | beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load... |
9bccf70c A |
798 | |
799 | dcbt 0,r11 ; Touch line in | |
800 | ||
de355530 | 801 | lwz r3,SAVprev(r14) ; Get the previous context |
9bccf70c A |
802 | lwz r0,SAVlevel(r14) ; Get the level of first facility savearea |
803 | cmplw r0,r15 ; Top level correct to load? | |
de355530 | 804 | bne- MakeSureThatNoTerroristsCanHurtUsByGod ; No, go initialize... |
9bccf70c A |
805 | |
806 | stw r3,FPUsave(r29) ; Pop the context (we will toss the savearea later) | |
1c79356b A |
807 | |
808 | #if FPVECDBG | |
9bccf70c A |
809 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
810 | li r2,0x7F05 ; (TEST/DEBUG) | |
811 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
812 | sc ; (TEST/DEBUG) | |
1c79356b A |
813 | #endif |
814 | ||
9bccf70c A |
815 | la r11,savefp4(r14) ; Point to next line |
816 | dcbt 0,r11 ; Touch line in | |
1c79356b A |
817 | lfd f0, savefp0(r14) |
818 | lfd f1,savefp1(r14) | |
1c79356b | 819 | lfd f2,savefp2(r14) |
9bccf70c | 820 | la r11,savefp8(r14) ; Point to next line |
1c79356b | 821 | lfd f3,savefp3(r14) |
9bccf70c | 822 | dcbt 0,r11 ; Touch line in |
1c79356b A |
823 | lfd f4,savefp4(r14) |
824 | lfd f5,savefp5(r14) | |
825 | lfd f6,savefp6(r14) | |
9bccf70c | 826 | la r11,savefp12(r14) ; Point to next line |
1c79356b | 827 | lfd f7,savefp7(r14) |
9bccf70c | 828 | dcbt 0,r11 ; Touch line in |
1c79356b A |
829 | lfd f8,savefp8(r14) |
830 | lfd f9,savefp9(r14) | |
831 | lfd f10,savefp10(r14) | |
9bccf70c | 832 | la r11,savefp16(r14) ; Point to next line |
1c79356b | 833 | lfd f11,savefp11(r14) |
9bccf70c | 834 | dcbt 0,r11 ; Touch line in |
1c79356b A |
835 | lfd f12,savefp12(r14) |
836 | lfd f13,savefp13(r14) | |
837 | lfd f14,savefp14(r14) | |
9bccf70c | 838 | la r11,savefp20(r14) ; Point to next line |
1c79356b | 839 | lfd f15,savefp15(r14) |
9bccf70c | 840 | dcbt 0,r11 ; Touch line in |
1c79356b A |
841 | lfd f16,savefp16(r14) |
842 | lfd f17,savefp17(r14) | |
843 | lfd f18,savefp18(r14) | |
9bccf70c | 844 | la r11,savefp24(r14) ; Point to next line |
1c79356b | 845 | lfd f19,savefp19(r14) |
9bccf70c | 846 | dcbt 0,r11 ; Touch line in |
1c79356b A |
847 | lfd f20,savefp20(r14) |
848 | lfd f21,savefp21(r14) | |
9bccf70c | 849 | la r11,savefp28(r14) ; Point to next line |
1c79356b A |
850 | lfd f22,savefp22(r14) |
851 | lfd f23,savefp23(r14) | |
9bccf70c | 852 | dcbt 0,r11 ; Touch line in |
1c79356b A |
853 | lfd f24,savefp24(r14) |
854 | lfd f25,savefp25(r14) | |
855 | lfd f26,savefp26(r14) | |
856 | lfd f27,savefp27(r14) | |
857 | lfd f28,savefp28(r14) | |
858 | lfd f29,savefp29(r14) | |
859 | lfd f30,savefp30(r14) | |
860 | lfd f31,savefp31(r14) | |
861 | ||
9bccf70c A |
862 | mr r3,r14 ; Get the old savearea (we popped it before) |
863 | bl EXT(save_ret) ; Toss it | |
864 | ||
de355530 A |
865 | fsenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy |
866 | rlwinm r5,r25,0,0,19 ; Get the page address of the savearea | |
9bccf70c | 867 | ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature |
d7e50217 A |
868 | lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags |
869 | lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act | |
de355530 | 870 | lwz r5,SACvrswap(r5) ; Get Virtual to Real translation |
1c79356b | 871 | oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point |
d7e50217 | 872 | oris r11,r11,hi16(floatUsed|floatCng) ; Set that we used floating point |
9bccf70c | 873 | rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state |
de355530 A |
874 | stw r8,savesrr1(r25) ; Set the msr of the interrupted guy |
875 | xor r3,r25,r5 ; Get the real address of the savearea | |
b4c24cb9 | 876 | beq- fsnuser ; We are not user state... |
9bccf70c | 877 | stw r10,ACT_MACT_SPF(r17) ; Set the activation copy |
d7e50217 | 878 | stw r11,spcFlags(r26) ; Set per_proc copy |
1c79356b A |
879 | |
880 | fsnuser: | |
881 | #if FPVECDBG | |
9bccf70c A |
882 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
883 | li r2,0x7F07 ; (TEST/DEBUG) | |
884 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
885 | sc ; (TEST/DEBUG) | |
1c79356b | 886 | #endif |
1c79356b | 887 | |
9bccf70c | 888 | b EXT(exception_exit) ; Exit to the fray... |
1c79356b A |
889 | |
890 | /* | |
891 | * Initialize the registers to some bogus value | |
892 | */ | |
893 | ||
894 | MakeSureThatNoTerroristsCanHurtUsByGod: | |
0b4e3aa0 | 895 | |
1c79356b | 896 | #if FPVECDBG |
9bccf70c A |
897 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
898 | li r2,0x7F06 ; (TEST/DEBUG) | |
899 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
900 | sc ; (TEST/DEBUG) | |
1c79356b | 901 | #endif |
9bccf70c A |
902 | lis r5,hi16(EXT(FloatInit)) ; Get top secret floating point init value address |
903 | ori r5,r5,lo16(EXT(FloatInit)) ; Slam bottom | |
904 | lfd f0,0(r5) ; Initialize FP0 | |
905 | fmr f1,f0 ; Do them all | |
1c79356b A |
906 | fmr f2,f0 |
907 | fmr f3,f0 | |
908 | fmr f4,f0 | |
909 | fmr f5,f0 | |
910 | fmr f6,f0 | |
911 | fmr f7,f0 | |
912 | fmr f8,f0 | |
913 | fmr f9,f0 | |
914 | fmr f10,f0 | |
915 | fmr f11,f0 | |
916 | fmr f12,f0 | |
917 | fmr f13,f0 | |
918 | fmr f14,f0 | |
919 | fmr f15,f0 | |
920 | fmr f16,f0 | |
921 | fmr f17,f0 | |
1c79356b A |
922 | fmr f18,f0 |
923 | fmr f19,f0 | |
924 | fmr f20,f0 | |
1c79356b A |
925 | fmr f21,f0 |
926 | fmr f22,f0 | |
927 | fmr f23,f0 | |
928 | fmr f24,f0 | |
929 | fmr f25,f0 | |
930 | fmr f26,f0 | |
931 | fmr f27,f0 | |
932 | fmr f28,f0 | |
933 | fmr f29,f0 | |
934 | fmr f30,f0 | |
935 | fmr f31,f0 | |
9bccf70c A |
936 | b fsenable ; Finish setting it all up... |
937 | ||
1c79356b A |
938 | |
939 | ; | |
9bccf70c A |
940 | ; We get here when we are switching to the same context at the same level and the context |
941 | ; is still live. Essentially, all we are doing is turning on the faility. It may have | |
942 | ; gotten turned off due to doing a context save for the current level or a context switch | |
943 | ; back to the live guy. | |
1c79356b | 944 | ; |
9bccf70c A |
945 | |
946 | .align 5 | |
1c79356b | 947 | |
9bccf70c | 948 | fsthesame: |
1c79356b | 949 | |
9bccf70c A |
950 | #if FPVECDBG |
951 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
952 | li r2,0x7F0A ; (TEST/DEBUG) | |
953 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
954 | sc ; (TEST/DEBUG) | |
955 | #endif | |
956 | beq- cr1,fsenable ; Not saved yet, nothing to pop, go enable and exit... | |
1c79356b | 957 | |
9bccf70c | 958 | lwz r11,SAVlevel(r30) ; Get the level of top saved context |
de355530 | 959 | lwz r14,SAVprev(r30) ; Get the previous savearea |
1c79356b | 960 | |
9bccf70c | 961 | cmplw r11,r31 ; Are live and saved the same? |
1c79356b | 962 | |
9bccf70c | 963 | bne+ fsenable ; Level not the same, nothing to pop, go enable and exit... |
1c79356b | 964 | |
9bccf70c A |
965 | mr r3,r30 ; Get the old savearea (we popped it before) |
966 | bl EXT(save_ret) ; Toss it | |
967 | b fsenable ; Go enable and exit... | |
968 | ||
969 | ||
970 | ; | |
971 | ; This function invalidates any live floating point context for the passed in facility_context. | |
972 | ; This is intended to be called just before act_machine_sv_free tosses saveareas. | |
973 | ; | |
974 | ||
975 | .align 5 | |
976 | .globl EXT(toss_live_fpu) | |
977 | ||
978 | LEXT(toss_live_fpu) | |
979 | ||
de355530 | 980 | |
9bccf70c | 981 | mfmsr r9 ; Get the MSR |
de355530 | 982 | rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions |
9bccf70c | 983 | rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now? |
de355530 A |
984 | rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off |
985 | rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure floats are turned off | |
9bccf70c A |
986 | mtmsr r0 ; No interruptions |
987 | isync | |
988 | beq+ tlfnotours ; Floats off, can not be live here... | |
989 | ||
990 | mfsprg r8,0 ; Get the per proc | |
991 | ||
992 | ; | |
993 | ; Note that at this point, since floats are on, we are the owner | |
994 | ; of live state on this processor | |
1c79356b | 995 | ; |
9bccf70c A |
996 | |
997 | lwz r6,FPUowner(r8) ; Get the thread that owns the floats | |
998 | li r0,0 ; Clear this just in case we need it | |
999 | cmplw r6,r3 ; Are we tossing our own context? | |
de355530 | 1000 | bne- tlfnotours ; Nope... |
9bccf70c | 1001 | |
de355530 | 1002 | fsub f1,f1,f1 ; Make a 0 |
9bccf70c A |
1003 | mtfsf 0xFF,f1 ; Clear it |
1004 | ||
1005 | tlfnotours: lwz r11,FPUcpu(r3) ; Get the cpu on which we last loaded context | |
1006 | lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc | |
1007 | mulli r11,r11,ppSize ; Find offset to the owner per_proc | |
1008 | ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc | |
1009 | li r10,FPUowner ; Displacement to float owner | |
1010 | add r11,r12,r11 ; Point to the owner per_proc | |
de355530 | 1011 | li r0,0 ; Set a 0 to invalidate context |
9bccf70c A |
1012 | |
1013 | tlfinvothr: lwarx r12,r10,r11 ; Get the owner | |
de355530 A |
1014 | cmplw r12,r3 ; Does he still have this context? |
1015 | bne+ tlfexit ; Nope, leave... | |
1016 | stwcx. r0,r10,r11 ; Try to invalidate it | |
1017 | bne- tlfinvothr ; Try again if there was a collision... | |
9bccf70c | 1018 | |
de355530 | 1019 | tlfexit: mtmsr r9 ; Restore interruptions |
9bccf70c A |
1020 | isync ; Could be turning off floats here |
1021 | blr ; Leave... | |
1022 | ||
1c79356b A |
1023 | |
1024 | /* | |
1025 | * Altivec stuff is here. The techniques used are pretty identical to | |
1026 | * the floating point. Except that we will honor the VRSAVE register | |
1027 | * settings when loading and restoring registers. | |
1028 | * | |
1029 | * There are two indications of saved VRs: the VRSAVE register and the vrvalid | |
1030 | * mask. VRSAVE is set by the vector user and represents the VRs that they | |
1031 | * say that they are using. The vrvalid mask indicates which vector registers | |
1032 | * are saved in the savearea. Whenever context is saved, it is saved according | |
1033 | * to the VRSAVE register. It is loaded based on VRSAVE anded with | |
1034 | * vrvalid (all other registers are splatted with 0s). This is done because we | |
1035 | * don't want to load any registers we don't have a copy of, we want to set them | |
1036 | * to zero instead. | |
1037 | * | |
9bccf70c A |
1038 | * Note that there are some oddities here when we save a context we are using. |
1039 | * It is really not too cool to do this, but what the hey... Anyway, | |
1040 | * we turn vectors and fpu off before we leave. | |
1041 | * The oddity is that if you use vectors after this, the | |
1042 | * savearea containing the context just saved will go away. So, bottom line is | |
1043 | * that don't use vectors until after you are done with the saved context. | |
1044 | * | |
1c79356b A |
1045 | */ |
1046 | ||
9bccf70c A |
1047 | .align 5 |
1048 | .globl EXT(vec_save) | |
1049 | ||
1050 | LEXT(vec_save) | |
1c79356b | 1051 | |
9bccf70c | 1052 | mfmsr r0 ; Get the MSR |
de355530 A |
1053 | rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off when we leave |
1054 | rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now | |
9bccf70c | 1055 | oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also |
de355530 | 1056 | rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp |
9bccf70c | 1057 | mtmsr r2 ; Set the MSR |
1c79356b A |
1058 | isync |
1059 | ||
9bccf70c A |
1060 | mfsprg r6,0 ; Get the per_processor block |
1061 | lwz r12,VMXowner(r6) ; Get the context ID for owner | |
1062 | ||
1c79356b | 1063 | #if FPVECDBG |
9bccf70c A |
1064 | mr r7,r0 ; (TEST/DEBUG) |
1065 | li r4,0 ; (TEST/DEBUG) | |
1066 | mr r10,r3 ; (TEST/DEBUG) | |
1067 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
1068 | mr. r3,r12 ; (TEST/DEBUG) | |
1069 | li r2,0x5F00 ; (TEST/DEBUG) | |
1070 | li r5,0 ; (TEST/DEBUG) | |
1071 | beq- noowneryeu ; (TEST/DEBUG) | |
1072 | lwz r4,VMXlevel(r12) ; (TEST/DEBUG) | |
1073 | lwz r5,VMXsave(r12) ; (TEST/DEBUG) | |
1074 | ||
1075 | noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1076 | sc ; (TEST/DEBUG) | |
1077 | mr r0,r7 ; (TEST/DEBUG) | |
1078 | mr r3,r10 ; (TEST/DEBUG) | |
1c79356b | 1079 | #endif |
9bccf70c A |
1080 | mflr r2 ; Save the return address |
1081 | ||
1082 | vsretry: mr. r12,r12 ; Anyone own the vector? | |
1083 | lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number | |
1084 | beq- vsret ; Nobody owns the vector, no save required... | |
1085 | ||
1086 | cmplw cr1,r3,r12 ; Is the specified context live? | |
1087 | ||
1088 | isync ; Force owner check first | |
1089 | ||
1090 | lwz r9,VMXcpu(r12) ; Get the cpu that context was last on | |
1091 | bne- cr1,vsret ; Specified context is not live | |
1092 | ||
1093 | cmplw cr1,r9,r11 ; Was the context for this processor? | |
1094 | beq+ cr1,vsgoodcpu ; Facility last used on this processor... | |
1095 | ||
1096 | b vsret ; Someone else claimed this... | |
1097 | ||
1098 | .align 5 | |
1099 | ||
1100 | vsgoodcpu: lwz r3,VMXsave(r12) ; Get the current vector savearea for the thread | |
1101 | lwz r10,liveVRS(r6) ; Get the right VRSave register | |
1102 | lwz r9,VMXlevel(r12) ; Get our current level indicator | |
1103 | ||
1104 | ||
1105 | cmplwi cr1,r3,0 ; Have we ever saved this facility context? | |
1106 | beq- cr1,vsneedone ; Never saved it, so we need an area... | |
1107 | ||
1108 | lwz r8,SAVlevel(r3) ; Get the level this savearea is for | |
1109 | mr. r10,r10 ; Is VRsave set to 0? | |
1110 | cmplw cr1,r9,r8 ; Correct level? | |
1111 | bne- cr1,vsneedone ; Different level, so we need to save... | |
1c79356b | 1112 | |
9bccf70c | 1113 | bne+ vsret ; VRsave is non-zero so we need to keep what is saved... |
0b4e3aa0 | 1114 | |
de355530 | 1115 | lwz r4,SAVprev(r3) ; Pick up the previous area |
9bccf70c A |
1116 | lwz r5,SAVlevel(r4) ; Get the level associated with save |
1117 | stw r4,VMXsave(r12) ; Dequeue this savearea | |
1118 | stw r5,VMXlevel(r12) ; Save the level | |
1119 | ||
de355530 A |
1120 | li r3,0 ; Clear |
1121 | stw r3,VMXowner(r12) ; Show no live context here | |
9bccf70c A |
1122 | eieio |
1123 | ||
de355530 A |
1124 | vsbackout: mr r12,r0 ; Set the saved MSR |
1125 | b EXT(save_ret_join) ; Toss the savearea and return from there... | |
9bccf70c A |
1126 | |
1127 | .align 5 | |
1128 | ||
1129 | vsneedone: mr. r10,r10 ; Is VRsave set to 0? | |
1130 | beq- vsret ; Yeah, they do not care about any of them... | |
1131 | ||
1132 | bl EXT(save_get) ; Get a savearea for the context | |
1133 | ||
1134 | mfsprg r6,0 ; Get back per_processor block | |
1135 | li r4,SAVvector ; Get vector tag | |
1136 | lwz r12,VMXowner(r6) ; Get back our context ID | |
1137 | stb r4,SAVflags+2(r3) ; Mark this savearea as a vector | |
1138 | mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it... | |
1139 | beq- vsbackout ; If disowned, just toss savearea... | |
1140 | lwz r4,facAct(r12) ; Get the activation associated with live context | |
de355530 | 1141 | mtlr r2 ; Restore return |
9bccf70c A |
1142 | lwz r8,VMXsave(r12) ; Get the current top vector savearea |
1143 | stw r4,SAVact(r3) ; Indicate the right activation for this context | |
1144 | lwz r9,VMXlevel(r12) ; Get our current level indicator again | |
1145 | stw r3,VMXsave(r12) ; Set this as the most current floating point context | |
de355530 | 1146 | stw r8,SAVprev(r3) ; And then chain this in front |
9bccf70c A |
1147 | |
1148 | stw r9,SAVlevel(r3) ; Set level in savearea | |
1149 | ||
de355530 A |
1150 | mfcr r2 ; Save non-volatile CRs |
1151 | lwz r10,liveVRS(r6) ; Get the right VRSave register | |
1152 | lis r9,0x5555 ; Mask with odd bits set | |
1153 | rlwinm r11,r10,1,0,31 ; Shift over 1 | |
1154 | ori r9,r9,0x5555 ; Finish mask | |
1155 | or r4,r10,r11 ; After this, even bits show which lines to zap | |
1156 | ||
1157 | andc r11,r4,r9 ; Clear out odd bits | |
1158 | ||
1159 | la r6,savevr0(r3) ; Point to line 0 | |
1160 | rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits | |
1161 | or r4,r11,r4 ; Set the odd bits | |
1162 | ; (bit 0 is line 0, bit 1 is line 8, | |
1163 | ; bit 2 is line 1, bit 3 is line 9, etc. | |
1164 | rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31 | |
1165 | la r7,savevr2(r3) ; Point to line 1 | |
1166 | mtcrf 255,r4 ; Load up the CRs | |
1167 | stw r10,savevrvalid(r3) ; Save the validity information | |
1168 | mr r8,r6 ; Start registers off | |
1169 | ; | |
1170 | ; Save the current vector state | |
1171 | ; | |
1172 | ||
1173 | bf 0,snol0 ; No line 0 to do... | |
1174 | dcba br0,r6 ; Allocate cache line 0 | |
1175 | ||
1176 | snol0: | |
1177 | la r6,savevr4(r3) ; Point to line 2 | |
1178 | bf 2,snol1 ; No line 1 to do... | |
1179 | dcba br0,r7 ; Allocate cache line 1 | |
1180 | ||
1181 | snol1: | |
1182 | la r7,savevr6(r3) ; Point to line 3 | |
1183 | bf 4,snol2 ; No line 2 to do... | |
1184 | dcba br0,r6 ; Allocate cache line 2 | |
1185 | ||
1186 | snol2: | |
1187 | li r11,16 ; Get offset for odd registers | |
1188 | bf 16,snovr0 ; Do not save VR0... | |
1189 | stvxl v0,br0,r8 ; Save VR0 | |
1190 | ||
1191 | snovr0: | |
1192 | la r9,savevr2(r3) ; Point to V2/V3 pair | |
1193 | bf 17,snovr1 ; Do not save VR1... | |
1194 | stvxl v1,r11,r8 ; Save VR1 | |
1195 | ||
1196 | snovr1: | |
1197 | la r6,savevr8(r3) ; Point to line 4 | |
1198 | bf 6,snol3 ; No line 3 to do... | |
1199 | dcba br0,r7 ; Allocate cache line 3 | |
1200 | ||
1201 | snol3: | |
1202 | la r8,savevr4(r3) ; Point to V4/V5 pair | |
1203 | bf 18,snovr2 ; Do not save VR2... | |
1204 | stvxl v2,br0,r9 ; Save VR2 | |
1205 | ||
1206 | snovr2: | |
1207 | bf 19,snovr3 ; Do not save VR3... | |
1208 | stvxl v3,r11,r9 ; Save VR3 | |
1209 | ||
1210 | snovr3: | |
1211 | ; | |
1212 | ; Note: CR4 is now free | |
1213 | ; | |
1214 | la r7,savevr10(r3) ; Point to line 5 | |
1215 | bf 8,snol4 ; No line 4 to do... | |
1216 | dcba br0,r6 ; Allocate cache line 4 | |
1217 | ||
1218 | snol4: | |
1219 | la r9,savevr6(r3) ; Point to R6/R7 pair | |
1220 | bf 20,snovr4 ; Do not save VR4... | |
1221 | stvxl v4,br0,r8 ; Save VR4 | |
1222 | ||
1223 | snovr4: | |
1224 | bf 21,snovr5 ; Do not save VR5... | |
1225 | stvxl v5,r11,r8 ; Save VR5 | |
1226 | ||
1227 | snovr5: | |
1228 | mtcrf 0x08,r10 ; Set CRs for registers 16-19 | |
1229 | la r6,savevr12(r3) ; Point to line 6 | |
1230 | bf 10,snol5 ; No line 5 to do... | |
1231 | dcba br0,r7 ; Allocate cache line 5 | |
1232 | ||
1233 | snol5: | |
1234 | la r8,savevr8(r3) ; Point to V8/V9 pair | |
1235 | bf 22,snovr6 ; Do not save VR6... | |
1236 | stvxl v6,br0,r9 ; Save VR6 | |
1237 | ||
1238 | snovr6: | |
1239 | bf 23,snovr7 ; Do not save VR7... | |
1240 | stvxl v7,r11,r9 ; Save VR7 | |
1241 | ||
1242 | snovr7: | |
1243 | ; | |
1244 | ; Note: CR5 is now free | |
1245 | ; | |
1246 | la r7,savevr14(r3) ; Point to line 7 | |
1247 | bf 12,snol6 ; No line 6 to do... | |
1248 | dcba br0,r6 ; Allocate cache line 6 | |
1249 | ||
1250 | snol6: | |
1251 | la r9,savevr10(r3) ; Point to V10/V11 pair | |
1252 | bf 24,snovr8 ; Do not save VR8... | |
1253 | stvxl v8,br0,r8 ; Save VR8 | |
1254 | ||
1255 | snovr8: | |
1256 | bf 25,snovr9 ; Do not save VR9... | |
1257 | stvxl v9,r11,r8 ; Save VR9 | |
1258 | ||
1259 | snovr9: | |
1260 | mtcrf 0x04,r10 ; Set CRs for registers 20-23 | |
1261 | la r6,savevr16(r3) ; Point to line 8 | |
1262 | bf 14,snol7 ; No line 7 to do... | |
1263 | dcba br0,r7 ; Allocate cache line 7 | |
1264 | ||
1265 | snol7: | |
1266 | la r8,savevr12(r3) ; Point to V12/V13 pair | |
1267 | bf 26,snovr10 ; Do not save VR10... | |
1268 | stvxl v10,br0,r9 ; Save VR10 | |
1269 | ||
1270 | snovr10: | |
1271 | bf 27,snovr11 ; Do not save VR11... | |
1272 | stvxl v11,r11,r9 ; Save VR11 | |
1273 | ||
1274 | snovr11: | |
1275 | ||
1276 | ; | |
1277 | ; Note: CR6 is now free | |
1278 | ; | |
1279 | la r7,savevr18(r3) ; Point to line 9 | |
1280 | bf 1,snol8 ; No line 8 to do... | |
1281 | dcba br0,r6 ; Allocate cache line 8 | |
1282 | ||
1283 | snol8: | |
1284 | la r9,savevr14(r3) ; Point to V14/V15 pair | |
1285 | bf 28,snovr12 ; Do not save VR12... | |
1286 | stvxl v12,br0,r8 ; Save VR12 | |
1287 | ||
1288 | snovr12: | |
1289 | bf 29,snovr13 ; Do not save VR13... | |
1290 | stvxl v13,r11,r8 ; Save VR13 | |
1291 | ||
1292 | snovr13: | |
1293 | mtcrf 0x02,r10 ; Set CRs for registers 24-27 | |
1294 | la r6,savevr20(r3) ; Point to line 10 | |
1295 | bf 3,snol9 ; No line 9 to do... | |
1296 | dcba br0,r7 ; Allocate cache line 9 | |
1297 | ||
1298 | snol9: | |
1299 | la r8,savevr16(r3) ; Point to V16/V17 pair | |
1300 | bf 30,snovr14 ; Do not save VR14... | |
1301 | stvxl v14,br0,r9 ; Save VR14 | |
1302 | ||
1303 | snovr14: | |
1304 | bf 31,snovr15 ; Do not save VR15... | |
1305 | stvxl v15,r11,r9 ; Save VR15 | |
1306 | ||
1307 | snovr15: | |
1308 | ; | |
1309 | ; Note: CR7 is now free | |
1310 | ; | |
1311 | la r7,savevr22(r3) ; Point to line 11 | |
1312 | bf 5,snol10 ; No line 10 to do... | |
1313 | dcba br0,r6 ; Allocate cache line 10 | |
1314 | ||
1315 | snol10: | |
1316 | la r9,savevr18(r3) ; Point to V18/V19 pair | |
1317 | bf 16,snovr16 ; Do not save VR16... | |
1318 | stvxl v16,br0,r8 ; Save VR16 | |
1319 | ||
1320 | snovr16: | |
1321 | bf 17,snovr17 ; Do not save VR17... | |
1322 | stvxl v17,r11,r8 ; Save VR17 | |
1323 | ||
1324 | snovr17: | |
1325 | mtcrf 0x01,r10 ; Set CRs for registers 28-31 | |
1326 | ; | |
1327 | ; Note: All registers have been or are accounted for in CRs | |
1328 | ; | |
1329 | la r6,savevr24(r3) ; Point to line 12 | |
1330 | bf 7,snol11 ; No line 11 to do... | |
1331 | dcba br0,r7 ; Allocate cache line 11 | |
1332 | ||
1333 | snol11: | |
1334 | la r8,savevr20(r3) ; Point to V20/V21 pair | |
1335 | bf 18,snovr18 ; Do not save VR18... | |
1336 | stvxl v18,br0,r9 ; Save VR18 | |
1337 | ||
1338 | snovr18: | |
1339 | bf 19,snovr19 ; Do not save VR19... | |
1340 | stvxl v19,r11,r9 ; Save VR19 | |
1341 | ||
1342 | snovr19: | |
1343 | la r7,savevr26(r3) ; Point to line 13 | |
1344 | bf 9,snol12 ; No line 12 to do... | |
1345 | dcba br0,r6 ; Allocate cache line 12 | |
1346 | ||
1347 | snol12: | |
1348 | la r9,savevr22(r3) ; Point to V22/V23 pair | |
1349 | bf 20,snovr20 ; Do not save VR20... | |
1350 | stvxl v20,br0,r8 ; Save VR20 | |
1351 | ||
1352 | snovr20: | |
1353 | bf 21,snovr21 ; Do not save VR21... | |
1354 | stvxl v21,r11,r8 ; Save VR21 | |
1355 | ||
1356 | snovr21: | |
1357 | la r6,savevr28(r3) ; Point to line 14 | |
1358 | bf 11,snol13 ; No line 13 to do... | |
1359 | dcba br0,r7 ; Allocate cache line 13 | |
1360 | ||
1361 | snol13: | |
1362 | la r8,savevr24(r3) ; Point to V24/V25 pair | |
1363 | bf 22,snovr22 ; Do not save VR22... | |
1364 | stvxl v22,br0,r9 ; Save VR22 | |
1365 | ||
1366 | snovr22: | |
1367 | bf 23,snovr23 ; Do not save VR23... | |
1368 | stvxl v23,r11,r9 ; Save VR23 | |
1369 | ||
1370 | snovr23: | |
1371 | la r7,savevr30(r3) ; Point to line 15 | |
1372 | bf 13,snol14 ; No line 14 to do... | |
1373 | dcba br0,r6 ; Allocate cache line 14 | |
1374 | ||
1375 | snol14: | |
1376 | la r9,savevr26(r3) ; Point to V26/V27 pair | |
1377 | bf 24,snovr24 ; Do not save VR24... | |
1378 | stvxl v24,br0,r8 ; Save VR24 | |
1379 | ||
1380 | snovr24: | |
1381 | bf 25,snovr25 ; Do not save VR25... | |
1382 | stvxl v25,r11,r8 ; Save VR25 | |
1383 | ||
1384 | snovr25: | |
1385 | bf 15,snol15 ; No line 15 to do... | |
1386 | dcba br0,r7 ; Allocate cache line 15 | |
1387 | ||
1388 | snol15: | |
1389 | ; | |
1390 | ; Note: All cache lines allocated now | |
1391 | ; | |
1392 | la r8,savevr28(r3) ; Point to V28/V29 pair | |
1393 | bf 26,snovr26 ; Do not save VR26... | |
1394 | stvxl v26,br0,r9 ; Save VR26 | |
1395 | ||
1396 | snovr26: | |
1397 | bf 27,snovr27 ; Do not save VR27... | |
1398 | stvxl v27,r11,r9 ; Save VR27 | |
1399 | ||
1400 | snovr27: | |
1401 | la r7,savevr30(r3) ; Point to V30/V31 pair | |
1402 | bf 28,snovr28 ; Do not save VR28... | |
1403 | stvxl v28,br0,r8 ; Save VR28 | |
1404 | ||
1405 | snovr28: | |
1406 | bf 29,snovr29 ; Do not save VR29... | |
1407 | stvxl v29,r11,r8 ; Save VR29 | |
1408 | ||
1409 | snovr29: | |
1410 | bf 30,snovr30 ; Do not save VR30... | |
1411 | stvxl v30,br0,r7 ; Save VR30 | |
1412 | ||
1413 | snovr30: | |
1414 | bf 31,snovr31 ; Do not save VR31... | |
1415 | stvxl v31,r11,r7 ; Save VR31 | |
1416 | ||
1417 | snovr31: | |
1418 | mtcrf 255,r2 ; Restore all cr | |
1419 | ||
1420 | vsret: mtmsr r0 ; Put interrupts on if they were and vector off | |
1c79356b A |
1421 | isync |
1422 | ||
1423 | blr | |
1424 | ||
1425 | /* | |
1426 | * vec_switch() | |
1427 | * | |
1428 | * Entered to handle the vector unavailable exception and | |
1429 | * switch vector context | |
1430 | * | |
1431 | * This code is run with virtual address mode on and interrupts off. | |
1432 | * | |
1433 | * Upon exit, the code returns to the users context with the vector | |
1434 | * facility turned on. | |
1435 | * | |
1436 | * ENTRY: VM switched ON | |
1437 | * Interrupts OFF | |
1438 | * State is saved in savearea pointed to by R4. | |
1439 | * All other registers are free. | |
1440 | * | |
1441 | */ | |
1442 | ||
9bccf70c A |
1443 | .align 5 |
1444 | .globl EXT(vec_switch) | |
1445 | ||
1446 | LEXT(vec_switch) | |
1c79356b A |
1447 | |
1448 | #if DEBUG | |
1c79356b A |
1449 | lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter |
1450 | ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter | |
1451 | lwz r1,0(r3) | |
1452 | addi r1,r1,1 | |
1453 | stw r1,0(r3) | |
1c79356b A |
1454 | #endif /* DEBUG */ |
1455 | ||
9bccf70c A |
1456 | mfsprg r26,0 ; Get the per_processor block |
1457 | mfmsr r19 ; Get the current MSR | |
1c79356b | 1458 | |
9bccf70c A |
1459 | mr r25,r4 ; Save the entry savearea |
1460 | lwz r22,VMXowner(r26) ; Get the thread that owns the vector | |
1461 | lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread | |
1462 | oris r19,r19,hi16(MASK(MSR_VEC)) ; Enable the vector feature | |
1463 | lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running | |
1464 | ||
1465 | mtmsr r19 ; Enable vector instructions | |
1c79356b A |
1466 | isync |
1467 | ||
9bccf70c A |
1468 | lwz r27,ACT_MACT_PCB(r17) ; Get the current level |
1469 | lwz r29,curctx(r17) ; Grab the current context anchor of the current thread | |
0b4e3aa0 | 1470 | |
9bccf70c A |
1471 | ; R22 has the "old" context anchor |
1472 | ; R29 has the "new" context anchor | |
0b4e3aa0 | 1473 | |
1c79356b | 1474 | #if FPVECDBG |
9bccf70c A |
1475 | lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) |
1476 | li r2,0x5F01 ; (TEST/DEBUG) | |
1477 | mr r3,r22 ; (TEST/DEBUG) | |
1478 | mr r5,r29 ; (TEST/DEBUG) | |
1479 | oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) | |
1480 | sc ; (TEST/DEBUG) | |
1c79356b A |
1481 | #endif |
1482 | ||
9bccf70c | 1483 | lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number |
1c79356b | 1484 | |
9bccf70c | 1485 | vsvretry: mr. r22,r22 ; See if there is any live vector status |
1c79356b | 1486 | |
9bccf70c | 1487 | beq- vsnosave ; No live context, so nothing to save... |
1c79356b | 1488 | |
9bccf70c | 1489 | isync ; Make sure we see this in the right order |
1c79356b | 1490 | |
9bccf70c A |
1491 | lwz r30,VMXsave(r22) ; Get the top savearea |
1492 | cmplw cr2,r22,r29 ; Are both old and new the same context? | |
1493 | lwz r18,VMXcpu(r22) ; Get the last CPU we ran on | |
1494 | cmplwi cr1,r30,0 ; Anything saved yet? | |
1495 | cmplw r18,r16 ; Make sure we are on the right processor | |
1496 | lwz r31,VMXlevel(r22) ; Get the context level | |
1c79356b | 1497 | |
9bccf70c A |
1498 | lwz r10,liveVRS(r26) ; Get the right VRSave register |
1499 | ||
1500 | bne- vsnosave ; No, not on the same processor... | |
1501 | ||
1c79356b | 1502 | ; |
9bccf70c A |
1503 | ; Check to see if the live context has already been saved. |
1504 | ; Also check to see if all we are here just to re-enable the MSR | |
1505 | ; and handle specially if so. | |
1c79356b | 1506 | ; |
9bccf70c A |
1507 | |
1508 | cmplw r31,r27 ; See if the current and active levels are the same | |
1509 | crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same | |
1510 | li r8,0 ; Clear this | |
1c79356b | 1511 | |
9bccf70c A |
1512 | beq- vsthesame ; New and old are the same, just go enable... |
1513 | ||
1514 | cmplwi cr2,r10,0 ; Check VRSave to see if we really need to save anything... | |
1515 | beq- cr1,vsmstsave ; Not saved yet, go do it... | |
1c79356b | 1516 | |
9bccf70c | 1517 | lwz r11,SAVlevel(r30) ; Get the level of top saved context |
1c79356b | 1518 | |
9bccf70c A |
1519 | cmplw r31,r11 ; Are live and saved the same? |
1520 | ||
1c79356b | 1521 | #if FPVECDBG |
9bccf70c A |
1522 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
1523 | li r2,0x5F02 ; (TEST/DEBUG) | |
1524 | mr r3,r30 ; (TEST/DEBUG) | |
1525 | mr r5,r31 ; (TEST/DEBUG) | |
1526 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1527 | sc ; (TEST/DEBUG) | |
1c79356b | 1528 | #endif |
9bccf70c A |
1529 | |
1530 | bne- vsmstsave ; Live context has not been saved yet... | |
1531 | ||
1532 | bne- cr2,vsnosave ; Live context saved and VRSave not 0, no save and keep context... | |
1c79356b | 1533 | |
de355530 | 1534 | lwz r4,SAVprev(r30) ; Pick up the previous area |
9bccf70c A |
1535 | li r5,0 ; Assume this is the only one (which should be the ususal case) |
1536 | mr. r4,r4 ; Was this the only one? | |
1537 | stw r4,VMXsave(r22) ; Dequeue this savearea | |
1538 | beq+ vsonlyone ; This was the only one... | |
1539 | lwz r5,SAVlevel(r4) ; Get the level associated with previous save | |
1540 | ||
1541 | vsonlyone: stw r5,VMXlevel(r22) ; Save the level | |
1542 | stw r8,VMXowner(r26) ; Clear owner | |
1543 | eieio | |
1544 | mr r3,r30 ; Copy the savearea we are tossing | |
1545 | bl EXT(save_ret) ; Toss the savearea | |
1546 | b vsnosave ; Go load up the context... | |
1547 | ||
1548 | .align 5 | |
1c79356b | 1549 | |
9bccf70c A |
1550 | |
1551 | vsmstsave: stw r8,VMXowner(r26) ; Clear owner | |
1552 | eieio | |
1553 | beq- cr2,vsnosave ; The VRSave was 0, so there is nothing to save... | |
1554 | ||
1555 | bl EXT(save_get) ; Go get a savearea | |
1556 | ||
de355530 | 1557 | lwz r12,facAct(r22) ; Get the activation associated with the context |
d7e50217 | 1558 | stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread |
de355530 A |
1559 | |
1560 | stw r30,SAVprev(r3) ; Point us to the old context | |
9bccf70c A |
1561 | stw r31,SAVlevel(r3) ; Tag our level |
1562 | li r7,SAVvector ; Get the vector ID | |
1563 | stw r12,SAVact(r3) ; Make sure we point to the right guy | |
1564 | stb r7,SAVflags+2(r3) ; Set that we have a vector save area | |
1c79356b | 1565 | |
1c79356b | 1566 | #if FPVECDBG |
9bccf70c A |
1567 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
1568 | li r2,0x5F03 ; (TEST/DEBUG) | |
1569 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1570 | sc ; (TEST/DEBUG) | |
1c79356b A |
1571 | #endif |
1572 | ||
9bccf70c | 1573 | lwz r10,liveVRS(r26) ; Get the right VRSave register |
de355530 A |
1574 | lis r9,0x5555 ; Mask with odd bits set |
1575 | rlwinm r11,r10,1,0,31 ; Shift over 1 | |
1576 | ori r9,r9,0x5555 ; Finish mask | |
1577 | or r21,r10,r11 ; After this, even bits show which lines to zap | |
1578 | ||
1579 | andc r13,r21,r9 ; Clear out odd bits | |
1580 | ||
1581 | la r11,savevr0(r3) ; Point to line 0 | |
1582 | rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits | |
1583 | or r24,r13,r24 ; Set the odd bits | |
1584 | ; (bit 0 is line 0, bit 1 is line 8, | |
1585 | ; bit 2 is line 1, bit 3 is line 9, etc. | |
1586 | rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31 | |
1587 | la r21,savevr2(r3) ; Point to line 1 | |
1588 | mtcrf 255,r24 ; Load up the CRs | |
1589 | stw r10,savevrvalid(r3) ; Save the validity information | |
1590 | mr r12,r11 ; Start registers off | |
1591 | ; | |
1592 | ; Save the current vector state | |
1593 | ; | |
1594 | ||
1595 | bf 0,nol0 ; No line 0 to do... | |
1596 | dcba br0,r11 ; Allocate cache line 0 | |
1597 | ||
1598 | nol0: | |
1599 | la r11,savevr4(r3) ; Point to line 2 | |
1600 | bf 2,nol1 ; No line 1 to do... | |
1601 | dcba br0,r21 ; Allocate cache line 1 | |
1602 | ||
1603 | nol1: | |
1604 | la r21,savevr6(r3) ; Point to line 3 | |
1605 | bf 4,nol2 ; No line 2 to do... | |
1606 | dcba br0,r11 ; Allocate cache line 2 | |
1607 | ||
1608 | nol2: | |
1609 | li r14,16 ; Get offset for odd registers | |
1610 | bf 16,novr0 ; Do not save VR0... | |
1611 | stvxl v0,br0,r12 ; Save VR0 | |
1612 | ||
1613 | novr0: | |
1614 | la r13,savevr2(r3) ; Point to V2/V3 pair | |
1615 | bf 17,novr1 ; Do not save VR1... | |
1616 | stvxl v1,r14,r12 ; Save VR1 | |
1617 | ||
1618 | novr1: | |
1619 | la r11,savevr8(r3) ; Point to line 4 | |
1620 | bf 6,nol3 ; No line 3 to do... | |
1621 | dcba br0,r21 ; Allocate cache line 3 | |
1622 | ||
1623 | nol3: | |
1624 | la r12,savevr4(r3) ; Point to V4/V5 pair | |
1625 | bf 18,novr2 ; Do not save VR2... | |
1626 | stvxl v2,br0,r13 ; Save VR2 | |
1627 | ||
1628 | novr2: | |
1629 | bf 19,novr3 ; Do not save VR3... | |
1630 | stvxl v3,r14,r13 ; Save VR3 | |
1631 | ||
1632 | novr3: | |
1633 | ; | |
1634 | ; Note: CR4 is now free | |
1635 | ; | |
1636 | la r21,savevr10(r3) ; Point to line 5 | |
1637 | bf 8,nol4 ; No line 4 to do... | |
1638 | dcba br0,r11 ; Allocate cache line 4 | |
1639 | ||
1640 | nol4: | |
1641 | la r13,savevr6(r3) ; Point to R6/R7 pair | |
1642 | bf 20,novr4 ; Do not save VR4... | |
1643 | stvxl v4,br0,r12 ; Save VR4 | |
1644 | ||
1645 | novr4: | |
1646 | bf 21,novr5 ; Do not save VR5... | |
1647 | stvxl v5,r14,r12 ; Save VR5 | |
1648 | ||
1649 | novr5: | |
1650 | mtcrf 0x08,r10 ; Set CRs for registers 16-19 | |
1651 | la r11,savevr12(r3) ; Point to line 6 | |
1652 | bf 10,nol5 ; No line 5 to do... | |
1653 | dcba br0,r21 ; Allocate cache line 5 | |
1654 | ||
1655 | nol5: | |
1656 | la r12,savevr8(r3) ; Point to V8/V9 pair | |
1657 | bf 22,novr6 ; Do not save VR6... | |
1658 | stvxl v6,br0,r13 ; Save VR6 | |
1659 | ||
1660 | novr6: | |
1661 | bf 23,novr7 ; Do not save VR7... | |
1662 | stvxl v7,r14,r13 ; Save VR7 | |
1663 | ||
1664 | novr7: | |
1665 | ; | |
1666 | ; Note: CR5 is now free | |
1667 | ; | |
1668 | la r21,savevr14(r3) ; Point to line 7 | |
1669 | bf 12,nol6 ; No line 6 to do... | |
1670 | dcba br0,r11 ; Allocate cache line 6 | |
1671 | ||
1672 | nol6: | |
1673 | la r13,savevr10(r3) ; Point to V10/V11 pair | |
1674 | bf 24,novr8 ; Do not save VR8... | |
1675 | stvxl v8,br0,r12 ; Save VR8 | |
1676 | ||
1677 | novr8: | |
1678 | bf 25,novr9 ; Do not save VR9... | |
1679 | stvxl v9,r14,r12 ; Save VR9 | |
1680 | ||
1681 | novr9: | |
1682 | mtcrf 0x04,r10 ; Set CRs for registers 20-23 | |
1683 | la r11,savevr16(r3) ; Point to line 8 | |
1684 | bf 14,nol7 ; No line 7 to do... | |
1685 | dcba br0,r21 ; Allocate cache line 7 | |
1686 | ||
1687 | nol7: | |
1688 | la r12,savevr12(r3) ; Point to V12/V13 pair | |
1689 | bf 26,novr10 ; Do not save VR10... | |
1690 | stvxl v10,br0,r13 ; Save VR10 | |
1691 | ||
1692 | novr10: | |
1693 | bf 27,novr11 ; Do not save VR11... | |
1694 | stvxl v11,r14,r13 ; Save VR11 | |
1695 | ||
1696 | novr11: | |
1697 | ||
1698 | ; | |
1699 | ; Note: CR6 is now free | |
1700 | ; | |
1701 | la r21,savevr18(r3) ; Point to line 9 | |
1702 | bf 1,nol8 ; No line 8 to do... | |
1703 | dcba br0,r11 ; Allocate cache line 8 | |
1704 | ||
1705 | nol8: | |
1706 | la r13,savevr14(r3) ; Point to V14/V15 pair | |
1707 | bf 28,novr12 ; Do not save VR12... | |
1708 | stvxl v12,br0,r12 ; Save VR12 | |
1709 | ||
1710 | novr12: | |
1711 | bf 29,novr13 ; Do not save VR13... | |
1712 | stvxl v13,r14,r12 ; Save VR13 | |
1713 | ||
1714 | novr13: | |
1715 | mtcrf 0x02,r10 ; Set CRs for registers 24-27 | |
1716 | la r11,savevr20(r3) ; Point to line 10 | |
1717 | bf 3,nol9 ; No line 9 to do... | |
1718 | dcba br0,r21 ; Allocate cache line 9 | |
1719 | ||
1720 | nol9: | |
1721 | la r12,savevr16(r3) ; Point to V16/V17 pair | |
1722 | bf 30,novr14 ; Do not save VR14... | |
1723 | stvxl v14,br0,r13 ; Save VR14 | |
1724 | ||
1725 | novr14: | |
1726 | bf 31,novr15 ; Do not save VR15... | |
1727 | stvxl v15,r14,r13 ; Save VR15 | |
1728 | ||
1729 | novr15: | |
1730 | ; | |
1731 | ; Note: CR7 is now free | |
1732 | ; | |
1733 | la r21,savevr22(r3) ; Point to line 11 | |
1734 | bf 5,nol10 ; No line 10 to do... | |
1735 | dcba br0,r11 ; Allocate cache line 10 | |
1736 | ||
1737 | nol10: | |
1738 | la r13,savevr18(r3) ; Point to V18/V19 pair | |
1739 | bf 16,novr16 ; Do not save VR16... | |
1740 | stvxl v16,br0,r12 ; Save VR16 | |
1741 | ||
1742 | novr16: | |
1743 | bf 17,novr17 ; Do not save VR17... | |
1744 | stvxl v17,r14,r12 ; Save VR17 | |
1745 | ||
1746 | novr17: | |
1747 | mtcrf 0x01,r10 ; Set CRs for registers 28-31 | |
1748 | ; | |
1749 | ; Note: All registers have been or are accounted for in CRs | |
1750 | ; | |
1751 | la r11,savevr24(r3) ; Point to line 12 | |
1752 | bf 7,nol11 ; No line 11 to do... | |
1753 | dcba br0,r21 ; Allocate cache line 11 | |
1754 | ||
1755 | nol11: | |
1756 | la r12,savevr20(r3) ; Point to V20/V21 pair | |
1757 | bf 18,novr18 ; Do not save VR18... | |
1758 | stvxl v18,br0,r13 ; Save VR18 | |
1759 | ||
1760 | novr18: | |
1761 | bf 19,novr19 ; Do not save VR19... | |
1762 | stvxl v19,r14,r13 ; Save VR19 | |
1763 | ||
1764 | novr19: | |
1765 | la r21,savevr26(r3) ; Point to line 13 | |
1766 | bf 9,nol12 ; No line 12 to do... | |
1767 | dcba br0,r11 ; Allocate cache line 12 | |
1768 | ||
1769 | nol12: | |
1770 | la r13,savevr22(r3) ; Point to V22/V23 pair | |
1771 | bf 20,novr20 ; Do not save VR20... | |
1772 | stvxl v20,br0,r12 ; Save VR20 | |
1773 | ||
1774 | novr20: | |
1775 | bf 21,novr21 ; Do not save VR21... | |
1776 | stvxl v21,r14,r12 ; Save VR21 | |
1777 | ||
1778 | novr21: | |
1779 | la r11,savevr28(r3) ; Point to line 14 | |
1780 | bf 11,nol13 ; No line 13 to do... | |
1781 | dcba br0,r21 ; Allocate cache line 13 | |
1782 | ||
1783 | nol13: | |
1784 | la r12,savevr24(r3) ; Point to V24/V25 pair | |
1785 | bf 22,novr22 ; Do not save VR22... | |
1786 | stvxl v22,br0,r13 ; Save VR22 | |
1787 | ||
1788 | novr22: | |
1789 | bf 23,novr23 ; Do not save VR23... | |
1790 | stvxl v23,r14,r13 ; Save VR23 | |
1791 | ||
1792 | novr23: | |
1793 | la r21,savevr30(r3) ; Point to line 15 | |
1794 | bf 13,nol14 ; No line 14 to do... | |
1795 | dcba br0,r11 ; Allocate cache line 14 | |
1796 | ||
1797 | nol14: | |
1798 | la r13,savevr26(r3) ; Point to V26/V27 pair | |
1799 | bf 24,novr24 ; Do not save VR24... | |
1800 | stvxl v24,br0,r12 ; Save VR24 | |
1801 | ||
1802 | novr24: | |
1803 | bf 25,novr25 ; Do not save VR25... | |
1804 | stvxl v25,r14,r12 ; Save VR25 | |
1805 | ||
1806 | novr25: | |
1807 | bf 15,nol15 ; No line 15 to do... | |
1808 | dcba br0,r21 ; Allocate cache line 15 | |
1809 | ||
1810 | nol15: | |
1811 | ; | |
1812 | ; Note: All cache lines allocated now | |
1813 | ; | |
1814 | la r12,savevr28(r3) ; Point to V28/V29 pair | |
1815 | bf 26,novr26 ; Do not save VR26... | |
1816 | stvxl v26,br0,r13 ; Save VR26 | |
1817 | ||
1818 | novr26: | |
1819 | bf 27,novr27 ; Do not save VR27... | |
1820 | stvxl v27,r14,r13 ; Save VR27 | |
1821 | ||
1822 | novr27: | |
1823 | la r13,savevr30(r3) ; Point to V30/V31 pair | |
1824 | bf 28,novr28 ; Do not save VR28... | |
1825 | stvxl v28,br0,r12 ; Save VR28 | |
1826 | ||
1827 | novr28: | |
1828 | bf 29,novr29 ; Do not save VR29... | |
1829 | stvxl v29,r14,r12 ; Save VR29 | |
1830 | ||
1831 | novr29: | |
1832 | bf 30,novr30 ; Do not save VR30... | |
1833 | stvxl v30,br0,r13 ; Save VR30 | |
1834 | ||
1835 | novr30: | |
1836 | bf 31,novr31 ; Do not save VR31... | |
1837 | stvxl v31,r14,r13 ; Save VR31 | |
1838 | ||
1839 | novr31: | |
1840 | ||
1c79356b A |
1841 | |
1842 | ||
9bccf70c A |
1843 | ; |
1844 | ; The context is all saved now and the facility is free. | |
1845 | ; | |
1846 | ; If we do not we need to fill the registers with junk, because this level has | |
1847 | ; never used them before and some thieving bastard could hack the old values | |
1848 | ; of some thread! Just imagine what would happen if they could! Why, nothing | |
1849 | ; would be safe! My God! It is terrifying! | |
1850 | ; | |
1851 | ; Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian) | |
1852 | ; constant that we may need to fill unused vector registers. | |
1853 | ; | |
1c79356b | 1854 | |
0b4e3aa0 A |
1855 | |
1856 | ||
0b4e3aa0 | 1857 | |
9bccf70c A |
1858 | vsnosave: vspltisb v31,-10 ; Get 0xF6F6F6F6 |
1859 | lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one | |
1860 | vspltisb v30,5 ; Get 0x05050505 | |
1861 | lwz r19,VMXcpu(r29) ; Get the last CPU we ran on | |
1862 | vspltish v29,4 ; Get 0x00040004 | |
1863 | lwz r14,VMXsave(r29) ; Point to the top of the "new" context stack | |
1864 | vrlb v31,v31,v30 ; Get 0xDEDEDEDE | |
1865 | ||
1866 | stw r16,VMXcpu(r29) ; Claim context for us | |
1867 | eieio | |
1c79356b A |
1868 | |
1869 | #if FPVECDBG | |
9bccf70c A |
1870 | lwz r13,VMXlevel(r29) ; (TEST/DEBUG) |
1871 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
1872 | li r2,0x5F04 ; (TEST/DEBUG) | |
1873 | mr r1,r15 ; (TEST/DEBUG) | |
1874 | mr r3,r14 ; (TEST/DEBUG) | |
1875 | mr r5,r13 ; (TEST/DEBUG) | |
1876 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1877 | sc ; (TEST/DEBUG) | |
1c79356b | 1878 | #endif |
9bccf70c A |
1879 | |
1880 | lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc | |
1881 | vspltisb v28,-2 ; Get 0xFEFEFEFE | |
1882 | mulli r19,r19,ppSize ; Find offset to the owner per_proc | |
1883 | vsubuhm v31,v31,v29 ; Get 0xDEDADEDA | |
1884 | ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc | |
1885 | vpkpx v30,v28,v3 ; Get 0x7FFF7FFF | |
1886 | li r16,VMXowner ; Displacement to vector owner | |
1887 | add r19,r18,r19 ; Point to the owner per_proc | |
1888 | vrlb v31,v31,v29 ; Get 0xDEADDEAD | |
de355530 | 1889 | li r0,0 |
9bccf70c A |
1890 | |
1891 | vsinvothr: lwarx r18,r16,r19 ; Get the owner | |
de355530 A |
1892 | cmplw r18,r29 ; Does he still have this context? |
1893 | bne vsinvoths ; Nope... | |
1894 | stwcx. r0,r16,r19 ; Try to invalidate it | |
1895 | bne- vsinvothr ; Try again if there was a collision... | |
1896 | ||
9bccf70c | 1897 | |
de355530 | 1898 | vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load? |
9bccf70c A |
1899 | vmrghh v31,v30,v31 ; Get 0x7FFFDEAD. V31 keeps this value until the bitter end |
1900 | stw r15,VMXlevel(r29) ; Set the "new" active level | |
1901 | eieio | |
1902 | stw r29,VMXowner(r26) ; Mark us as having the live context | |
1c79356b | 1903 | |
de355530 | 1904 | beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use... |
9bccf70c | 1905 | |
de355530 | 1906 | lwz r3,SAVprev(r14) ; Get the previous context |
9bccf70c A |
1907 | lwz r0,SAVlevel(r14) ; Get the level of first facility savearea |
1908 | cmplw r0,r15 ; Top level correct to load? | |
de355530 | 1909 | bne- ProtectTheAmericanWay ; No, go initialize... |
1c79356b | 1910 | |
9bccf70c A |
1911 | stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later) |
1912 | ||
1c79356b | 1913 | #if FPVECDBG |
9bccf70c A |
1914 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
1915 | li r2,0x5F05 ; (TEST/DEBUG) | |
1916 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1917 | sc ; (TEST/DEBUG) | |
1c79356b A |
1918 | #endif |
1919 | ||
d7e50217 | 1920 | lwz r22,savevrsave(r25) ; Get the most current VRSAVE |
de355530 A |
1921 | lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea |
1922 | lis r9,0x5555 ; Mask with odd bits set | |
9bccf70c | 1923 | and r10,r10,r22 ; Figure out just what registers need to be loaded |
de355530 A |
1924 | ori r9,r9,0x5555 ; Finish mask |
1925 | rlwinm r11,r10,1,0,31 ; Shift over 1 | |
1926 | or r12,r10,r11 ; After this, even bits show which lines to touch | |
1927 | andc r13,r12,r9 ; Clear out odd bits | |
1928 | ||
1929 | la r20,savevr0(r14) ; Point to line 0 | |
1930 | rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits | |
1931 | la r21,savevr2(r3) ; Point to line 1 | |
1932 | or r3,r13,r3 ; Set the odd bits | |
1933 | ; (bit 0 is line 0, bit 1 is line 8, | |
1934 | ; bit 2 is line 1, bit 3 is line 9, etc. | |
1935 | rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31 | |
1936 | mtcrf 255,r3 ; Load up the CRs | |
1937 | mr r22,r20 ; Start registers off | |
1938 | ; | |
1939 | ; Load the new vector state | |
1940 | ; | |
1941 | ||
1942 | bf 0,lnol0 ; No line 0 to do... | |
1943 | dcbt br0,r20 ; Touch cache line 0 | |
1944 | ||
1945 | lnol0: | |
1946 | la r20,savevr4(r14) ; Point to line 2 | |
1947 | bf 2,lnol1 ; No line 1 to do... | |
1948 | dcbt br0,r21 ; Touch cache line 1 | |
1949 | ||
1950 | lnol1: | |
1951 | la r21,savevr6(r14) ; Point to line 3 | |
1952 | bf 4,lnol2 ; No line 2 to do... | |
1953 | dcbt br0,r20 ; Touch cache line 2 | |
1954 | ||
1955 | lnol2: | |
1956 | li r30,16 ; Get offset for odd registers | |
1957 | bf 16,lnovr0 ; Do not restore VR0... | |
1958 | lvxl v0,br0,r22 ; Restore VR0 | |
1959 | ||
1960 | lnovr0: | |
1961 | la r23,savevr2(r14) ; Point to V2/V3 pair | |
1962 | bf 17,lnovr1 ; Do not restore VR1... | |
1963 | lvxl v1,r30,r22 ; Restore VR1 | |
1964 | ||
1965 | lnovr1: | |
1966 | la r20,savevr8(r14) ; Point to line 4 | |
1967 | bf 6,lnol3 ; No line 3 to do... | |
1968 | dcbt br0,r21 ; Touch cache line 3 | |
1969 | ||
1970 | lnol3: | |
1971 | la r22,savevr4(r14) ; Point to V4/V5 pair | |
1972 | bf 18,lnovr2 ; Do not restore VR2... | |
1973 | lvxl v2,br0,r23 ; Restore VR2 | |
1974 | ||
1975 | lnovr2: | |
1976 | bf 19,lnovr3 ; Do not restore VR3... | |
1977 | lvxl v3,r30,r23 ; Restore VR3 | |
1978 | ||
1979 | lnovr3: | |
1980 | ; | |
1981 | ; Note: CR4 is now free | |
1982 | ; | |
1983 | la r21,savevr10(r14) ; Point to line 5 | |
1984 | bf 8,lnol4 ; No line 4 to do... | |
1985 | dcbt br0,r20 ; Touch cache line 4 | |
1986 | ||
1987 | lnol4: | |
1988 | la r23,savevr6(r14) ; Point to R6/R7 pair | |
1989 | bf 20,lnovr4 ; Do not restore VR4... | |
1990 | lvxl v4,br0,r22 ; Restore VR4 | |
1991 | ||
1992 | lnovr4: | |
1993 | bf 21,lnovr5 ; Do not restore VR5... | |
1994 | lvxl v5,r30,r22 ; Restore VR5 | |
1995 | ||
1996 | lnovr5: | |
1997 | mtcrf 0x08,r10 ; Set CRs for registers 16-19 | |
1998 | la r20,savevr12(r14) ; Point to line 6 | |
1999 | bf 10,lnol5 ; No line 5 to do... | |
2000 | dcbt br0,r21 ; Touch cache line 5 | |
2001 | ||
2002 | lnol5: | |
2003 | la r22,savevr8(r14) ; Point to V8/V9 pair | |
2004 | bf 22,lnovr6 ; Do not restore VR6... | |
2005 | lvxl v6,br0,r23 ; Restore VR6 | |
2006 | ||
2007 | lnovr6: | |
2008 | bf 23,lnovr7 ; Do not restore VR7... | |
2009 | lvxl v7,r30,r23 ; Restore VR7 | |
2010 | ||
2011 | lnovr7: | |
2012 | ; | |
2013 | ; Note: CR5 is now free | |
2014 | ; | |
2015 | la r21,savevr14(r14) ; Point to line 7 | |
2016 | bf 12,lnol6 ; No line 6 to do... | |
2017 | dcbt br0,r20 ; Touch cache line 6 | |
2018 | ||
2019 | lnol6: | |
2020 | la r23,savevr10(r14) ; Point to V10/V11 pair | |
2021 | bf 24,lnovr8 ; Do not restore VR8... | |
2022 | lvxl v8,br0,r22 ; Restore VR8 | |
2023 | ||
2024 | lnovr8: | |
2025 | bf 25,lnovr9 ; Do not save VR9... | |
2026 | lvxl v9,r30,r22 ; Restore VR9 | |
2027 | ||
2028 | lnovr9: | |
2029 | mtcrf 0x04,r10 ; Set CRs for registers 20-23 | |
2030 | la r20,savevr16(r14) ; Point to line 8 | |
2031 | bf 14,lnol7 ; No line 7 to do... | |
2032 | dcbt br0,r21 ; Touch cache line 7 | |
2033 | ||
2034 | lnol7: | |
2035 | la r22,savevr12(r14) ; Point to V12/V13 pair | |
2036 | bf 26,lnovr10 ; Do not restore VR10... | |
2037 | lvxl v10,br0,r23 ; Restore VR10 | |
2038 | ||
2039 | lnovr10: | |
2040 | bf 27,lnovr11 ; Do not restore VR11... | |
2041 | lvxl v11,r30,r23 ; Restore VR11 | |
2042 | ||
2043 | lnovr11: | |
2044 | ||
2045 | ; | |
2046 | ; Note: CR6 is now free | |
2047 | ; | |
2048 | la r21,savevr18(r14) ; Point to line 9 | |
2049 | bf 1,lnol8 ; No line 8 to do... | |
2050 | dcbt br0,r20 ; Touch cache line 8 | |
2051 | ||
2052 | lnol8: | |
2053 | la r23,savevr14(r14) ; Point to V14/V15 pair | |
2054 | bf 28,lnovr12 ; Do not restore VR12... | |
2055 | lvxl v12,br0,r22 ; Restore VR12 | |
2056 | ||
2057 | lnovr12: | |
2058 | bf 29,lnovr13 ; Do not restore VR13... | |
2059 | lvxl v13,r30,r22 ; Restore VR13 | |
2060 | ||
2061 | lnovr13: | |
2062 | mtcrf 0x02,r10 ; Set CRs for registers 24-27 | |
2063 | la r20,savevr20(r14) ; Point to line 10 | |
2064 | bf 3,lnol9 ; No line 9 to do... | |
2065 | dcbt br0,r21 ; Touch cache line 9 | |
2066 | ||
2067 | lnol9: | |
2068 | la r22,savevr16(r14) ; Point to V16/V17 pair | |
2069 | bf 30,lnovr14 ; Do not restore VR14... | |
2070 | lvxl v14,br0,r23 ; Restore VR14 | |
2071 | ||
2072 | lnovr14: | |
2073 | bf 31,lnovr15 ; Do not restore VR15... | |
2074 | lvxl v15,r30,r23 ; Restore VR15 | |
2075 | ||
2076 | lnovr15: | |
2077 | ; | |
2078 | ; Note: CR7 is now free | |
2079 | ; | |
2080 | la r21,savevr22(r14) ; Point to line 11 | |
2081 | bf 5,lnol10 ; No line 10 to do... | |
2082 | dcbt br0,r20 ; Touch cache line 10 | |
2083 | ||
2084 | lnol10: | |
2085 | la r23,savevr18(r14) ; Point to V18/V19 pair | |
2086 | bf 16,lnovr16 ; Do not restore VR16... | |
2087 | lvxl v16,br0,r22 ; Restore VR16 | |
2088 | ||
2089 | lnovr16: | |
2090 | bf 17,lnovr17 ; Do not restore VR17... | |
2091 | lvxl v17,r30,r22 ; Restore VR17 | |
2092 | ||
2093 | lnovr17: | |
2094 | mtcrf 0x01,r10 ; Set CRs for registers 28-31 | |
2095 | ; | |
2096 | ; Note: All registers have been or are accounted for in CRs | |
2097 | ; | |
2098 | la r20,savevr24(r14) ; Point to line 12 | |
2099 | bf 7,lnol11 ; No line 11 to do... | |
2100 | dcbt br0,r21 ; Touch cache line 11 | |
2101 | ||
2102 | lnol11: | |
2103 | la r22,savevr20(r14) ; Point to V20/V21 pair | |
2104 | bf 18,lnovr18 ; Do not restore VR18... | |
2105 | lvxl v18,br0,r23 ; Restore VR18 | |
2106 | ||
2107 | lnovr18: | |
2108 | bf 19,lnovr19 ; Do not restore VR19... | |
2109 | lvxl v19,r30,r23 ; Restore VR19 | |
2110 | ||
2111 | lnovr19: | |
2112 | la r21,savevr26(r14) ; Point to line 13 | |
2113 | bf 9,lnol12 ; No line 12 to do... | |
2114 | dcbt br0,r20 ; Touch cache line 12 | |
2115 | ||
2116 | lnol12: | |
2117 | la r23,savevr22(r14) ; Point to V22/V23 pair | |
2118 | bf 20,lnovr20 ; Do not restore VR20... | |
2119 | lvxl v20,br0,r22 ; Restore VR20 | |
2120 | ||
2121 | lnovr20: | |
2122 | bf 21,lnovr21 ; Do not restore VR21... | |
2123 | lvxl v21,r30,r22 ; Restore VR21 | |
2124 | ||
2125 | lnovr21: | |
2126 | la r20,savevr28(r14) ; Point to line 14 | |
2127 | bf 11,lnol13 ; No line 13 to do... | |
2128 | dcbt br0,r21 ; Touch cache line 13 | |
2129 | ||
2130 | lnol13: | |
2131 | la r22,savevr24(r14) ; Point to V24/V25 pair | |
2132 | bf 22,lnovr22 ; Do not restore VR22... | |
2133 | lvxl v22,br0,r23 ; Restore VR22 | |
2134 | ||
2135 | lnovr22: | |
2136 | bf 23,lnovr23 ; Do not restore VR23... | |
2137 | lvxl v23,r30,r23 ; Restore VR23 | |
2138 | ||
2139 | lnovr23: | |
2140 | la r21,savevr30(r14) ; Point to line 15 | |
2141 | bf 13,lnol14 ; No line 14 to do... | |
2142 | dcbt br0,r20 ; Touch cache line 14 | |
2143 | ||
2144 | lnol14: | |
2145 | la r23,savevr26(r14) ; Point to V26/V27 pair | |
2146 | bf 24,lnovr24 ; Do not restore VR24... | |
2147 | lvxl v24,br0,r22 ; Restore VR24 | |
2148 | ||
2149 | lnovr24: | |
2150 | bf 25,lnovr25 ; Do not restore VR25... | |
2151 | lvxl v25,r30,r22 ; Restore VR25 | |
2152 | ||
2153 | lnovr25: | |
2154 | bf 15,lnol15 ; No line 15 to do... | |
2155 | dcbt br0,r21 ; Touch cache line 15 | |
2156 | ||
2157 | lnol15: | |
2158 | ; | |
2159 | ; Note: All needed cache lines have been touched now | |
2160 | ; | |
2161 | la r22,savevr28(r14) ; Point to V28/V29 pair | |
2162 | bf 26,lnovr26 ; Do not restore VR26... | |
2163 | lvxl v26,br0,r23 ; Restore VR26 | |
2164 | ||
2165 | lnovr26: | |
2166 | bf 27,lnovr27 ; Do not restore VR27... | |
2167 | lvxl v27,r30,r23 ; Restore VR27 | |
2168 | ||
2169 | lnovr27: | |
2170 | la r23,savevr30(r14) ; Point to V30/V31 pair | |
2171 | bf 28,lnovr28 ; Do not restore VR28... | |
2172 | lvxl v28,br0,r22 ; Restore VR28 | |
2173 | ||
2174 | lnovr28: | |
2175 | bf 29,lnovr29 ; Do not restore VR29... | |
2176 | lvxl v29,r30,r22 ; Restore VR29 | |
2177 | ||
2178 | lnovr29: | |
2179 | bf 30,lnovr30 ; Do not restore VR30... | |
2180 | lvxl v30,br0,r23 ; Restore VR30 | |
2181 | ||
2182 | lnovr30: | |
2183 | ; | |
2184 | ; Everything is restored now except for VR31. We need it to get | |
2185 | ; the QNaNBarbarian value to put into idle vector registers. | |
2186 | ; Note: V31 was set above to QNaNbarbarian | |
2187 | ; | |
2188 | ||
2189 | cmpwi r10,-1 ; Handle the quick case of all registers in use | |
2190 | beq- mstlvr31 ; Not likely, but all are in use... | |
2191 | mtcrf 255,r10 ; Get mask of valid registers | |
2192 | ||
2193 | bt 0,ni0 ; Register is ok already... | |
2194 | vor v0,v31,v31 ; Copy into the next register | |
2195 | ni0: | |
2196 | bt 1,ni1 ; Register is ok already... | |
2197 | vor v1,v31,v31 ; Copy into the next register | |
2198 | ni1: | |
2199 | bt 2,ni2 ; Register is ok already... | |
2200 | vor v2,v31,v31 ; Copy into the next register | |
2201 | ni2: | |
2202 | bt 3,ni3 ; Register is ok already... | |
2203 | vor v3,v31,v31 ; Copy into the next register | |
2204 | ni3: | |
2205 | bt 4,ni4 ; Register is ok already... | |
2206 | vor v4,v31,v31 ; Copy into the next register | |
2207 | ni4: | |
2208 | bt 5,ni5 ; Register is ok already... | |
2209 | vor v5,v31,v31 ; Copy into the next register | |
2210 | ni5: | |
2211 | bt 6,ni6 ; Register is ok already... | |
2212 | vor v6,v31,v31 ; Copy into the next register | |
2213 | ni6: | |
2214 | bt 7,ni7 ; Register is ok already... | |
2215 | vor v7,v31,v31 ; Copy into the next register | |
2216 | ni7: | |
2217 | bt 8,ni8 ; Register is ok already... | |
2218 | vor v8,v31,v31 ; Copy into the next register | |
2219 | ni8: | |
2220 | bt 9,ni9 ; Register is ok already... | |
2221 | vor v9,v31,v31 ; Copy into the next register | |
2222 | ni9: | |
2223 | bt 10,ni10 ; Register is ok already... | |
2224 | vor v10,v31,v31 ; Copy into the next register | |
2225 | ni10: | |
2226 | bt 11,ni11 ; Register is ok already... | |
2227 | vor v11,v31,v31 ; Copy into the next register | |
2228 | ni11: | |
2229 | bt 12,ni12 ; Register is ok already... | |
2230 | vor v12,v31,v31 ; Copy into the next register | |
2231 | ni12: | |
2232 | bt 13,ni13 ; Register is ok already... | |
2233 | vor v13,v31,v31 ; Copy into the next register | |
2234 | ni13: | |
2235 | bt 14,ni14 ; Register is ok already... | |
2236 | vor v14,v31,v31 ; Copy into the next register | |
2237 | ni14: | |
2238 | bt 15,ni15 ; Register is ok already... | |
2239 | vor v15,v31,v31 ; Copy into the next register | |
2240 | ni15: | |
2241 | bt 16,ni16 ; Register is ok already... | |
2242 | vor v16,v31,v31 ; Copy into the next register | |
2243 | ni16: | |
2244 | bt 17,ni17 ; Register is ok already... | |
2245 | vor v17,v31,v31 ; Copy into the next register | |
2246 | ni17: | |
2247 | bt 18,ni18 ; Register is ok already... | |
2248 | vor v18,v31,v31 ; Copy into the next register | |
2249 | ni18: | |
2250 | bt 19,ni19 ; Register is ok already... | |
2251 | vor v19,v31,v31 ; Copy into the next register | |
2252 | ni19: | |
2253 | bt 20,ni20 ; Register is ok already... | |
2254 | vor v20,v31,v31 ; Copy into the next register | |
2255 | ni20: | |
2256 | bt 21,ni21 ; Register is ok already... | |
2257 | vor v21,v31,v31 ; Copy into the next register | |
2258 | ni21: | |
2259 | bt 22,ni22 ; Register is ok already... | |
2260 | vor v22,v31,v31 ; Copy into the next register | |
2261 | ni22: | |
2262 | bt 23,ni23 ; Register is ok already... | |
2263 | vor v23,v31,v31 ; Copy into the next register | |
2264 | ni23: | |
2265 | bt 24,ni24 ; Register is ok already... | |
2266 | vor v24,v31,v31 ; Copy into the next register | |
2267 | ni24: | |
2268 | bt 25,ni25 ; Register is ok already... | |
2269 | vor v25,v31,v31 ; Copy into the next register | |
2270 | ni25: | |
2271 | bt 26,ni26 ; Register is ok already... | |
2272 | vor v26,v31,v31 ; Copy into the next register | |
2273 | ni26: | |
2274 | bt 27,ni27 ; Register is ok already... | |
2275 | vor v27,v31,v31 ; Copy into the next register | |
2276 | ni27: | |
2277 | bt 28,ni28 ; Register is ok already... | |
2278 | vor v28,v31,v31 ; Copy into the next register | |
2279 | ni28: | |
2280 | bt 29,ni29 ; Register is ok already... | |
2281 | vor v29,v31,v31 ; Copy into the next register | |
2282 | ni29: | |
2283 | bt 30,ni30 ; Register is ok already... | |
2284 | vor v30,v31,v31 ; Copy into the next register | |
2285 | ni30: | |
2286 | bf 31,lnovr31 ; V31 is empty, no need to restore... | |
2287 | ||
2288 | mstlvr31: lvxl v31,r30,r23 ; Restore VR31 | |
1c79356b | 2289 | |
de355530 A |
2290 | lnovr31: mr r3,r14 ; Get the old savearea (we popped it before) |
2291 | bl EXT(save_ret) ; Toss it | |
2292 | ||
2293 | vrenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy | |
2294 | rlwinm r5,r25,0,0,19 ; Get the page address of the savearea | |
9bccf70c | 2295 | oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility |
d7e50217 A |
2296 | lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags |
2297 | lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act | |
de355530 | 2298 | lwz r5,SACvrswap(r5) ; Get Virtual to Real translation |
1c79356b | 2299 | oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors |
d7e50217 | 2300 | oris r11,r11,hi16(vectorUsed|vectorCng) ; Set that we used vectors |
9bccf70c | 2301 | rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state |
de355530 A |
2302 | stw r8,savesrr1(r25) ; Set the msr of the interrupted guy |
2303 | xor r3,r25,r5 ; Get the real address of the savearea | |
b4c24cb9 | 2304 | beq- vrnuser ; We are not user state... |
9bccf70c | 2305 | stw r10,ACT_MACT_SPF(r17) ; Set the activation copy |
d7e50217 | 2306 | stw r11,spcFlags(r26) ; Set per_proc copy |
1c79356b A |
2307 | |
2308 | vrnuser: | |
2309 | #if FPVECDBG | |
9bccf70c A |
2310 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
2311 | li r2,0x5F07 ; (TEST/DEBUG) | |
2312 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
2313 | sc ; (TEST/DEBUG) | |
1c79356b | 2314 | #endif |
9bccf70c | 2315 | b EXT(exception_exit) ; Exit to the fray... |
1c79356b A |
2316 | |
2317 | /* | |
2318 | * Initialize the registers to some bogus value | |
1c79356b A |
2319 | */ |
2320 | ||
2321 | ProtectTheAmericanWay: | |
2322 | ||
2323 | #if FPVECDBG | |
9bccf70c A |
2324 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
2325 | li r2,0x5F06 ; (TEST/DEBUG) | |
2326 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
2327 | sc ; (TEST/DEBUG) | |
1c79356b | 2328 | #endif |
9bccf70c A |
2329 | |
2330 | vor v0,v31,v31 ; Copy into the next register | |
2331 | vor v1,v31,v31 ; Copy into the next register | |
2332 | vor v2,v31,v31 ; Copy into the next register | |
2333 | vor v3,v31,v31 ; Copy into the next register | |
2334 | vor v4,v31,v31 ; Copy into the next register | |
2335 | vor v5,v31,v31 ; Copy into the next register | |
2336 | vor v6,v31,v31 ; Copy into the next register | |
2337 | vor v7,v31,v31 ; Copy into the next register | |
2338 | vor v8,v31,v31 ; Copy into the next register | |
2339 | vor v9,v31,v31 ; Copy into the next register | |
2340 | vor v10,v31,v31 ; Copy into the next register | |
2341 | vor v11,v31,v31 ; Copy into the next register | |
2342 | vor v12,v31,v31 ; Copy into the next register | |
2343 | vor v13,v31,v31 ; Copy into the next register | |
2344 | vor v14,v31,v31 ; Copy into the next register | |
2345 | vor v15,v31,v31 ; Copy into the next register | |
2346 | vor v16,v31,v31 ; Copy into the next register | |
2347 | vor v17,v31,v31 ; Copy into the next register | |
2348 | vor v18,v31,v31 ; Copy into the next register | |
2349 | vor v19,v31,v31 ; Copy into the next register | |
2350 | vor v20,v31,v31 ; Copy into the next register | |
2351 | vor v21,v31,v31 ; Copy into the next register | |
2352 | vor v22,v31,v31 ; Copy into the next register | |
2353 | vor v23,v31,v31 ; Copy into the next register | |
2354 | vor v24,v31,v31 ; Copy into the next register | |
2355 | vor v25,v31,v31 ; Copy into the next register | |
2356 | vor v26,v31,v31 ; Copy into the next register | |
2357 | vor v27,v31,v31 ; Copy into the next register | |
2358 | vor v28,v31,v31 ; Copy into the next register | |
2359 | vor v29,v31,v31 ; Copy into the next register | |
2360 | vor v30,v31,v31 ; Copy into the next register | |
2361 | b vrenable ; Finish setting it all up... | |
2362 | ||
2363 | ||
2364 | ||
2365 | ; | |
2366 | ; We get here when we are switching to the same context at the same level and the context | |
2367 | ; is still live. Essentially, all we are doing is turning on the faility. It may have | |
2368 | ; gotten turned off due to doing a context save for the current level or a context switch | |
2369 | ; back to the live guy. | |
2370 | ; | |
2371 | ||
2372 | .align 5 | |
2373 | ||
2374 | vsthesame: | |
2375 | ||
2376 | #if FPVECDBG | |
2377 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
2378 | li r2,0x5F0A ; (TEST/DEBUG) | |
2379 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
2380 | sc ; (TEST/DEBUG) | |
2381 | #endif | |
2382 | beq- cr1,vrenable ; Not saved yet, nothing to pop, go enable and exit... | |
2383 | ||
2384 | lwz r11,SAVlevel(r30) ; Get the level of top saved context | |
de355530 | 2385 | lwz r14,SAVprev(r30) ; Get the previous savearea |
9bccf70c A |
2386 | |
2387 | cmplw r11,r31 ; Are live and saved the same? | |
2388 | ||
2389 | bne+ vrenable ; Level not the same, nothing to pop, go enable and exit... | |
2390 | ||
2391 | mr r3,r30 ; Get the old savearea (we popped it before) | |
2392 | bl EXT(save_ret) ; Toss it | |
2393 | b vrenable ; Go enable and exit... | |
2394 | ||
2395 | ||
2396 | ; | |
2397 | ; This function invalidates any live vector context for the passed in facility_context. | |
2398 | ; This is intended to be called just before act_machine_sv_free tosses saveareas. | |
1c79356b | 2399 | ; |
1c79356b | 2400 | |
9bccf70c A |
2401 | .align 5 |
2402 | .globl EXT(toss_live_vec) | |
1c79356b | 2403 | |
9bccf70c A |
2404 | LEXT(toss_live_vec) |
2405 | ||
2406 | mfmsr r9 ; Get the MSR | |
de355530 A |
2407 | rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions |
2408 | rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now? | |
2409 | rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vector is turned off | |
2410 | rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure fpu is turned off | |
9bccf70c A |
2411 | mtmsr r0 ; No interruptions |
2412 | isync | |
2413 | beq+ tlvnotours ; Vector off, can not be live here... | |
1c79356b | 2414 | |
9bccf70c A |
2415 | mfsprg r8,0 ; Get the per proc |
2416 | ||
2417 | ; | |
2418 | ; Note that at this point, since vecs are on, we are the owner | |
2419 | ; of live state on this processor | |
2420 | ; | |
2421 | ||
2422 | lwz r6,VMXowner(r8) ; Get the thread that owns the vector | |
2423 | li r0,0 ; Clear this just in case we need it | |
2424 | cmplw r6,r3 ; Are we tossing our own context? | |
2425 | bne- tlvnotours ; Nope... | |
2426 | ||
2427 | vspltish v1,1 ; Turn on the non-Java bit and saturate | |
2428 | vspltisw v0,1 ; Turn on the saturate bit | |
2429 | vxor v1,v1,v0 ; Turn off saturate | |
2430 | mtspr vrsave,r0 ; Clear VRSAVE | |
2431 | mtvscr v1 ; Set the non-java, no saturate status | |
2432 | ||
2433 | tlvnotours: lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context | |
2434 | lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc | |
2435 | mulli r11,r11,ppSize ; Find offset to the owner per_proc | |
2436 | ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc | |
2437 | li r10,VMXowner ; Displacement to vector owner | |
2438 | add r11,r12,r11 ; Point to the owner per_proc | |
2439 | li r0,0 ; Set a 0 to invalidate context | |
2440 | ||
2441 | tlvinvothr: lwarx r12,r10,r11 ; Get the owner | |
de355530 A |
2442 | cmplw r12,r3 ; Does he still have this context? |
2443 | bne+ tlvexit ; Nope, leave... | |
2444 | stwcx. r0,r10,r11 ; Try to invalidate it | |
2445 | bne- tlvinvothr ; Try again if there was a collision... | |
9bccf70c | 2446 | |
de355530 | 2447 | tlvexit: mtmsr r9 ; Restore interruptions |
9bccf70c A |
2448 | isync ; Could be turning off vectors here |
2449 | blr ; Leave.... | |
2450 | ||
2451 | #if 0 | |
2452 | ; | |
2453 | ; This function invalidates any live vector context for the passed in facility_context | |
2454 | ; if the level is current. It also tosses the corresponding savearea if there is one. | |
2455 | ; This function is primarily used whenever we detect a VRSave that is all zeros. | |
2456 | ; | |
2457 | ||
2458 | .align 5 | |
2459 | .globl EXT(vec_trash) | |
2460 | ||
2461 | LEXT(vec_trash) | |
2462 | ||
2463 | lwz r12,facAct(r3) ; Get the activation | |
2464 | lwz r11,VMXlevel(r3) ; Get the context level | |
2465 | lwz r10,ACT_MACT_PCB(r12) ; Grab the current level for the thread | |
2466 | lwz r9,VMXsave(r3) ; Get the savearea, if any | |
2467 | cmplw r10,r11 ; Are we at the right level? | |
2468 | cmplwi cr1,r9,0 ; Remember if there is a savearea | |
2469 | bnelr+ ; No, we do nothing... | |
2470 | ||
2471 | lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context | |
2472 | lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc | |
2473 | mulli r11,r11,ppSize ; Find offset to the owner per_proc | |
2474 | ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc | |
2475 | li r10,VMXowner ; Displacement to vector owner | |
2476 | add r11,r12,r11 ; Point to the owner per_proc | |
de355530 | 2477 | li r0,0 ; Set a 0 to invalidate context |
9bccf70c A |
2478 | |
2479 | vtinvothr: lwarx r12,r10,r11 ; Get the owner | |
de355530 A |
2480 | cmplw r12,r3 ; Does he still have this context? |
2481 | bne vtnotlive ; Nope, not live anywhere... | |
2482 | stwcx. r0,r10,r11 ; Try to invalidate it | |
2483 | bne- vtinvothr ; Try again if there was a collision... | |
9bccf70c | 2484 | |
de355530 | 2485 | vtnotlive: beqlr+ cr1 ; Leave if there is no savearea |
9bccf70c A |
2486 | lwz r8,SAVlevel(r9) ; Get the level of the savearea |
2487 | cmplw r8,r11 ; Savearea for the current level? | |
de355530 | 2488 | bnelr+ ; No, nothing to release... |
9bccf70c | 2489 | |
de355530 | 2490 | lwz r8,SAVprev(r9) ; Pick up the previous area |
9bccf70c | 2491 | mr. r8,r8 ; Is there a previous? |
de355530 | 2492 | beq- vtnoprev ; Nope... |
9bccf70c A |
2493 | lwz r7,SAVlevel(r8) ; Get the level associated with save |
2494 | ||
2495 | vtnoprev: stw r8,VMXsave(r3) ; Dequeue this savearea | |
2496 | stw r7,VMXlevel(r3) ; Pop the level | |
2497 | ||
2498 | mr r3,r9 ; Get the savearea to release | |
2499 | b EXT(save_ret) ; Go and toss the save area (note, we will return from there)... | |
2500 | #endif | |
2501 | ||
2502 | ; | |
2503 | ; Just some test code to force vector and/or floating point in the kernel | |
2504 | ; | |
2505 | ||
2506 | .align 5 | |
2507 | .globl EXT(fctx_test) | |
1c79356b | 2508 | |
9bccf70c A |
2509 | LEXT(fctx_test) |
2510 | ||
2511 | mfsprg r3,0 ; Get the per_proc block | |
2512 | lwz r3,PP_ACTIVE_THREAD(r3) ; Get the thread pointer | |
2513 | mr. r3,r3 ; Are we actually up and running? | |
2514 | beqlr- ; No... | |
2515 | ||
2516 | fmr f0,f0 ; Use floating point | |
2517 | mftb r4 ; Get time base for a random number | |
2518 | li r5,1 ; Get a potential vrsave to use | |
2519 | andi. r4,r4,0x3F ; Get a number from 0 - 63 | |
2520 | slw r5,r5,r4 ; Choose a register to save (should be 0 half the time) | |
2521 | mtspr vrsave,r5 ; Set VRSave | |
2522 | vor v0,v0,v0 ; Use vectors | |
2523 | blr |