]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
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 | |
9bccf70c | 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 */ | |
9bccf70c | 82 | mtsprg 1,r9 |
1c79356b A |
83 | stw r1,0(r12) |
84 | li r0,0 /* Clear a register */ | |
85 | lwz r8,ACT_MACT_PCB(r9) /* Get the savearea used */ | |
1c79356b A |
86 | rlwinm r7,r8,0,0,19 /* Switch to savearea base */ |
87 | lwz r11,SAVprev(r8) /* Get the previous savearea */ | |
88 | mfmsr r5 /* Since we are passing control, get our MSR values */ | |
89 | lwz r1,saver1(r8) /* Load new stack pointer */ | |
1c79356b A |
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 */ | |
92 | stw r0,FM_BACKPTR(r1) /* zero backptr */ | |
93 | stw r5,savesrr1(r8) /* Pass our MSR to the new guy */ | |
1c79356b A |
94 | xor r3,r7,r8 /* Get the physical address of the new context save area */ |
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. | |
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. | |
126 | */ | |
127 | ||
128 | /* Context switches are double jumps. We pass the following to the | |
129 | * context switch firmware call: | |
130 | * | |
131 | * R3 = switchee's savearea | |
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 |
9bccf70c | 149 | lwz r11,PP_ISTACKPTR(r12) ; (DEBUG/TRACE) make sure we are not |
1c79356b A |
150 | mr. r11,r11 ; (DEBUG/TRACE) on the interrupt |
151 | bne+ notonintstack ; (DEBUG/TRACE) stack | |
152 | BREAKPOINT_TRAP | |
153 | notonintstack: | |
154 | #endif | |
9bccf70c A |
155 | stw r4,THREAD_CONTINUATION(r3) ; Set continuation into the thread |
156 | cmpwi cr1,r4,0 ; used waaaay down below | |
157 | lwz r7,0(r10) ; Get the current stack | |
1c79356b A |
158 | /* |
159 | * Make the new thread the current thread. | |
160 | */ | |
161 | ||
9bccf70c A |
162 | stw r7,THREAD_KERNEL_STACK(r3) ; Remember the current stack in the thread (do not need???) |
163 | stw r5, PP_ACTIVE_THREAD(r12) ; Make the new thread current | |
1c79356b | 164 | |
9bccf70c | 165 | lwz r11,THREAD_KERNEL_STACK(r5) ; Get the new stack pointer |
1c79356b | 166 | |
9bccf70c A |
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 |
0b4e3aa0 | 170 | lwz r8,ACT_MACT_PCB(r5) ; Get the PCB for the new guy |
9bccf70c A |
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 | |
180 | ||
181 | stw r11,0(r10) ; Save the new kernel stack address | |
182 | stw r7,UAW(r12) ; Save the assist word for the "ultra fast path" | |
0b4e3aa0 A |
183 | |
184 | lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment | |
1c79356b A |
185 | |
186 | lwz r7,ACT_MACT_SPF(r5) ; Get the special flags | |
187 | ||
188 | lwz r10,ACT_KLOADED(r5) | |
9bccf70c | 189 | stw r11,ppbbTaskEnv(r12) ; Save the bb task env |
1c79356b A |
190 | li r0,0 |
191 | cmpwi cr0,r10,0 | |
9bccf70c A |
192 | lwz r10,PP_ACTIVE_KLOADED(r12) |
193 | stw r7,spcFlags(r12) ; Set per_proc copy of the special flags | |
1c79356b A |
194 | beq cr0,.L_sw_ctx_not_kld |
195 | ||
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 | |
208 | lis r0,hi16(CutTrace) ; Trace FW call | |
209 | mr. r10,r10 ; Any tracing going on? | |
210 | ori r0,r0,lo16(CutTrace) ; Trace FW call | |
211 | beq+ cswNoTrc ; No trace today, dude... | |
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 | ||
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 */ | |
1c79356b A |
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 */ | |
9bccf70c | 223 | lwz r2,curctx(r5) ; Grab our current context pointer |
1c79356b A |
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 */ | |
9bccf70c A |
226 | |
227 | lhz r0,PP_CPU_NUMBER(r12) ; Get our CPU number | |
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? | |
233 | bne+ cswnofloat ; Float is not ours... | |
234 | ||
235 | cmplw r10,r11 ; Is the level the same? | |
236 | lwz r5,FPUcpu(r2) ; Get the owning cpu | |
237 | bne+ cswnofloat ; Level not the same, this is not live... | |
238 | ||
239 | cmplw r5,r0 ; Still owned by this cpu? | |
240 | lwz r10,FPUsave(r2) ; Get the level | |
241 | bne+ cswnofloat ; CPU claimed by someone else... | |
242 | ||
243 | mr. r10,r10 ; Is there a savearea here? | |
244 | ori r6,r6,lo16(MASK(MSR_FP)) ; Enable floating point | |
245 | ||
246 | beq- cswnofloat ; No savearea to check... | |
247 | ||
248 | lwz r3,SAVlevel(r10) ; Get the level | |
249 | lwz r5,SAVprev(r10) ; Get the previous of this savearea | |
250 | cmplw r3,r11 ; Is it for the current level? | |
251 | ||
252 | bne+ cswnofloat ; Nope... | |
253 | ||
254 | stw r5,FPUsave(r2) ; Pop off this savearea | |
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 | |
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 | ||
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... | |
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 | |
287 | bne+ cswnovect ; Level not the same, this is not live... | |
288 | ||
289 | cmplw r5,r0 ; Still owned by this cpu? | |
290 | lwz r10,VMXsave(r2) ; Get the level | |
291 | bne+ cswnovect ; CPU claimed by someone else... | |
292 | ||
293 | mr. r10,r10 ; Is there a savearea here? | |
294 | oris r6,r6,hi16(MASK(MSR_VEC)) ; Enable vector | |
295 | ||
296 | beq- cswnovect ; No savearea to check... | |
297 | ||
298 | lwz r3,SAVlevel(r10) ; Get the level | |
299 | lwz r5,SAVprev(r10) ; Get the previous of this savearea | |
300 | cmplw r3,r11 ; Is it for the current level? | |
301 | ||
302 | bne+ cswnovect ; Nope... | |
303 | ||
304 | stw r5,VMXsave(r2) ; Pop off this savearea | |
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 | |
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 | ||
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 | ; | |
324 | ||
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 */ | |
333 | lis r0,hi16(SwitchContextCall) /* Top part of switch context */ | |
1c79356b | 334 | stw r9,savesrr0(r8) /* Make us jump to the switch in routine */ |
9bccf70c | 335 | |
1c79356b A |
336 | li r10,MSR_SUPERVISOR_INT_OFF /* Get the switcher's MSR */ |
337 | lwz r9,SAVflags(r8) /* Get the flags */ | |
338 | stw r10,savesrr1(r8) /* Set up for switch in */ | |
339 | rlwinm r9,r9,0,15,13 /* Reset the syscall flag */ | |
340 | ori r0,r0,lo16(SwitchContextCall) /* Bottom part of switch context */ | |
1c79356b A |
341 | xor r3,r7,r8 /* Get the physical address of the new context save area */ |
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 A |
362 | swtchtocont: |
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 | |
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 | * | |
378 | * R3 = switcher's savearea | |
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) | |
1c79356b A |
391 | |
392 | lwz r4,saver4(r3) /* Get the old thread */ | |
1c79356b A |
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 */ | |
397 | ||
398 | stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */ | |
399 | stw r10,SAVprev(r3) /* Chain on the old one */ | |
400 | ||
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 | |
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 | |
433 | rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off | |
1c79356b | 434 | rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now |
9bccf70c A |
435 | ori r2,r2,MASK(MSR_FP) ; Enable the floating point feature for now also |
436 | rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off | |
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) | |
451 | beq- noowneryet ; (TEST/DEBUG) | |
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 | |
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 A |
470 | lwz r9,FPUcpu(r12) ; Get the cpu that context was last on |
471 | bne- cr1,fsret ; No, it is not... | |
1c79356b | 472 | |
9bccf70c A |
473 | cmplw cr1,r9,r11 ; Was the context for this processor? |
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? | |
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... | |
497 | beq- fsbackout ; If disowned, just toss savearea... | |
498 | lwz r4,facAct(r12) ; Get the activation associated with live context | |
499 | mtlr r2 ; Restore return | |
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 | |
504 | stw r8,SAVprev(r3) ; And then chain this in front | |
1c79356b | 505 | |
9bccf70c | 506 | stw r9,SAVlevel(r3) ; Show level in savearea |
1c79356b A |
507 | |
508 | ; | |
509 | ; Save the current FPU state into the PCB of the thread that owns it. | |
510 | ; | |
511 | ||
9bccf70c A |
512 | la r11,savefp0(r3) ; Point to the 1st line |
513 | dcbz 0,r11 ; Allocate the first savearea line | |
1c79356b | 514 | |
9bccf70c | 515 | la r11,savefp4(r3) ; Point to the 2nd line |
1c79356b | 516 | stfd f0,savefp0(r3) |
9bccf70c | 517 | dcbz 0,r11 ; Allocate it |
1c79356b A |
518 | stfd f1,savefp1(r3) |
519 | stfd f2,savefp2(r3) | |
9bccf70c | 520 | la r11,savefp8(r3) ; Point to the 3rd line |
1c79356b | 521 | stfd f3,savefp3(r3) |
9bccf70c | 522 | dcbz 0,r11 ; Allocate it |
1c79356b A |
523 | stfd f4,savefp4(r3) |
524 | stfd f5,savefp5(r3) | |
525 | stfd f6,savefp6(r3) | |
9bccf70c | 526 | la r11,savefp12(r3) ; Point to the 4th line |
1c79356b | 527 | stfd f7,savefp7(r3) |
9bccf70c | 528 | dcbz 0,r11 ; Allocate it |
1c79356b A |
529 | stfd f8,savefp8(r3) |
530 | stfd f9,savefp9(r3) | |
531 | stfd f10,savefp10(r3) | |
9bccf70c | 532 | la r11,savefp16(r3) ; Point to the 5th line |
1c79356b | 533 | stfd f11,savefp11(r3) |
9bccf70c | 534 | dcbz 0,r11 ; Allocate it |
1c79356b A |
535 | stfd f12,savefp12(r3) |
536 | stfd f13,savefp13(r3) | |
537 | stfd f14,savefp14(r3) | |
9bccf70c | 538 | la r11,savefp20(r3) ; Point to the 6th line |
1c79356b A |
539 | stfd f15,savefp15(r3) |
540 | stfd f16,savefp16(r3) | |
541 | stfd f17,savefp17(r3) | |
542 | stfd f18,savefp18(r3) | |
9bccf70c | 543 | la r11,savefp24(r3) ; Point to the 7th line |
1c79356b | 544 | stfd f19,savefp19(r3) |
9bccf70c | 545 | dcbz 0,r11 ; Allocate it |
1c79356b | 546 | stfd f20,savefp20(r3) |
1c79356b A |
547 | stfd f21,savefp21(r3) |
548 | stfd f22,savefp22(r3) | |
9bccf70c | 549 | la r11,savefp28(r3) ; Point to the 8th line |
1c79356b | 550 | stfd f23,savefp23(r3) |
9bccf70c | 551 | dcbz 0,r11 ; Allocate it |
1c79356b A |
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 | ||
1c79356b A |
558 | stfd f29,savefp29(r3) |
559 | stfd f30,savefp30(r3) | |
560 | stfd f31,savefp31(r3) | |
9bccf70c A |
561 | |
562 | fsret: mtmsr r0 ; Put interrupts on if they were and floating point off | |
1c79356b A |
563 | isync |
564 | ||
565 | blr | |
566 | ||
9bccf70c A |
567 | fsbackout: mr r12,r0 ; Save the original MSR |
568 | b EXT(save_ret_join) ; Toss savearea and return from there... | |
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 | ||
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 | |
682 | stw r3,FPUsave(r22) ; Set this as the latest context savearea for the thread | |
1c79356b | 683 | |
9bccf70c A |
684 | stw r30,SAVprev(r3) ; Point us to the old context |
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 | ||
697 | ; | |
698 | ; Now we will actually save the old context | |
699 | ; | |
700 | ||
9bccf70c | 701 | la r11,savefp4(r3) ; Point to the 2nd line |
1c79356b | 702 | stfd f0,savefp0(r3) |
9bccf70c | 703 | dcbz 0,r11 ; Allocate cache |
1c79356b A |
704 | stfd f1,savefp1(r3) |
705 | stfd f2,savefp2(r3) | |
9bccf70c | 706 | la r11,savefp8(r3) ; Point to the 3rd line |
1c79356b | 707 | stfd f3,savefp3(r3) |
9bccf70c | 708 | dcbz 0,r11 ; Allocate cache |
1c79356b A |
709 | stfd f4,savefp4(r3) |
710 | stfd f5,savefp5(r3) | |
711 | stfd f6,savefp6(r3) | |
9bccf70c | 712 | la r11,savefp12(r3) ; Point to the 4th line |
1c79356b | 713 | stfd f7,savefp7(r3) |
9bccf70c | 714 | dcbz 0,r11 ; Allocate cache |
1c79356b A |
715 | stfd f8,savefp8(r3) |
716 | stfd f9,savefp9(r3) | |
717 | stfd f10,savefp10(r3) | |
9bccf70c | 718 | la r11,savefp16(r3) ; Point to the 5th line |
1c79356b | 719 | stfd f11,savefp11(r3) |
9bccf70c | 720 | dcbz 0,r11 ; Allocate cache |
1c79356b A |
721 | stfd f12,savefp12(r3) |
722 | stfd f13,savefp13(r3) | |
723 | stfd f14,savefp14(r3) | |
9bccf70c | 724 | la r11,savefp20(r3) ; Point to the 6th line |
1c79356b | 725 | stfd f15,savefp15(r3) |
9bccf70c | 726 | dcbz 0,r11 ; Allocate cache |
1c79356b A |
727 | stfd f16,savefp16(r3) |
728 | stfd f17,savefp17(r3) | |
729 | stfd f18,savefp18(r3) | |
9bccf70c | 730 | la r11,savefp24(r3) ; Point to the 7th line |
1c79356b | 731 | stfd f19,savefp19(r3) |
9bccf70c | 732 | dcbz 0,r11 ; Allocate cache |
1c79356b A |
733 | stfd f20,savefp20(r3) |
734 | ||
1c79356b A |
735 | stfd f21,savefp21(r3) |
736 | stfd f22,savefp22(r3) | |
9bccf70c | 737 | la r11,savefp28(r3) ; Point to the 8th line |
1c79356b | 738 | stfd f23,savefp23(r3) |
9bccf70c | 739 | dcbz 0,r11 ; allocate it |
1c79356b A |
740 | stfd f24,savefp24(r3) |
741 | stfd f25,savefp25(r3) | |
742 | stfd f26,savefp26(r3) | |
1c79356b | 743 | stfd f27,savefp27(r3) |
9bccf70c | 744 | dcbz 0,r11 ; allocate it |
1c79356b A |
745 | stfd f28,savefp28(r3) |
746 | stfd f29,savefp29(r3) | |
747 | stfd f30,savefp30(r3) | |
748 | stfd f31,savefp31(r3) | |
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 | |
783 | li r0,0 | |
784 | ||
785 | fsinvothr: lwarx r18,r16,r19 ; Get the owner | |
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... | |
790 | ||
791 | fsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load? | |
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 A |
796 | |
797 | beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load... | |
9bccf70c A |
798 | |
799 | dcbt 0,r11 ; Touch line in | |
800 | ||
801 | lwz r3,SAVprev(r14) ; Get the previous context | |
802 | lwz r0,SAVlevel(r14) ; Get the level of first facility savearea | |
803 | cmplw r0,r15 ; Top level correct to load? | |
1c79356b | 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 | ||
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 | |
867 | ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature | |
868 | lwz r10,ACT_MACT_SPF(r17) ; Get the special flags | |
869 | lwz r5,SACvrswap(r5) ; Get Virtual to Real translation | |
1c79356b | 870 | oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point |
9bccf70c A |
871 | rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state |
872 | stw r8,savesrr1(r25) ; Set the msr of the interrupted guy | |
873 | xor r3,r25,r5 ; Get the real address of the savearea | |
b4c24cb9 | 874 | beq- fsnuser ; We are not user state... |
9bccf70c A |
875 | stw r10,ACT_MACT_SPF(r17) ; Set the activation copy |
876 | stw r10,spcFlags(r26) ; Set per_proc copy | |
1c79356b A |
877 | |
878 | fsnuser: | |
879 | #if FPVECDBG | |
9bccf70c A |
880 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
881 | li r2,0x7F07 ; (TEST/DEBUG) | |
882 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
883 | sc ; (TEST/DEBUG) | |
1c79356b | 884 | #endif |
1c79356b | 885 | |
9bccf70c | 886 | b EXT(exception_exit) ; Exit to the fray... |
1c79356b A |
887 | |
888 | /* | |
889 | * Initialize the registers to some bogus value | |
890 | */ | |
891 | ||
892 | MakeSureThatNoTerroristsCanHurtUsByGod: | |
0b4e3aa0 | 893 | |
1c79356b | 894 | #if FPVECDBG |
9bccf70c A |
895 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
896 | li r2,0x7F06 ; (TEST/DEBUG) | |
897 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
898 | sc ; (TEST/DEBUG) | |
1c79356b | 899 | #endif |
9bccf70c A |
900 | lis r5,hi16(EXT(FloatInit)) ; Get top secret floating point init value address |
901 | ori r5,r5,lo16(EXT(FloatInit)) ; Slam bottom | |
902 | lfd f0,0(r5) ; Initialize FP0 | |
903 | fmr f1,f0 ; Do them all | |
1c79356b A |
904 | fmr f2,f0 |
905 | fmr f3,f0 | |
906 | fmr f4,f0 | |
907 | fmr f5,f0 | |
908 | fmr f6,f0 | |
909 | fmr f7,f0 | |
910 | fmr f8,f0 | |
911 | fmr f9,f0 | |
912 | fmr f10,f0 | |
913 | fmr f11,f0 | |
914 | fmr f12,f0 | |
915 | fmr f13,f0 | |
916 | fmr f14,f0 | |
917 | fmr f15,f0 | |
918 | fmr f16,f0 | |
919 | fmr f17,f0 | |
1c79356b A |
920 | fmr f18,f0 |
921 | fmr f19,f0 | |
922 | fmr f20,f0 | |
1c79356b A |
923 | fmr f21,f0 |
924 | fmr f22,f0 | |
925 | fmr f23,f0 | |
926 | fmr f24,f0 | |
927 | fmr f25,f0 | |
928 | fmr f26,f0 | |
929 | fmr f27,f0 | |
930 | fmr f28,f0 | |
931 | fmr f29,f0 | |
932 | fmr f30,f0 | |
933 | fmr f31,f0 | |
9bccf70c A |
934 | b fsenable ; Finish setting it all up... |
935 | ||
1c79356b A |
936 | |
937 | ; | |
9bccf70c A |
938 | ; We get here when we are switching to the same context at the same level and the context |
939 | ; is still live. Essentially, all we are doing is turning on the faility. It may have | |
940 | ; gotten turned off due to doing a context save for the current level or a context switch | |
941 | ; back to the live guy. | |
1c79356b | 942 | ; |
9bccf70c A |
943 | |
944 | .align 5 | |
1c79356b | 945 | |
9bccf70c | 946 | fsthesame: |
1c79356b | 947 | |
9bccf70c A |
948 | #if FPVECDBG |
949 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
950 | li r2,0x7F0A ; (TEST/DEBUG) | |
951 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
952 | sc ; (TEST/DEBUG) | |
953 | #endif | |
954 | beq- cr1,fsenable ; Not saved yet, nothing to pop, go enable and exit... | |
1c79356b | 955 | |
9bccf70c A |
956 | lwz r11,SAVlevel(r30) ; Get the level of top saved context |
957 | lwz r14,SAVprev(r30) ; Get the previous savearea | |
1c79356b | 958 | |
9bccf70c | 959 | cmplw r11,r31 ; Are live and saved the same? |
1c79356b | 960 | |
9bccf70c | 961 | bne+ fsenable ; Level not the same, nothing to pop, go enable and exit... |
1c79356b | 962 | |
9bccf70c A |
963 | mr r3,r30 ; Get the old savearea (we popped it before) |
964 | bl EXT(save_ret) ; Toss it | |
965 | b fsenable ; Go enable and exit... | |
966 | ||
967 | ||
968 | ; | |
969 | ; This function invalidates any live floating point context for the passed in facility_context. | |
970 | ; This is intended to be called just before act_machine_sv_free tosses saveareas. | |
971 | ; | |
972 | ||
973 | .align 5 | |
974 | .globl EXT(toss_live_fpu) | |
975 | ||
976 | LEXT(toss_live_fpu) | |
977 | ||
978 | ||
979 | mfmsr r9 ; Get the MSR | |
980 | rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions | |
981 | rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now? | |
982 | rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off | |
983 | rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure floats are turned off | |
984 | mtmsr r0 ; No interruptions | |
985 | isync | |
986 | beq+ tlfnotours ; Floats off, can not be live here... | |
987 | ||
988 | mfsprg r8,0 ; Get the per proc | |
989 | ||
990 | ; | |
991 | ; Note that at this point, since floats are on, we are the owner | |
992 | ; of live state on this processor | |
1c79356b | 993 | ; |
9bccf70c A |
994 | |
995 | lwz r6,FPUowner(r8) ; Get the thread that owns the floats | |
996 | li r0,0 ; Clear this just in case we need it | |
997 | cmplw r6,r3 ; Are we tossing our own context? | |
998 | bne- tlfnotours ; Nope... | |
999 | ||
1000 | fsub f1,f1,f1 ; Make a 0 | |
1001 | mtfsf 0xFF,f1 ; Clear it | |
1002 | ||
1003 | tlfnotours: lwz r11,FPUcpu(r3) ; Get the cpu on which we last loaded context | |
1004 | lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc | |
1005 | mulli r11,r11,ppSize ; Find offset to the owner per_proc | |
1006 | ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc | |
1007 | li r10,FPUowner ; Displacement to float owner | |
1008 | add r11,r12,r11 ; Point to the owner per_proc | |
1009 | li r0,0 ; Set a 0 to invalidate context | |
1010 | ||
1011 | tlfinvothr: lwarx r12,r10,r11 ; Get the owner | |
1012 | cmplw r12,r3 ; Does he still have this context? | |
1013 | bne+ tlfexit ; Nope, leave... | |
1014 | stwcx. r0,r10,r11 ; Try to invalidate it | |
1015 | bne- tlfinvothr ; Try again if there was a collision... | |
1016 | ||
1017 | tlfexit: mtmsr r9 ; Restore interruptions | |
1018 | isync ; Could be turning off floats here | |
1019 | blr ; Leave... | |
1020 | ||
1c79356b A |
1021 | |
1022 | /* | |
1023 | * Altivec stuff is here. The techniques used are pretty identical to | |
1024 | * the floating point. Except that we will honor the VRSAVE register | |
1025 | * settings when loading and restoring registers. | |
1026 | * | |
1027 | * There are two indications of saved VRs: the VRSAVE register and the vrvalid | |
1028 | * mask. VRSAVE is set by the vector user and represents the VRs that they | |
1029 | * say that they are using. The vrvalid mask indicates which vector registers | |
1030 | * are saved in the savearea. Whenever context is saved, it is saved according | |
1031 | * to the VRSAVE register. It is loaded based on VRSAVE anded with | |
1032 | * vrvalid (all other registers are splatted with 0s). This is done because we | |
1033 | * don't want to load any registers we don't have a copy of, we want to set them | |
1034 | * to zero instead. | |
1035 | * | |
9bccf70c A |
1036 | * Note that there are some oddities here when we save a context we are using. |
1037 | * It is really not too cool to do this, but what the hey... Anyway, | |
1038 | * we turn vectors and fpu off before we leave. | |
1039 | * The oddity is that if you use vectors after this, the | |
1040 | * savearea containing the context just saved will go away. So, bottom line is | |
1041 | * that don't use vectors until after you are done with the saved context. | |
1042 | * | |
1c79356b A |
1043 | */ |
1044 | ||
9bccf70c A |
1045 | .align 5 |
1046 | .globl EXT(vec_save) | |
1047 | ||
1048 | LEXT(vec_save) | |
1c79356b | 1049 | |
9bccf70c A |
1050 | mfmsr r0 ; Get the MSR |
1051 | rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off when we leave | |
1c79356b | 1052 | rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now |
9bccf70c A |
1053 | oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also |
1054 | rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp | |
1055 | mtmsr r2 ; Set the MSR | |
1c79356b A |
1056 | isync |
1057 | ||
9bccf70c A |
1058 | mfsprg r6,0 ; Get the per_processor block |
1059 | lwz r12,VMXowner(r6) ; Get the context ID for owner | |
1060 | ||
1c79356b | 1061 | #if FPVECDBG |
9bccf70c A |
1062 | mr r7,r0 ; (TEST/DEBUG) |
1063 | li r4,0 ; (TEST/DEBUG) | |
1064 | mr r10,r3 ; (TEST/DEBUG) | |
1065 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
1066 | mr. r3,r12 ; (TEST/DEBUG) | |
1067 | li r2,0x5F00 ; (TEST/DEBUG) | |
1068 | li r5,0 ; (TEST/DEBUG) | |
1069 | beq- noowneryeu ; (TEST/DEBUG) | |
1070 | lwz r4,VMXlevel(r12) ; (TEST/DEBUG) | |
1071 | lwz r5,VMXsave(r12) ; (TEST/DEBUG) | |
1072 | ||
1073 | noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1074 | sc ; (TEST/DEBUG) | |
1075 | mr r0,r7 ; (TEST/DEBUG) | |
1076 | mr r3,r10 ; (TEST/DEBUG) | |
1c79356b | 1077 | #endif |
9bccf70c A |
1078 | mflr r2 ; Save the return address |
1079 | ||
1080 | vsretry: mr. r12,r12 ; Anyone own the vector? | |
1081 | lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number | |
1082 | beq- vsret ; Nobody owns the vector, no save required... | |
1083 | ||
1084 | cmplw cr1,r3,r12 ; Is the specified context live? | |
1085 | ||
1086 | isync ; Force owner check first | |
1087 | ||
1088 | lwz r9,VMXcpu(r12) ; Get the cpu that context was last on | |
1089 | bne- cr1,vsret ; Specified context is not live | |
1090 | ||
1091 | cmplw cr1,r9,r11 ; Was the context for this processor? | |
1092 | beq+ cr1,vsgoodcpu ; Facility last used on this processor... | |
1093 | ||
1094 | b vsret ; Someone else claimed this... | |
1095 | ||
1096 | .align 5 | |
1097 | ||
1098 | vsgoodcpu: lwz r3,VMXsave(r12) ; Get the current vector savearea for the thread | |
1099 | lwz r10,liveVRS(r6) ; Get the right VRSave register | |
1100 | lwz r9,VMXlevel(r12) ; Get our current level indicator | |
1101 | ||
1102 | ||
1103 | cmplwi cr1,r3,0 ; Have we ever saved this facility context? | |
1104 | beq- cr1,vsneedone ; Never saved it, so we need an area... | |
1105 | ||
1106 | lwz r8,SAVlevel(r3) ; Get the level this savearea is for | |
1107 | mr. r10,r10 ; Is VRsave set to 0? | |
1108 | cmplw cr1,r9,r8 ; Correct level? | |
1109 | bne- cr1,vsneedone ; Different level, so we need to save... | |
1c79356b | 1110 | |
9bccf70c | 1111 | bne+ vsret ; VRsave is non-zero so we need to keep what is saved... |
0b4e3aa0 | 1112 | |
9bccf70c A |
1113 | lwz r4,SAVprev(r3) ; Pick up the previous area |
1114 | lwz r5,SAVlevel(r4) ; Get the level associated with save | |
1115 | stw r4,VMXsave(r12) ; Dequeue this savearea | |
1116 | stw r5,VMXlevel(r12) ; Save the level | |
1117 | ||
1118 | li r3,0 ; Clear | |
1119 | stw r3,VMXowner(r12) ; Show no live context here | |
1120 | eieio | |
1121 | ||
1122 | vsbackout: mr r12,r0 ; Set the saved MSR | |
1123 | b EXT(save_ret_join) ; Toss the savearea and return from there... | |
1124 | ||
1125 | .align 5 | |
1126 | ||
1127 | vsneedone: mr. r10,r10 ; Is VRsave set to 0? | |
1128 | beq- vsret ; Yeah, they do not care about any of them... | |
1129 | ||
1130 | bl EXT(save_get) ; Get a savearea for the context | |
1131 | ||
1132 | mfsprg r6,0 ; Get back per_processor block | |
1133 | li r4,SAVvector ; Get vector tag | |
1134 | lwz r12,VMXowner(r6) ; Get back our context ID | |
1135 | stb r4,SAVflags+2(r3) ; Mark this savearea as a vector | |
1136 | mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it... | |
1137 | beq- vsbackout ; If disowned, just toss savearea... | |
1138 | lwz r4,facAct(r12) ; Get the activation associated with live context | |
1139 | mtlr r2 ; Restore return | |
1140 | lwz r8,VMXsave(r12) ; Get the current top vector savearea | |
1141 | stw r4,SAVact(r3) ; Indicate the right activation for this context | |
1142 | lwz r9,VMXlevel(r12) ; Get our current level indicator again | |
1143 | stw r3,VMXsave(r12) ; Set this as the most current floating point context | |
1144 | stw r8,SAVprev(r3) ; And then chain this in front | |
1145 | ||
1146 | stw r9,SAVlevel(r3) ; Set level in savearea | |
1147 | ||
1c79356b A |
1148 | mfcr r2 ; Save non-volatile CRs |
1149 | lwz r10,liveVRS(r6) ; Get the right VRSave register | |
1150 | lis r9,0x5555 ; Mask with odd bits set | |
1151 | rlwinm r11,r10,1,0,31 ; Shift over 1 | |
1152 | ori r9,r9,0x5555 ; Finish mask | |
0b4e3aa0 | 1153 | or r4,r10,r11 ; After this, even bits show which lines to zap |
1c79356b | 1154 | |
0b4e3aa0 | 1155 | andc r11,r4,r9 ; Clear out odd bits |
1c79356b A |
1156 | |
1157 | la r6,savevr0(r3) ; Point to line 0 | |
1158 | rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits | |
1c79356b A |
1159 | or r4,r11,r4 ; Set the odd bits |
1160 | ; (bit 0 is line 0, bit 1 is line 8, | |
1161 | ; bit 2 is line 1, bit 3 is line 9, etc. | |
1c79356b A |
1162 | rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31 |
1163 | la r7,savevr2(r3) ; Point to line 1 | |
1164 | mtcrf 255,r4 ; Load up the CRs | |
1165 | stw r10,savevrvalid(r3) ; Save the validity information | |
1166 | mr r8,r6 ; Start registers off | |
1167 | ; | |
1168 | ; Save the current vector state | |
1169 | ; | |
1170 | ||
1171 | bf 0,snol0 ; No line 0 to do... | |
1172 | dcba br0,r6 ; Allocate cache line 0 | |
1173 | ||
1174 | snol0: | |
1175 | la r6,savevr4(r3) ; Point to line 2 | |
1176 | bf 2,snol1 ; No line 1 to do... | |
1177 | dcba br0,r7 ; Allocate cache line 1 | |
1178 | ||
1179 | snol1: | |
1180 | la r7,savevr6(r3) ; Point to line 3 | |
1181 | bf 4,snol2 ; No line 2 to do... | |
1182 | dcba br0,r6 ; Allocate cache line 2 | |
1183 | ||
1184 | snol2: | |
1185 | li r11,16 ; Get offset for odd registers | |
1186 | bf 16,snovr0 ; Do not save VR0... | |
1187 | stvxl v0,br0,r8 ; Save VR0 | |
1188 | ||
1189 | snovr0: | |
1190 | la r9,savevr2(r3) ; Point to V2/V3 pair | |
1191 | bf 17,snovr1 ; Do not save VR1... | |
1192 | stvxl v1,r11,r8 ; Save VR1 | |
1193 | ||
1194 | snovr1: | |
1195 | la r6,savevr8(r3) ; Point to line 4 | |
1196 | bf 6,snol3 ; No line 3 to do... | |
1197 | dcba br0,r7 ; Allocate cache line 3 | |
1198 | ||
1199 | snol3: | |
1200 | la r8,savevr4(r3) ; Point to V4/V5 pair | |
1201 | bf 18,snovr2 ; Do not save VR2... | |
1202 | stvxl v2,br0,r9 ; Save VR2 | |
1203 | ||
1204 | snovr2: | |
1205 | bf 19,snovr3 ; Do not save VR3... | |
1206 | stvxl v3,r11,r9 ; Save VR3 | |
1207 | ||
1208 | snovr3: | |
1209 | ; | |
1210 | ; Note: CR4 is now free | |
1211 | ; | |
1212 | la r7,savevr10(r3) ; Point to line 5 | |
1213 | bf 8,snol4 ; No line 4 to do... | |
1214 | dcba br0,r6 ; Allocate cache line 4 | |
1215 | ||
1216 | snol4: | |
1217 | la r9,savevr6(r3) ; Point to R6/R7 pair | |
1218 | bf 20,snovr4 ; Do not save VR4... | |
1219 | stvxl v4,br0,r8 ; Save VR4 | |
1220 | ||
1221 | snovr4: | |
1222 | bf 21,snovr5 ; Do not save VR5... | |
1223 | stvxl v5,r11,r8 ; Save VR5 | |
1224 | ||
1225 | snovr5: | |
1226 | mtcrf 0x08,r10 ; Set CRs for registers 16-19 | |
1227 | la r6,savevr12(r3) ; Point to line 6 | |
1228 | bf 10,snol5 ; No line 5 to do... | |
1229 | dcba br0,r7 ; Allocate cache line 5 | |
1230 | ||
1231 | snol5: | |
1232 | la r8,savevr8(r3) ; Point to V8/V9 pair | |
1233 | bf 22,snovr6 ; Do not save VR6... | |
1234 | stvxl v6,br0,r9 ; Save VR6 | |
1235 | ||
1236 | snovr6: | |
1237 | bf 23,snovr7 ; Do not save VR7... | |
1238 | stvxl v7,r11,r9 ; Save VR7 | |
1239 | ||
1240 | snovr7: | |
1241 | ; | |
1242 | ; Note: CR5 is now free | |
1243 | ; | |
1244 | la r7,savevr14(r3) ; Point to line 7 | |
1245 | bf 12,snol6 ; No line 6 to do... | |
1246 | dcba br0,r6 ; Allocate cache line 6 | |
1247 | ||
1248 | snol6: | |
1249 | la r9,savevr10(r3) ; Point to V10/V11 pair | |
1250 | bf 24,snovr8 ; Do not save VR8... | |
1251 | stvxl v8,br0,r8 ; Save VR8 | |
1252 | ||
1253 | snovr8: | |
1254 | bf 25,snovr9 ; Do not save VR9... | |
1255 | stvxl v9,r11,r8 ; Save VR9 | |
1256 | ||
1257 | snovr9: | |
1258 | mtcrf 0x04,r10 ; Set CRs for registers 20-23 | |
1259 | la r6,savevr16(r3) ; Point to line 8 | |
1260 | bf 14,snol7 ; No line 7 to do... | |
1261 | dcba br0,r7 ; Allocate cache line 7 | |
1262 | ||
1263 | snol7: | |
1264 | la r8,savevr12(r3) ; Point to V12/V13 pair | |
1265 | bf 26,snovr10 ; Do not save VR10... | |
1266 | stvxl v10,br0,r9 ; Save VR10 | |
1267 | ||
1268 | snovr10: | |
1269 | bf 27,snovr11 ; Do not save VR11... | |
1270 | stvxl v11,r11,r9 ; Save VR11 | |
1271 | ||
1272 | snovr11: | |
1273 | ||
1274 | ; | |
1275 | ; Note: CR6 is now free | |
1276 | ; | |
1277 | la r7,savevr18(r3) ; Point to line 9 | |
1278 | bf 1,snol8 ; No line 8 to do... | |
1279 | dcba br0,r6 ; Allocate cache line 8 | |
1280 | ||
1281 | snol8: | |
1282 | la r9,savevr14(r3) ; Point to V14/V15 pair | |
1283 | bf 28,snovr12 ; Do not save VR12... | |
1284 | stvxl v12,br0,r8 ; Save VR12 | |
1285 | ||
1286 | snovr12: | |
1287 | bf 29,snovr13 ; Do not save VR13... | |
1288 | stvxl v13,r11,r8 ; Save VR13 | |
1289 | ||
1290 | snovr13: | |
1291 | mtcrf 0x02,r10 ; Set CRs for registers 24-27 | |
1292 | la r6,savevr20(r3) ; Point to line 10 | |
1293 | bf 3,snol9 ; No line 9 to do... | |
1294 | dcba br0,r7 ; Allocate cache line 9 | |
1295 | ||
1296 | snol9: | |
1297 | la r8,savevr16(r3) ; Point to V16/V17 pair | |
1298 | bf 30,snovr14 ; Do not save VR14... | |
1299 | stvxl v14,br0,r9 ; Save VR14 | |
1300 | ||
1301 | snovr14: | |
1302 | bf 31,snovr15 ; Do not save VR15... | |
1303 | stvxl v15,r11,r9 ; Save VR15 | |
1304 | ||
1305 | snovr15: | |
1306 | ; | |
1307 | ; Note: CR7 is now free | |
1308 | ; | |
1309 | la r7,savevr22(r3) ; Point to line 11 | |
1310 | bf 5,snol10 ; No line 10 to do... | |
1311 | dcba br0,r6 ; Allocate cache line 10 | |
1312 | ||
1313 | snol10: | |
1314 | la r9,savevr18(r3) ; Point to V18/V19 pair | |
1315 | bf 16,snovr16 ; Do not save VR16... | |
1316 | stvxl v16,br0,r8 ; Save VR16 | |
1317 | ||
1318 | snovr16: | |
1319 | bf 17,snovr17 ; Do not save VR17... | |
1320 | stvxl v17,r11,r8 ; Save VR17 | |
1321 | ||
1322 | snovr17: | |
1323 | mtcrf 0x01,r10 ; Set CRs for registers 28-31 | |
1324 | ; | |
1325 | ; Note: All registers have been or are accounted for in CRs | |
1326 | ; | |
1327 | la r6,savevr24(r3) ; Point to line 12 | |
1328 | bf 7,snol11 ; No line 11 to do... | |
1329 | dcba br0,r7 ; Allocate cache line 11 | |
1330 | ||
1331 | snol11: | |
1332 | la r8,savevr20(r3) ; Point to V20/V21 pair | |
1333 | bf 18,snovr18 ; Do not save VR18... | |
1334 | stvxl v18,br0,r9 ; Save VR18 | |
1335 | ||
1336 | snovr18: | |
1337 | bf 19,snovr19 ; Do not save VR19... | |
1338 | stvxl v19,r11,r9 ; Save VR19 | |
1339 | ||
1340 | snovr19: | |
1341 | la r7,savevr26(r3) ; Point to line 13 | |
1342 | bf 9,snol12 ; No line 12 to do... | |
1343 | dcba br0,r6 ; Allocate cache line 12 | |
1344 | ||
1345 | snol12: | |
1346 | la r9,savevr22(r3) ; Point to V22/V23 pair | |
1347 | bf 20,snovr20 ; Do not save VR20... | |
1348 | stvxl v20,br0,r8 ; Save VR20 | |
1349 | ||
1350 | snovr20: | |
1351 | bf 21,snovr21 ; Do not save VR21... | |
1352 | stvxl v21,r11,r8 ; Save VR21 | |
1353 | ||
1354 | snovr21: | |
1355 | la r6,savevr28(r3) ; Point to line 14 | |
1356 | bf 11,snol13 ; No line 13 to do... | |
1357 | dcba br0,r7 ; Allocate cache line 13 | |
1358 | ||
1359 | snol13: | |
1360 | la r8,savevr24(r3) ; Point to V24/V25 pair | |
1361 | bf 22,snovr22 ; Do not save VR22... | |
1362 | stvxl v22,br0,r9 ; Save VR22 | |
1363 | ||
1364 | snovr22: | |
1365 | bf 23,snovr23 ; Do not save VR23... | |
1366 | stvxl v23,r11,r9 ; Save VR23 | |
1367 | ||
1368 | snovr23: | |
1369 | la r7,savevr30(r3) ; Point to line 15 | |
1370 | bf 13,snol14 ; No line 14 to do... | |
1371 | dcba br0,r6 ; Allocate cache line 14 | |
1372 | ||
1373 | snol14: | |
1374 | la r9,savevr26(r3) ; Point to V26/V27 pair | |
1375 | bf 24,snovr24 ; Do not save VR24... | |
1376 | stvxl v24,br0,r8 ; Save VR24 | |
1377 | ||
1378 | snovr24: | |
1379 | bf 25,snovr25 ; Do not save VR25... | |
1380 | stvxl v25,r11,r8 ; Save VR25 | |
1381 | ||
1382 | snovr25: | |
1383 | bf 15,snol15 ; No line 15 to do... | |
1384 | dcba br0,r7 ; Allocate cache line 15 | |
1385 | ||
1386 | snol15: | |
1387 | ; | |
1388 | ; Note: All cache lines allocated now | |
1389 | ; | |
1390 | la r8,savevr28(r3) ; Point to V28/V29 pair | |
1391 | bf 26,snovr26 ; Do not save VR26... | |
1392 | stvxl v26,br0,r9 ; Save VR26 | |
1393 | ||
1394 | snovr26: | |
1395 | bf 27,snovr27 ; Do not save VR27... | |
1396 | stvxl v27,r11,r9 ; Save VR27 | |
1397 | ||
1398 | snovr27: | |
1399 | la r7,savevr30(r3) ; Point to V30/V31 pair | |
1400 | bf 28,snovr28 ; Do not save VR28... | |
1401 | stvxl v28,br0,r8 ; Save VR28 | |
1402 | ||
1403 | snovr28: | |
1404 | bf 29,snovr29 ; Do not save VR29... | |
1405 | stvxl v29,r11,r8 ; Save VR29 | |
1406 | ||
1407 | snovr29: | |
1c79356b A |
1408 | bf 30,snovr30 ; Do not save VR30... |
1409 | stvxl v30,br0,r7 ; Save VR30 | |
1410 | ||
1411 | snovr30: | |
1c79356b A |
1412 | bf 31,snovr31 ; Do not save VR31... |
1413 | stvxl v31,r11,r7 ; Save VR31 | |
1414 | ||
1415 | snovr31: | |
9bccf70c | 1416 | mtcrf 255,r2 ; Restore all cr |
1c79356b | 1417 | |
9bccf70c | 1418 | vsret: mtmsr r0 ; Put interrupts on if they were and vector off |
1c79356b A |
1419 | isync |
1420 | ||
1421 | blr | |
1422 | ||
1423 | /* | |
1424 | * vec_switch() | |
1425 | * | |
1426 | * Entered to handle the vector unavailable exception and | |
1427 | * switch vector context | |
1428 | * | |
1429 | * This code is run with virtual address mode on and interrupts off. | |
1430 | * | |
1431 | * Upon exit, the code returns to the users context with the vector | |
1432 | * facility turned on. | |
1433 | * | |
1434 | * ENTRY: VM switched ON | |
1435 | * Interrupts OFF | |
1436 | * State is saved in savearea pointed to by R4. | |
1437 | * All other registers are free. | |
1438 | * | |
1439 | */ | |
1440 | ||
9bccf70c A |
1441 | .align 5 |
1442 | .globl EXT(vec_switch) | |
1443 | ||
1444 | LEXT(vec_switch) | |
1c79356b A |
1445 | |
1446 | #if DEBUG | |
1c79356b A |
1447 | lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter |
1448 | ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter | |
1449 | lwz r1,0(r3) | |
1450 | addi r1,r1,1 | |
1451 | stw r1,0(r3) | |
1c79356b A |
1452 | #endif /* DEBUG */ |
1453 | ||
9bccf70c A |
1454 | mfsprg r26,0 ; Get the per_processor block |
1455 | mfmsr r19 ; Get the current MSR | |
1c79356b | 1456 | |
9bccf70c A |
1457 | mr r25,r4 ; Save the entry savearea |
1458 | lwz r22,VMXowner(r26) ; Get the thread that owns the vector | |
1459 | lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread | |
1460 | oris r19,r19,hi16(MASK(MSR_VEC)) ; Enable the vector feature | |
1461 | lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running | |
1462 | ||
1463 | mtmsr r19 ; Enable vector instructions | |
1c79356b A |
1464 | isync |
1465 | ||
9bccf70c A |
1466 | lwz r27,ACT_MACT_PCB(r17) ; Get the current level |
1467 | lwz r29,curctx(r17) ; Grab the current context anchor of the current thread | |
0b4e3aa0 | 1468 | |
9bccf70c A |
1469 | ; R22 has the "old" context anchor |
1470 | ; R29 has the "new" context anchor | |
0b4e3aa0 | 1471 | |
1c79356b | 1472 | #if FPVECDBG |
9bccf70c A |
1473 | lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) |
1474 | li r2,0x5F01 ; (TEST/DEBUG) | |
1475 | mr r3,r22 ; (TEST/DEBUG) | |
1476 | mr r5,r29 ; (TEST/DEBUG) | |
1477 | oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) | |
1478 | sc ; (TEST/DEBUG) | |
1c79356b A |
1479 | #endif |
1480 | ||
9bccf70c | 1481 | lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number |
1c79356b | 1482 | |
9bccf70c | 1483 | vsvretry: mr. r22,r22 ; See if there is any live vector status |
1c79356b | 1484 | |
9bccf70c | 1485 | beq- vsnosave ; No live context, so nothing to save... |
1c79356b | 1486 | |
9bccf70c | 1487 | isync ; Make sure we see this in the right order |
1c79356b | 1488 | |
9bccf70c A |
1489 | lwz r30,VMXsave(r22) ; Get the top savearea |
1490 | cmplw cr2,r22,r29 ; Are both old and new the same context? | |
1491 | lwz r18,VMXcpu(r22) ; Get the last CPU we ran on | |
1492 | cmplwi cr1,r30,0 ; Anything saved yet? | |
1493 | cmplw r18,r16 ; Make sure we are on the right processor | |
1494 | lwz r31,VMXlevel(r22) ; Get the context level | |
1c79356b | 1495 | |
9bccf70c A |
1496 | lwz r10,liveVRS(r26) ; Get the right VRSave register |
1497 | ||
1498 | bne- vsnosave ; No, not on the same processor... | |
1499 | ||
1c79356b | 1500 | ; |
9bccf70c A |
1501 | ; Check to see if the live context has already been saved. |
1502 | ; Also check to see if all we are here just to re-enable the MSR | |
1503 | ; and handle specially if so. | |
1c79356b | 1504 | ; |
9bccf70c A |
1505 | |
1506 | cmplw r31,r27 ; See if the current and active levels are the same | |
1507 | crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same | |
1508 | li r8,0 ; Clear this | |
1c79356b | 1509 | |
9bccf70c A |
1510 | beq- vsthesame ; New and old are the same, just go enable... |
1511 | ||
1512 | cmplwi cr2,r10,0 ; Check VRSave to see if we really need to save anything... | |
1513 | beq- cr1,vsmstsave ; Not saved yet, go do it... | |
1c79356b | 1514 | |
9bccf70c | 1515 | lwz r11,SAVlevel(r30) ; Get the level of top saved context |
1c79356b | 1516 | |
9bccf70c A |
1517 | cmplw r31,r11 ; Are live and saved the same? |
1518 | ||
1c79356b | 1519 | #if FPVECDBG |
9bccf70c A |
1520 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
1521 | li r2,0x5F02 ; (TEST/DEBUG) | |
1522 | mr r3,r30 ; (TEST/DEBUG) | |
1523 | mr r5,r31 ; (TEST/DEBUG) | |
1524 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1525 | sc ; (TEST/DEBUG) | |
1c79356b | 1526 | #endif |
9bccf70c A |
1527 | |
1528 | bne- vsmstsave ; Live context has not been saved yet... | |
1529 | ||
1530 | bne- cr2,vsnosave ; Live context saved and VRSave not 0, no save and keep context... | |
1c79356b | 1531 | |
9bccf70c A |
1532 | lwz r4,SAVprev(r30) ; Pick up the previous area |
1533 | li r5,0 ; Assume this is the only one (which should be the ususal case) | |
1534 | mr. r4,r4 ; Was this the only one? | |
1535 | stw r4,VMXsave(r22) ; Dequeue this savearea | |
1536 | beq+ vsonlyone ; This was the only one... | |
1537 | lwz r5,SAVlevel(r4) ; Get the level associated with previous save | |
1538 | ||
1539 | vsonlyone: stw r5,VMXlevel(r22) ; Save the level | |
1540 | stw r8,VMXowner(r26) ; Clear owner | |
1541 | eieio | |
1542 | mr r3,r30 ; Copy the savearea we are tossing | |
1543 | bl EXT(save_ret) ; Toss the savearea | |
1544 | b vsnosave ; Go load up the context... | |
1545 | ||
1546 | .align 5 | |
1c79356b | 1547 | |
9bccf70c A |
1548 | |
1549 | vsmstsave: stw r8,VMXowner(r26) ; Clear owner | |
1550 | eieio | |
1551 | beq- cr2,vsnosave ; The VRSave was 0, so there is nothing to save... | |
1552 | ||
1553 | bl EXT(save_get) ; Go get a savearea | |
1554 | ||
1555 | lwz r12,facAct(r22) ; Get the activation associated with the context | |
1556 | stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread | |
1557 | ||
1558 | stw r30,SAVprev(r3) ; Point us to the old context | |
1559 | stw r31,SAVlevel(r3) ; Tag our level | |
1560 | li r7,SAVvector ; Get the vector ID | |
1561 | stw r12,SAVact(r3) ; Make sure we point to the right guy | |
1562 | stb r7,SAVflags+2(r3) ; Set that we have a vector save area | |
1c79356b | 1563 | |
1c79356b | 1564 | #if FPVECDBG |
9bccf70c A |
1565 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
1566 | li r2,0x5F03 ; (TEST/DEBUG) | |
1567 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1568 | sc ; (TEST/DEBUG) | |
1c79356b A |
1569 | #endif |
1570 | ||
9bccf70c A |
1571 | lwz r10,liveVRS(r26) ; Get the right VRSave register |
1572 | lis r9,0x5555 ; Mask with odd bits set | |
1573 | rlwinm r11,r10,1,0,31 ; Shift over 1 | |
1574 | ori r9,r9,0x5555 ; Finish mask | |
1575 | or r21,r10,r11 ; After this, even bits show which lines to zap | |
1576 | ||
1577 | andc r13,r21,r9 ; Clear out odd bits | |
1578 | ||
1579 | la r11,savevr0(r3) ; Point to line 0 | |
1580 | rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits | |
1581 | or r24,r13,r24 ; Set the odd bits | |
1582 | ; (bit 0 is line 0, bit 1 is line 8, | |
1583 | ; bit 2 is line 1, bit 3 is line 9, etc. | |
1584 | rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31 | |
1585 | la r21,savevr2(r3) ; Point to line 1 | |
1586 | mtcrf 255,r24 ; Load up the CRs | |
1587 | stw r10,savevrvalid(r3) ; Save the validity information | |
1588 | mr r12,r11 ; Start registers off | |
1c79356b A |
1589 | ; |
1590 | ; Save the current vector state | |
1591 | ; | |
1592 | ||
9bccf70c A |
1593 | bf 0,nol0 ; No line 0 to do... |
1594 | dcba br0,r11 ; Allocate cache line 0 | |
1c79356b A |
1595 | |
1596 | nol0: | |
9bccf70c A |
1597 | la r11,savevr4(r3) ; Point to line 2 |
1598 | bf 2,nol1 ; No line 1 to do... | |
1599 | dcba br0,r21 ; Allocate cache line 1 | |
1c79356b A |
1600 | |
1601 | nol1: | |
9bccf70c A |
1602 | la r21,savevr6(r3) ; Point to line 3 |
1603 | bf 4,nol2 ; No line 2 to do... | |
1604 | dcba br0,r11 ; Allocate cache line 2 | |
1c79356b A |
1605 | |
1606 | nol2: | |
9bccf70c A |
1607 | li r14,16 ; Get offset for odd registers |
1608 | bf 16,novr0 ; Do not save VR0... | |
1609 | stvxl v0,br0,r12 ; Save VR0 | |
1c79356b A |
1610 | |
1611 | novr0: | |
9bccf70c A |
1612 | la r13,savevr2(r3) ; Point to V2/V3 pair |
1613 | bf 17,novr1 ; Do not save VR1... | |
1614 | stvxl v1,r14,r12 ; Save VR1 | |
1c79356b A |
1615 | |
1616 | novr1: | |
9bccf70c A |
1617 | la r11,savevr8(r3) ; Point to line 4 |
1618 | bf 6,nol3 ; No line 3 to do... | |
1619 | dcba br0,r21 ; Allocate cache line 3 | |
1c79356b A |
1620 | |
1621 | nol3: | |
9bccf70c A |
1622 | la r12,savevr4(r3) ; Point to V4/V5 pair |
1623 | bf 18,novr2 ; Do not save VR2... | |
1624 | stvxl v2,br0,r13 ; Save VR2 | |
1c79356b A |
1625 | |
1626 | novr2: | |
9bccf70c A |
1627 | bf 19,novr3 ; Do not save VR3... |
1628 | stvxl v3,r14,r13 ; Save VR3 | |
1c79356b A |
1629 | |
1630 | novr3: | |
1631 | ; | |
1632 | ; Note: CR4 is now free | |
1633 | ; | |
9bccf70c A |
1634 | la r21,savevr10(r3) ; Point to line 5 |
1635 | bf 8,nol4 ; No line 4 to do... | |
1636 | dcba br0,r11 ; Allocate cache line 4 | |
1c79356b A |
1637 | |
1638 | nol4: | |
9bccf70c A |
1639 | la r13,savevr6(r3) ; Point to R6/R7 pair |
1640 | bf 20,novr4 ; Do not save VR4... | |
1641 | stvxl v4,br0,r12 ; Save VR4 | |
1c79356b A |
1642 | |
1643 | novr4: | |
9bccf70c A |
1644 | bf 21,novr5 ; Do not save VR5... |
1645 | stvxl v5,r14,r12 ; Save VR5 | |
1c79356b A |
1646 | |
1647 | novr5: | |
9bccf70c A |
1648 | mtcrf 0x08,r10 ; Set CRs for registers 16-19 |
1649 | la r11,savevr12(r3) ; Point to line 6 | |
1650 | bf 10,nol5 ; No line 5 to do... | |
1651 | dcba br0,r21 ; Allocate cache line 5 | |
1c79356b A |
1652 | |
1653 | nol5: | |
9bccf70c A |
1654 | la r12,savevr8(r3) ; Point to V8/V9 pair |
1655 | bf 22,novr6 ; Do not save VR6... | |
1656 | stvxl v6,br0,r13 ; Save VR6 | |
1c79356b A |
1657 | |
1658 | novr6: | |
9bccf70c A |
1659 | bf 23,novr7 ; Do not save VR7... |
1660 | stvxl v7,r14,r13 ; Save VR7 | |
1c79356b A |
1661 | |
1662 | novr7: | |
1663 | ; | |
1664 | ; Note: CR5 is now free | |
1665 | ; | |
9bccf70c A |
1666 | la r21,savevr14(r3) ; Point to line 7 |
1667 | bf 12,nol6 ; No line 6 to do... | |
1668 | dcba br0,r11 ; Allocate cache line 6 | |
1c79356b A |
1669 | |
1670 | nol6: | |
9bccf70c A |
1671 | la r13,savevr10(r3) ; Point to V10/V11 pair |
1672 | bf 24,novr8 ; Do not save VR8... | |
1673 | stvxl v8,br0,r12 ; Save VR8 | |
1c79356b A |
1674 | |
1675 | novr8: | |
9bccf70c A |
1676 | bf 25,novr9 ; Do not save VR9... |
1677 | stvxl v9,r14,r12 ; Save VR9 | |
1c79356b A |
1678 | |
1679 | novr9: | |
9bccf70c A |
1680 | mtcrf 0x04,r10 ; Set CRs for registers 20-23 |
1681 | la r11,savevr16(r3) ; Point to line 8 | |
1682 | bf 14,nol7 ; No line 7 to do... | |
1683 | dcba br0,r21 ; Allocate cache line 7 | |
1c79356b A |
1684 | |
1685 | nol7: | |
9bccf70c A |
1686 | la r12,savevr12(r3) ; Point to V12/V13 pair |
1687 | bf 26,novr10 ; Do not save VR10... | |
1688 | stvxl v10,br0,r13 ; Save VR10 | |
1c79356b A |
1689 | |
1690 | novr10: | |
9bccf70c A |
1691 | bf 27,novr11 ; Do not save VR11... |
1692 | stvxl v11,r14,r13 ; Save VR11 | |
1c79356b A |
1693 | |
1694 | novr11: | |
1695 | ||
1696 | ; | |
1697 | ; Note: CR6 is now free | |
1698 | ; | |
9bccf70c A |
1699 | la r21,savevr18(r3) ; Point to line 9 |
1700 | bf 1,nol8 ; No line 8 to do... | |
1701 | dcba br0,r11 ; Allocate cache line 8 | |
1c79356b A |
1702 | |
1703 | nol8: | |
9bccf70c A |
1704 | la r13,savevr14(r3) ; Point to V14/V15 pair |
1705 | bf 28,novr12 ; Do not save VR12... | |
1706 | stvxl v12,br0,r12 ; Save VR12 | |
1c79356b A |
1707 | |
1708 | novr12: | |
9bccf70c A |
1709 | bf 29,novr13 ; Do not save VR13... |
1710 | stvxl v13,r14,r12 ; Save VR13 | |
1c79356b A |
1711 | |
1712 | novr13: | |
9bccf70c A |
1713 | mtcrf 0x02,r10 ; Set CRs for registers 24-27 |
1714 | la r11,savevr20(r3) ; Point to line 10 | |
1715 | bf 3,nol9 ; No line 9 to do... | |
1716 | dcba br0,r21 ; Allocate cache line 9 | |
1c79356b A |
1717 | |
1718 | nol9: | |
9bccf70c A |
1719 | la r12,savevr16(r3) ; Point to V16/V17 pair |
1720 | bf 30,novr14 ; Do not save VR14... | |
1721 | stvxl v14,br0,r13 ; Save VR14 | |
1c79356b A |
1722 | |
1723 | novr14: | |
9bccf70c A |
1724 | bf 31,novr15 ; Do not save VR15... |
1725 | stvxl v15,r14,r13 ; Save VR15 | |
1c79356b A |
1726 | |
1727 | novr15: | |
1728 | ; | |
1729 | ; Note: CR7 is now free | |
1730 | ; | |
9bccf70c A |
1731 | la r21,savevr22(r3) ; Point to line 11 |
1732 | bf 5,nol10 ; No line 10 to do... | |
1733 | dcba br0,r11 ; Allocate cache line 10 | |
1c79356b A |
1734 | |
1735 | nol10: | |
9bccf70c A |
1736 | la r13,savevr18(r3) ; Point to V18/V19 pair |
1737 | bf 16,novr16 ; Do not save VR16... | |
1738 | stvxl v16,br0,r12 ; Save VR16 | |
1c79356b A |
1739 | |
1740 | novr16: | |
9bccf70c A |
1741 | bf 17,novr17 ; Do not save VR17... |
1742 | stvxl v17,r14,r12 ; Save VR17 | |
1c79356b A |
1743 | |
1744 | novr17: | |
9bccf70c | 1745 | mtcrf 0x01,r10 ; Set CRs for registers 28-31 |
1c79356b A |
1746 | ; |
1747 | ; Note: All registers have been or are accounted for in CRs | |
1748 | ; | |
9bccf70c A |
1749 | la r11,savevr24(r3) ; Point to line 12 |
1750 | bf 7,nol11 ; No line 11 to do... | |
1751 | dcba br0,r21 ; Allocate cache line 11 | |
1c79356b A |
1752 | |
1753 | nol11: | |
9bccf70c A |
1754 | la r12,savevr20(r3) ; Point to V20/V21 pair |
1755 | bf 18,novr18 ; Do not save VR18... | |
1756 | stvxl v18,br0,r13 ; Save VR18 | |
1c79356b A |
1757 | |
1758 | novr18: | |
9bccf70c A |
1759 | bf 19,novr19 ; Do not save VR19... |
1760 | stvxl v19,r14,r13 ; Save VR19 | |
1c79356b A |
1761 | |
1762 | novr19: | |
9bccf70c A |
1763 | la r21,savevr26(r3) ; Point to line 13 |
1764 | bf 9,nol12 ; No line 12 to do... | |
1765 | dcba br0,r11 ; Allocate cache line 12 | |
1c79356b A |
1766 | |
1767 | nol12: | |
9bccf70c A |
1768 | la r13,savevr22(r3) ; Point to V22/V23 pair |
1769 | bf 20,novr20 ; Do not save VR20... | |
1770 | stvxl v20,br0,r12 ; Save VR20 | |
1c79356b A |
1771 | |
1772 | novr20: | |
9bccf70c A |
1773 | bf 21,novr21 ; Do not save VR21... |
1774 | stvxl v21,r14,r12 ; Save VR21 | |
1c79356b A |
1775 | |
1776 | novr21: | |
9bccf70c A |
1777 | la r11,savevr28(r3) ; Point to line 14 |
1778 | bf 11,nol13 ; No line 13 to do... | |
1779 | dcba br0,r21 ; Allocate cache line 13 | |
1c79356b A |
1780 | |
1781 | nol13: | |
9bccf70c A |
1782 | la r12,savevr24(r3) ; Point to V24/V25 pair |
1783 | bf 22,novr22 ; Do not save VR22... | |
1784 | stvxl v22,br0,r13 ; Save VR22 | |
1c79356b A |
1785 | |
1786 | novr22: | |
9bccf70c A |
1787 | bf 23,novr23 ; Do not save VR23... |
1788 | stvxl v23,r14,r13 ; Save VR23 | |
1c79356b A |
1789 | |
1790 | novr23: | |
9bccf70c A |
1791 | la r21,savevr30(r3) ; Point to line 15 |
1792 | bf 13,nol14 ; No line 14 to do... | |
1793 | dcba br0,r11 ; Allocate cache line 14 | |
1c79356b A |
1794 | |
1795 | nol14: | |
9bccf70c A |
1796 | la r13,savevr26(r3) ; Point to V26/V27 pair |
1797 | bf 24,novr24 ; Do not save VR24... | |
1798 | stvxl v24,br0,r12 ; Save VR24 | |
1c79356b A |
1799 | |
1800 | novr24: | |
9bccf70c A |
1801 | bf 25,novr25 ; Do not save VR25... |
1802 | stvxl v25,r14,r12 ; Save VR25 | |
1c79356b A |
1803 | |
1804 | novr25: | |
9bccf70c A |
1805 | bf 15,nol15 ; No line 15 to do... |
1806 | dcba br0,r21 ; Allocate cache line 15 | |
1c79356b A |
1807 | |
1808 | nol15: | |
1809 | ; | |
1810 | ; Note: All cache lines allocated now | |
1811 | ; | |
9bccf70c A |
1812 | la r12,savevr28(r3) ; Point to V28/V29 pair |
1813 | bf 26,novr26 ; Do not save VR26... | |
1814 | stvxl v26,br0,r13 ; Save VR26 | |
1c79356b A |
1815 | |
1816 | novr26: | |
9bccf70c A |
1817 | bf 27,novr27 ; Do not save VR27... |
1818 | stvxl v27,r14,r13 ; Save VR27 | |
1c79356b A |
1819 | |
1820 | novr27: | |
9bccf70c A |
1821 | la r13,savevr30(r3) ; Point to V30/V31 pair |
1822 | bf 28,novr28 ; Do not save VR28... | |
1823 | stvxl v28,br0,r12 ; Save VR28 | |
1c79356b A |
1824 | |
1825 | novr28: | |
9bccf70c A |
1826 | bf 29,novr29 ; Do not save VR29... |
1827 | stvxl v29,r14,r12 ; Save VR29 | |
1c79356b A |
1828 | |
1829 | novr29: | |
9bccf70c A |
1830 | bf 30,novr30 ; Do not save VR30... |
1831 | stvxl v30,br0,r13 ; Save VR30 | |
1c79356b A |
1832 | |
1833 | novr30: | |
9bccf70c A |
1834 | bf 31,novr31 ; Do not save VR31... |
1835 | stvxl v31,r14,r13 ; Save VR31 | |
1c79356b A |
1836 | |
1837 | novr31: | |
1c79356b A |
1838 | |
1839 | ||
1840 | ||
9bccf70c A |
1841 | ; |
1842 | ; The context is all saved now and the facility is free. | |
1843 | ; | |
1844 | ; If we do not we need to fill the registers with junk, because this level has | |
1845 | ; never used them before and some thieving bastard could hack the old values | |
1846 | ; of some thread! Just imagine what would happen if they could! Why, nothing | |
1847 | ; would be safe! My God! It is terrifying! | |
1848 | ; | |
1849 | ; Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian) | |
1850 | ; constant that we may need to fill unused vector registers. | |
1851 | ; | |
1c79356b | 1852 | |
0b4e3aa0 A |
1853 | |
1854 | ||
0b4e3aa0 | 1855 | |
9bccf70c A |
1856 | vsnosave: vspltisb v31,-10 ; Get 0xF6F6F6F6 |
1857 | lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one | |
1858 | vspltisb v30,5 ; Get 0x05050505 | |
1859 | lwz r19,VMXcpu(r29) ; Get the last CPU we ran on | |
1860 | vspltish v29,4 ; Get 0x00040004 | |
1861 | lwz r14,VMXsave(r29) ; Point to the top of the "new" context stack | |
1862 | vrlb v31,v31,v30 ; Get 0xDEDEDEDE | |
1863 | ||
1864 | stw r16,VMXcpu(r29) ; Claim context for us | |
1865 | eieio | |
1c79356b A |
1866 | |
1867 | #if FPVECDBG | |
9bccf70c A |
1868 | lwz r13,VMXlevel(r29) ; (TEST/DEBUG) |
1869 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
1870 | li r2,0x5F04 ; (TEST/DEBUG) | |
1871 | mr r1,r15 ; (TEST/DEBUG) | |
1872 | mr r3,r14 ; (TEST/DEBUG) | |
1873 | mr r5,r13 ; (TEST/DEBUG) | |
1874 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1875 | sc ; (TEST/DEBUG) | |
1c79356b | 1876 | #endif |
9bccf70c A |
1877 | |
1878 | lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc | |
1879 | vspltisb v28,-2 ; Get 0xFEFEFEFE | |
1880 | mulli r19,r19,ppSize ; Find offset to the owner per_proc | |
1881 | vsubuhm v31,v31,v29 ; Get 0xDEDADEDA | |
1882 | ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc | |
1883 | vpkpx v30,v28,v3 ; Get 0x7FFF7FFF | |
1884 | li r16,VMXowner ; Displacement to vector owner | |
1885 | add r19,r18,r19 ; Point to the owner per_proc | |
1886 | vrlb v31,v31,v29 ; Get 0xDEADDEAD | |
1887 | li r0,0 | |
1888 | ||
1889 | vsinvothr: lwarx r18,r16,r19 ; Get the owner | |
1890 | cmplw r18,r29 ; Does he still have this context? | |
1891 | bne vsinvoths ; Nope... | |
1892 | stwcx. r0,r16,r19 ; Try to invalidate it | |
1893 | bne- vsinvothr ; Try again if there was a collision... | |
1894 | ||
1895 | ||
1896 | vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load? | |
1897 | vmrghh v31,v30,v31 ; Get 0x7FFFDEAD. V31 keeps this value until the bitter end | |
1898 | stw r15,VMXlevel(r29) ; Set the "new" active level | |
1899 | eieio | |
1900 | stw r29,VMXowner(r26) ; Mark us as having the live context | |
1c79356b | 1901 | |
9bccf70c A |
1902 | beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use... |
1903 | ||
1904 | lwz r3,SAVprev(r14) ; Get the previous context | |
1905 | lwz r0,SAVlevel(r14) ; Get the level of first facility savearea | |
1906 | cmplw r0,r15 ; Top level correct to load? | |
1907 | bne- ProtectTheAmericanWay ; No, go initialize... | |
1c79356b | 1908 | |
9bccf70c A |
1909 | stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later) |
1910 | ||
1c79356b | 1911 | #if FPVECDBG |
9bccf70c A |
1912 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
1913 | li r2,0x5F05 ; (TEST/DEBUG) | |
1914 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
1915 | sc ; (TEST/DEBUG) | |
1c79356b A |
1916 | #endif |
1917 | ||
9bccf70c A |
1918 | lwz r22,savevrsave(r25) ; Get the most current VRSAVE |
1919 | lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea | |
1920 | lis r9,0x5555 ; Mask with odd bits set | |
1921 | and r10,r10,r22 ; Figure out just what registers need to be loaded | |
1922 | ori r9,r9,0x5555 ; Finish mask | |
1923 | rlwinm r11,r10,1,0,31 ; Shift over 1 | |
1924 | or r12,r10,r11 ; After this, even bits show which lines to touch | |
1925 | andc r13,r12,r9 ; Clear out odd bits | |
1926 | ||
1927 | la r20,savevr0(r14) ; Point to line 0 | |
1928 | rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits | |
1929 | la r21,savevr2(r3) ; Point to line 1 | |
1930 | or r3,r13,r3 ; Set the odd bits | |
1931 | ; (bit 0 is line 0, bit 1 is line 8, | |
1932 | ; bit 2 is line 1, bit 3 is line 9, etc. | |
1933 | rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31 | |
1934 | mtcrf 255,r3 ; Load up the CRs | |
1935 | mr r22,r20 ; Start registers off | |
1c79356b A |
1936 | ; |
1937 | ; Load the new vector state | |
1938 | ; | |
1939 | ||
9bccf70c A |
1940 | bf 0,lnol0 ; No line 0 to do... |
1941 | dcbt br0,r20 ; Touch cache line 0 | |
1c79356b A |
1942 | |
1943 | lnol0: | |
9bccf70c A |
1944 | la r20,savevr4(r14) ; Point to line 2 |
1945 | bf 2,lnol1 ; No line 1 to do... | |
1946 | dcbt br0,r21 ; Touch cache line 1 | |
1c79356b A |
1947 | |
1948 | lnol1: | |
9bccf70c A |
1949 | la r21,savevr6(r14) ; Point to line 3 |
1950 | bf 4,lnol2 ; No line 2 to do... | |
1951 | dcbt br0,r20 ; Touch cache line 2 | |
1c79356b A |
1952 | |
1953 | lnol2: | |
9bccf70c A |
1954 | li r30,16 ; Get offset for odd registers |
1955 | bf 16,lnovr0 ; Do not restore VR0... | |
1956 | lvxl v0,br0,r22 ; Restore VR0 | |
1c79356b A |
1957 | |
1958 | lnovr0: | |
9bccf70c A |
1959 | la r23,savevr2(r14) ; Point to V2/V3 pair |
1960 | bf 17,lnovr1 ; Do not restore VR1... | |
1961 | lvxl v1,r30,r22 ; Restore VR1 | |
1c79356b A |
1962 | |
1963 | lnovr1: | |
9bccf70c A |
1964 | la r20,savevr8(r14) ; Point to line 4 |
1965 | bf 6,lnol3 ; No line 3 to do... | |
1966 | dcbt br0,r21 ; Touch cache line 3 | |
1c79356b A |
1967 | |
1968 | lnol3: | |
9bccf70c A |
1969 | la r22,savevr4(r14) ; Point to V4/V5 pair |
1970 | bf 18,lnovr2 ; Do not restore VR2... | |
1971 | lvxl v2,br0,r23 ; Restore VR2 | |
1c79356b A |
1972 | |
1973 | lnovr2: | |
9bccf70c A |
1974 | bf 19,lnovr3 ; Do not restore VR3... |
1975 | lvxl v3,r30,r23 ; Restore VR3 | |
1c79356b A |
1976 | |
1977 | lnovr3: | |
1978 | ; | |
1979 | ; Note: CR4 is now free | |
1980 | ; | |
9bccf70c A |
1981 | la r21,savevr10(r14) ; Point to line 5 |
1982 | bf 8,lnol4 ; No line 4 to do... | |
1983 | dcbt br0,r20 ; Touch cache line 4 | |
1c79356b A |
1984 | |
1985 | lnol4: | |
9bccf70c A |
1986 | la r23,savevr6(r14) ; Point to R6/R7 pair |
1987 | bf 20,lnovr4 ; Do not restore VR4... | |
1988 | lvxl v4,br0,r22 ; Restore VR4 | |
1c79356b A |
1989 | |
1990 | lnovr4: | |
9bccf70c A |
1991 | bf 21,lnovr5 ; Do not restore VR5... |
1992 | lvxl v5,r30,r22 ; Restore VR5 | |
1c79356b A |
1993 | |
1994 | lnovr5: | |
9bccf70c A |
1995 | mtcrf 0x08,r10 ; Set CRs for registers 16-19 |
1996 | la r20,savevr12(r14) ; Point to line 6 | |
1997 | bf 10,lnol5 ; No line 5 to do... | |
1998 | dcbt br0,r21 ; Touch cache line 5 | |
1c79356b A |
1999 | |
2000 | lnol5: | |
9bccf70c A |
2001 | la r22,savevr8(r14) ; Point to V8/V9 pair |
2002 | bf 22,lnovr6 ; Do not restore VR6... | |
2003 | lvxl v6,br0,r23 ; Restore VR6 | |
1c79356b A |
2004 | |
2005 | lnovr6: | |
9bccf70c A |
2006 | bf 23,lnovr7 ; Do not restore VR7... |
2007 | lvxl v7,r30,r23 ; Restore VR7 | |
1c79356b A |
2008 | |
2009 | lnovr7: | |
2010 | ; | |
2011 | ; Note: CR5 is now free | |
2012 | ; | |
9bccf70c A |
2013 | la r21,savevr14(r14) ; Point to line 7 |
2014 | bf 12,lnol6 ; No line 6 to do... | |
2015 | dcbt br0,r20 ; Touch cache line 6 | |
1c79356b A |
2016 | |
2017 | lnol6: | |
9bccf70c A |
2018 | la r23,savevr10(r14) ; Point to V10/V11 pair |
2019 | bf 24,lnovr8 ; Do not restore VR8... | |
2020 | lvxl v8,br0,r22 ; Restore VR8 | |
1c79356b A |
2021 | |
2022 | lnovr8: | |
9bccf70c A |
2023 | bf 25,lnovr9 ; Do not save VR9... |
2024 | lvxl v9,r30,r22 ; Restore VR9 | |
1c79356b A |
2025 | |
2026 | lnovr9: | |
9bccf70c A |
2027 | mtcrf 0x04,r10 ; Set CRs for registers 20-23 |
2028 | la r20,savevr16(r14) ; Point to line 8 | |
2029 | bf 14,lnol7 ; No line 7 to do... | |
2030 | dcbt br0,r21 ; Touch cache line 7 | |
1c79356b A |
2031 | |
2032 | lnol7: | |
9bccf70c A |
2033 | la r22,savevr12(r14) ; Point to V12/V13 pair |
2034 | bf 26,lnovr10 ; Do not restore VR10... | |
2035 | lvxl v10,br0,r23 ; Restore VR10 | |
1c79356b A |
2036 | |
2037 | lnovr10: | |
9bccf70c A |
2038 | bf 27,lnovr11 ; Do not restore VR11... |
2039 | lvxl v11,r30,r23 ; Restore VR11 | |
1c79356b A |
2040 | |
2041 | lnovr11: | |
2042 | ||
2043 | ; | |
2044 | ; Note: CR6 is now free | |
2045 | ; | |
9bccf70c A |
2046 | la r21,savevr18(r14) ; Point to line 9 |
2047 | bf 1,lnol8 ; No line 8 to do... | |
2048 | dcbt br0,r20 ; Touch cache line 8 | |
1c79356b A |
2049 | |
2050 | lnol8: | |
9bccf70c A |
2051 | la r23,savevr14(r14) ; Point to V14/V15 pair |
2052 | bf 28,lnovr12 ; Do not restore VR12... | |
2053 | lvxl v12,br0,r22 ; Restore VR12 | |
1c79356b A |
2054 | |
2055 | lnovr12: | |
9bccf70c A |
2056 | bf 29,lnovr13 ; Do not restore VR13... |
2057 | lvxl v13,r30,r22 ; Restore VR13 | |
1c79356b A |
2058 | |
2059 | lnovr13: | |
9bccf70c A |
2060 | mtcrf 0x02,r10 ; Set CRs for registers 24-27 |
2061 | la r20,savevr20(r14) ; Point to line 10 | |
2062 | bf 3,lnol9 ; No line 9 to do... | |
2063 | dcbt br0,r21 ; Touch cache line 9 | |
1c79356b A |
2064 | |
2065 | lnol9: | |
9bccf70c A |
2066 | la r22,savevr16(r14) ; Point to V16/V17 pair |
2067 | bf 30,lnovr14 ; Do not restore VR14... | |
2068 | lvxl v14,br0,r23 ; Restore VR14 | |
1c79356b A |
2069 | |
2070 | lnovr14: | |
9bccf70c A |
2071 | bf 31,lnovr15 ; Do not restore VR15... |
2072 | lvxl v15,r30,r23 ; Restore VR15 | |
1c79356b A |
2073 | |
2074 | lnovr15: | |
2075 | ; | |
2076 | ; Note: CR7 is now free | |
2077 | ; | |
9bccf70c A |
2078 | la r21,savevr22(r14) ; Point to line 11 |
2079 | bf 5,lnol10 ; No line 10 to do... | |
2080 | dcbt br0,r20 ; Touch cache line 10 | |
1c79356b A |
2081 | |
2082 | lnol10: | |
9bccf70c A |
2083 | la r23,savevr18(r14) ; Point to V18/V19 pair |
2084 | bf 16,lnovr16 ; Do not restore VR16... | |
2085 | lvxl v16,br0,r22 ; Restore VR16 | |
1c79356b A |
2086 | |
2087 | lnovr16: | |
9bccf70c A |
2088 | bf 17,lnovr17 ; Do not restore VR17... |
2089 | lvxl v17,r30,r22 ; Restore VR17 | |
1c79356b A |
2090 | |
2091 | lnovr17: | |
9bccf70c | 2092 | mtcrf 0x01,r10 ; Set CRs for registers 28-31 |
1c79356b A |
2093 | ; |
2094 | ; Note: All registers have been or are accounted for in CRs | |
2095 | ; | |
9bccf70c A |
2096 | la r20,savevr24(r14) ; Point to line 12 |
2097 | bf 7,lnol11 ; No line 11 to do... | |
2098 | dcbt br0,r21 ; Touch cache line 11 | |
1c79356b A |
2099 | |
2100 | lnol11: | |
9bccf70c A |
2101 | la r22,savevr20(r14) ; Point to V20/V21 pair |
2102 | bf 18,lnovr18 ; Do not restore VR18... | |
2103 | lvxl v18,br0,r23 ; Restore VR18 | |
1c79356b A |
2104 | |
2105 | lnovr18: | |
9bccf70c A |
2106 | bf 19,lnovr19 ; Do not restore VR19... |
2107 | lvxl v19,r30,r23 ; Restore VR19 | |
1c79356b A |
2108 | |
2109 | lnovr19: | |
9bccf70c A |
2110 | la r21,savevr26(r14) ; Point to line 13 |
2111 | bf 9,lnol12 ; No line 12 to do... | |
2112 | dcbt br0,r20 ; Touch cache line 12 | |
1c79356b A |
2113 | |
2114 | lnol12: | |
9bccf70c A |
2115 | la r23,savevr22(r14) ; Point to V22/V23 pair |
2116 | bf 20,lnovr20 ; Do not restore VR20... | |
2117 | lvxl v20,br0,r22 ; Restore VR20 | |
1c79356b A |
2118 | |
2119 | lnovr20: | |
9bccf70c A |
2120 | bf 21,lnovr21 ; Do not restore VR21... |
2121 | lvxl v21,r30,r22 ; Restore VR21 | |
1c79356b A |
2122 | |
2123 | lnovr21: | |
9bccf70c A |
2124 | la r20,savevr28(r14) ; Point to line 14 |
2125 | bf 11,lnol13 ; No line 13 to do... | |
2126 | dcbt br0,r21 ; Touch cache line 13 | |
1c79356b A |
2127 | |
2128 | lnol13: | |
9bccf70c A |
2129 | la r22,savevr24(r14) ; Point to V24/V25 pair |
2130 | bf 22,lnovr22 ; Do not restore VR22... | |
2131 | lvxl v22,br0,r23 ; Restore VR22 | |
1c79356b A |
2132 | |
2133 | lnovr22: | |
9bccf70c A |
2134 | bf 23,lnovr23 ; Do not restore VR23... |
2135 | lvxl v23,r30,r23 ; Restore VR23 | |
1c79356b A |
2136 | |
2137 | lnovr23: | |
9bccf70c A |
2138 | la r21,savevr30(r14) ; Point to line 15 |
2139 | bf 13,lnol14 ; No line 14 to do... | |
2140 | dcbt br0,r20 ; Touch cache line 14 | |
1c79356b A |
2141 | |
2142 | lnol14: | |
9bccf70c A |
2143 | la r23,savevr26(r14) ; Point to V26/V27 pair |
2144 | bf 24,lnovr24 ; Do not restore VR24... | |
2145 | lvxl v24,br0,r22 ; Restore VR24 | |
1c79356b A |
2146 | |
2147 | lnovr24: | |
9bccf70c A |
2148 | bf 25,lnovr25 ; Do not restore VR25... |
2149 | lvxl v25,r30,r22 ; Restore VR25 | |
1c79356b A |
2150 | |
2151 | lnovr25: | |
9bccf70c A |
2152 | bf 15,lnol15 ; No line 15 to do... |
2153 | dcbt br0,r21 ; Touch cache line 15 | |
1c79356b A |
2154 | |
2155 | lnol15: | |
2156 | ; | |
2157 | ; Note: All needed cache lines have been touched now | |
2158 | ; | |
9bccf70c A |
2159 | la r22,savevr28(r14) ; Point to V28/V29 pair |
2160 | bf 26,lnovr26 ; Do not restore VR26... | |
2161 | lvxl v26,br0,r23 ; Restore VR26 | |
1c79356b A |
2162 | |
2163 | lnovr26: | |
9bccf70c A |
2164 | bf 27,lnovr27 ; Do not restore VR27... |
2165 | lvxl v27,r30,r23 ; Restore VR27 | |
1c79356b A |
2166 | |
2167 | lnovr27: | |
9bccf70c A |
2168 | la r23,savevr30(r14) ; Point to V30/V31 pair |
2169 | bf 28,lnovr28 ; Do not restore VR28... | |
2170 | lvxl v28,br0,r22 ; Restore VR28 | |
1c79356b A |
2171 | |
2172 | lnovr28: | |
9bccf70c A |
2173 | bf 29,lnovr29 ; Do not restore VR29... |
2174 | lvxl v29,r30,r22 ; Restore VR29 | |
1c79356b A |
2175 | |
2176 | lnovr29: | |
9bccf70c A |
2177 | bf 30,lnovr30 ; Do not restore VR30... |
2178 | lvxl v30,br0,r23 ; Restore VR30 | |
1c79356b A |
2179 | |
2180 | lnovr30: | |
2181 | ; | |
2182 | ; Everything is restored now except for VR31. We need it to get | |
9bccf70c A |
2183 | ; the QNaNBarbarian value to put into idle vector registers. |
2184 | ; Note: V31 was set above to QNaNbarbarian | |
1c79356b A |
2185 | ; |
2186 | ||
9bccf70c A |
2187 | cmpwi r10,-1 ; Handle the quick case of all registers in use |
2188 | beq- mstlvr31 ; Not likely, but all are in use... | |
2189 | mtcrf 255,r10 ; Get mask of valid registers | |
1c79356b | 2190 | |
9bccf70c A |
2191 | bt 0,ni0 ; Register is ok already... |
2192 | vor v0,v31,v31 ; Copy into the next register | |
1c79356b | 2193 | ni0: |
9bccf70c A |
2194 | bt 1,ni1 ; Register is ok already... |
2195 | vor v1,v31,v31 ; Copy into the next register | |
1c79356b | 2196 | ni1: |
9bccf70c A |
2197 | bt 2,ni2 ; Register is ok already... |
2198 | vor v2,v31,v31 ; Copy into the next register | |
1c79356b | 2199 | ni2: |
9bccf70c A |
2200 | bt 3,ni3 ; Register is ok already... |
2201 | vor v3,v31,v31 ; Copy into the next register | |
1c79356b | 2202 | ni3: |
9bccf70c A |
2203 | bt 4,ni4 ; Register is ok already... |
2204 | vor v4,v31,v31 ; Copy into the next register | |
1c79356b | 2205 | ni4: |
9bccf70c A |
2206 | bt 5,ni5 ; Register is ok already... |
2207 | vor v5,v31,v31 ; Copy into the next register | |
1c79356b | 2208 | ni5: |
9bccf70c A |
2209 | bt 6,ni6 ; Register is ok already... |
2210 | vor v6,v31,v31 ; Copy into the next register | |
1c79356b | 2211 | ni6: |
9bccf70c A |
2212 | bt 7,ni7 ; Register is ok already... |
2213 | vor v7,v31,v31 ; Copy into the next register | |
1c79356b | 2214 | ni7: |
9bccf70c A |
2215 | bt 8,ni8 ; Register is ok already... |
2216 | vor v8,v31,v31 ; Copy into the next register | |
1c79356b | 2217 | ni8: |
9bccf70c A |
2218 | bt 9,ni9 ; Register is ok already... |
2219 | vor v9,v31,v31 ; Copy into the next register | |
1c79356b | 2220 | ni9: |
9bccf70c A |
2221 | bt 10,ni10 ; Register is ok already... |
2222 | vor v10,v31,v31 ; Copy into the next register | |
1c79356b | 2223 | ni10: |
9bccf70c A |
2224 | bt 11,ni11 ; Register is ok already... |
2225 | vor v11,v31,v31 ; Copy into the next register | |
1c79356b | 2226 | ni11: |
9bccf70c A |
2227 | bt 12,ni12 ; Register is ok already... |
2228 | vor v12,v31,v31 ; Copy into the next register | |
1c79356b | 2229 | ni12: |
9bccf70c A |
2230 | bt 13,ni13 ; Register is ok already... |
2231 | vor v13,v31,v31 ; Copy into the next register | |
1c79356b | 2232 | ni13: |
9bccf70c A |
2233 | bt 14,ni14 ; Register is ok already... |
2234 | vor v14,v31,v31 ; Copy into the next register | |
1c79356b | 2235 | ni14: |
9bccf70c A |
2236 | bt 15,ni15 ; Register is ok already... |
2237 | vor v15,v31,v31 ; Copy into the next register | |
1c79356b | 2238 | ni15: |
9bccf70c A |
2239 | bt 16,ni16 ; Register is ok already... |
2240 | vor v16,v31,v31 ; Copy into the next register | |
1c79356b | 2241 | ni16: |
9bccf70c A |
2242 | bt 17,ni17 ; Register is ok already... |
2243 | vor v17,v31,v31 ; Copy into the next register | |
1c79356b | 2244 | ni17: |
9bccf70c A |
2245 | bt 18,ni18 ; Register is ok already... |
2246 | vor v18,v31,v31 ; Copy into the next register | |
1c79356b | 2247 | ni18: |
9bccf70c A |
2248 | bt 19,ni19 ; Register is ok already... |
2249 | vor v19,v31,v31 ; Copy into the next register | |
1c79356b | 2250 | ni19: |
9bccf70c A |
2251 | bt 20,ni20 ; Register is ok already... |
2252 | vor v20,v31,v31 ; Copy into the next register | |
1c79356b | 2253 | ni20: |
9bccf70c A |
2254 | bt 21,ni21 ; Register is ok already... |
2255 | vor v21,v31,v31 ; Copy into the next register | |
1c79356b | 2256 | ni21: |
9bccf70c A |
2257 | bt 22,ni22 ; Register is ok already... |
2258 | vor v22,v31,v31 ; Copy into the next register | |
1c79356b | 2259 | ni22: |
9bccf70c A |
2260 | bt 23,ni23 ; Register is ok already... |
2261 | vor v23,v31,v31 ; Copy into the next register | |
1c79356b | 2262 | ni23: |
9bccf70c A |
2263 | bt 24,ni24 ; Register is ok already... |
2264 | vor v24,v31,v31 ; Copy into the next register | |
1c79356b | 2265 | ni24: |
9bccf70c A |
2266 | bt 25,ni25 ; Register is ok already... |
2267 | vor v25,v31,v31 ; Copy into the next register | |
1c79356b | 2268 | ni25: |
9bccf70c A |
2269 | bt 26,ni26 ; Register is ok already... |
2270 | vor v26,v31,v31 ; Copy into the next register | |
1c79356b | 2271 | ni26: |
9bccf70c A |
2272 | bt 27,ni27 ; Register is ok already... |
2273 | vor v27,v31,v31 ; Copy into the next register | |
1c79356b | 2274 | ni27: |
9bccf70c A |
2275 | bt 28,ni28 ; Register is ok already... |
2276 | vor v28,v31,v31 ; Copy into the next register | |
1c79356b | 2277 | ni28: |
9bccf70c A |
2278 | bt 29,ni29 ; Register is ok already... |
2279 | vor v29,v31,v31 ; Copy into the next register | |
1c79356b | 2280 | ni29: |
9bccf70c A |
2281 | bt 30,ni30 ; Register is ok already... |
2282 | vor v30,v31,v31 ; Copy into the next register | |
1c79356b | 2283 | ni30: |
9bccf70c | 2284 | bf 31,lnovr31 ; V31 is empty, no need to restore... |
1c79356b | 2285 | |
9bccf70c | 2286 | mstlvr31: lvxl v31,r30,r23 ; Restore VR31 |
1c79356b | 2287 | |
9bccf70c A |
2288 | lnovr31: mr r3,r14 ; Get the old savearea (we popped it before) |
2289 | bl EXT(save_ret) ; Toss it | |
1c79356b | 2290 | |
9bccf70c A |
2291 | vrenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy |
2292 | rlwinm r5,r25,0,0,19 ; Get the page address of the savearea | |
2293 | oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility | |
2294 | lwz r10,ACT_MACT_SPF(r17) ; Get the special flags | |
2295 | lwz r5,SACvrswap(r5) ; Get Virtual to Real translation | |
1c79356b | 2296 | oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors |
9bccf70c A |
2297 | rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state |
2298 | stw r8,savesrr1(r25) ; Set the msr of the interrupted guy | |
2299 | xor r3,r25,r5 ; Get the real address of the savearea | |
b4c24cb9 | 2300 | beq- vrnuser ; We are not user state... |
9bccf70c A |
2301 | stw r10,ACT_MACT_SPF(r17) ; Set the activation copy |
2302 | stw r10,spcFlags(r26) ; Set per_proc copy | |
1c79356b A |
2303 | |
2304 | vrnuser: | |
2305 | #if FPVECDBG | |
9bccf70c A |
2306 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
2307 | li r2,0x5F07 ; (TEST/DEBUG) | |
2308 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
2309 | sc ; (TEST/DEBUG) | |
1c79356b | 2310 | #endif |
9bccf70c | 2311 | b EXT(exception_exit) ; Exit to the fray... |
1c79356b A |
2312 | |
2313 | /* | |
2314 | * Initialize the registers to some bogus value | |
1c79356b A |
2315 | */ |
2316 | ||
2317 | ProtectTheAmericanWay: | |
2318 | ||
2319 | #if FPVECDBG | |
9bccf70c A |
2320 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) |
2321 | li r2,0x5F06 ; (TEST/DEBUG) | |
2322 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
2323 | sc ; (TEST/DEBUG) | |
1c79356b | 2324 | #endif |
9bccf70c A |
2325 | |
2326 | vor v0,v31,v31 ; Copy into the next register | |
2327 | vor v1,v31,v31 ; Copy into the next register | |
2328 | vor v2,v31,v31 ; Copy into the next register | |
2329 | vor v3,v31,v31 ; Copy into the next register | |
2330 | vor v4,v31,v31 ; Copy into the next register | |
2331 | vor v5,v31,v31 ; Copy into the next register | |
2332 | vor v6,v31,v31 ; Copy into the next register | |
2333 | vor v7,v31,v31 ; Copy into the next register | |
2334 | vor v8,v31,v31 ; Copy into the next register | |
2335 | vor v9,v31,v31 ; Copy into the next register | |
2336 | vor v10,v31,v31 ; Copy into the next register | |
2337 | vor v11,v31,v31 ; Copy into the next register | |
2338 | vor v12,v31,v31 ; Copy into the next register | |
2339 | vor v13,v31,v31 ; Copy into the next register | |
2340 | vor v14,v31,v31 ; Copy into the next register | |
2341 | vor v15,v31,v31 ; Copy into the next register | |
2342 | vor v16,v31,v31 ; Copy into the next register | |
2343 | vor v17,v31,v31 ; Copy into the next register | |
2344 | vor v18,v31,v31 ; Copy into the next register | |
2345 | vor v19,v31,v31 ; Copy into the next register | |
2346 | vor v20,v31,v31 ; Copy into the next register | |
2347 | vor v21,v31,v31 ; Copy into the next register | |
2348 | vor v22,v31,v31 ; Copy into the next register | |
2349 | vor v23,v31,v31 ; Copy into the next register | |
2350 | vor v24,v31,v31 ; Copy into the next register | |
2351 | vor v25,v31,v31 ; Copy into the next register | |
2352 | vor v26,v31,v31 ; Copy into the next register | |
2353 | vor v27,v31,v31 ; Copy into the next register | |
2354 | vor v28,v31,v31 ; Copy into the next register | |
2355 | vor v29,v31,v31 ; Copy into the next register | |
2356 | vor v30,v31,v31 ; Copy into the next register | |
2357 | b vrenable ; Finish setting it all up... | |
2358 | ||
2359 | ||
2360 | ||
2361 | ; | |
2362 | ; We get here when we are switching to the same context at the same level and the context | |
2363 | ; is still live. Essentially, all we are doing is turning on the faility. It may have | |
2364 | ; gotten turned off due to doing a context save for the current level or a context switch | |
2365 | ; back to the live guy. | |
2366 | ; | |
2367 | ||
2368 | .align 5 | |
2369 | ||
2370 | vsthesame: | |
2371 | ||
2372 | #if FPVECDBG | |
2373 | lis r0,hi16(CutTrace) ; (TEST/DEBUG) | |
2374 | li r2,0x5F0A ; (TEST/DEBUG) | |
2375 | oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG) | |
2376 | sc ; (TEST/DEBUG) | |
2377 | #endif | |
2378 | beq- cr1,vrenable ; Not saved yet, nothing to pop, go enable and exit... | |
2379 | ||
2380 | lwz r11,SAVlevel(r30) ; Get the level of top saved context | |
2381 | lwz r14,SAVprev(r30) ; Get the previous savearea | |
2382 | ||
2383 | cmplw r11,r31 ; Are live and saved the same? | |
2384 | ||
2385 | bne+ vrenable ; Level not the same, nothing to pop, go enable and exit... | |
2386 | ||
2387 | mr r3,r30 ; Get the old savearea (we popped it before) | |
2388 | bl EXT(save_ret) ; Toss it | |
2389 | b vrenable ; Go enable and exit... | |
2390 | ||
2391 | ||
2392 | ; | |
2393 | ; This function invalidates any live vector context for the passed in facility_context. | |
2394 | ; This is intended to be called just before act_machine_sv_free tosses saveareas. | |
1c79356b | 2395 | ; |
1c79356b | 2396 | |
9bccf70c A |
2397 | .align 5 |
2398 | .globl EXT(toss_live_vec) | |
1c79356b | 2399 | |
9bccf70c A |
2400 | LEXT(toss_live_vec) |
2401 | ||
2402 | mfmsr r9 ; Get the MSR | |
2403 | rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions | |
2404 | rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now? | |
2405 | rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vector is turned off | |
2406 | rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure fpu is turned off | |
2407 | mtmsr r0 ; No interruptions | |
2408 | isync | |
2409 | beq+ tlvnotours ; Vector off, can not be live here... | |
1c79356b | 2410 | |
9bccf70c A |
2411 | mfsprg r8,0 ; Get the per proc |
2412 | ||
2413 | ; | |
2414 | ; Note that at this point, since vecs are on, we are the owner | |
2415 | ; of live state on this processor | |
2416 | ; | |
2417 | ||
2418 | lwz r6,VMXowner(r8) ; Get the thread that owns the vector | |
2419 | li r0,0 ; Clear this just in case we need it | |
2420 | cmplw r6,r3 ; Are we tossing our own context? | |
2421 | bne- tlvnotours ; Nope... | |
2422 | ||
2423 | vspltish v1,1 ; Turn on the non-Java bit and saturate | |
2424 | vspltisw v0,1 ; Turn on the saturate bit | |
2425 | vxor v1,v1,v0 ; Turn off saturate | |
2426 | mtspr vrsave,r0 ; Clear VRSAVE | |
2427 | mtvscr v1 ; Set the non-java, no saturate status | |
2428 | ||
2429 | tlvnotours: lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context | |
2430 | lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc | |
2431 | mulli r11,r11,ppSize ; Find offset to the owner per_proc | |
2432 | ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc | |
2433 | li r10,VMXowner ; Displacement to vector owner | |
2434 | add r11,r12,r11 ; Point to the owner per_proc | |
2435 | li r0,0 ; Set a 0 to invalidate context | |
2436 | ||
2437 | tlvinvothr: lwarx r12,r10,r11 ; Get the owner | |
2438 | cmplw r12,r3 ; Does he still have this context? | |
2439 | bne+ tlvexit ; Nope, leave... | |
2440 | stwcx. r0,r10,r11 ; Try to invalidate it | |
2441 | bne- tlvinvothr ; Try again if there was a collision... | |
2442 | ||
2443 | tlvexit: mtmsr r9 ; Restore interruptions | |
2444 | isync ; Could be turning off vectors here | |
2445 | blr ; Leave.... | |
2446 | ||
2447 | #if 0 | |
2448 | ; | |
2449 | ; This function invalidates any live vector context for the passed in facility_context | |
2450 | ; if the level is current. It also tosses the corresponding savearea if there is one. | |
2451 | ; This function is primarily used whenever we detect a VRSave that is all zeros. | |
2452 | ; | |
2453 | ||
2454 | .align 5 | |
2455 | .globl EXT(vec_trash) | |
2456 | ||
2457 | LEXT(vec_trash) | |
2458 | ||
2459 | lwz r12,facAct(r3) ; Get the activation | |
2460 | lwz r11,VMXlevel(r3) ; Get the context level | |
2461 | lwz r10,ACT_MACT_PCB(r12) ; Grab the current level for the thread | |
2462 | lwz r9,VMXsave(r3) ; Get the savearea, if any | |
2463 | cmplw r10,r11 ; Are we at the right level? | |
2464 | cmplwi cr1,r9,0 ; Remember if there is a savearea | |
2465 | bnelr+ ; No, we do nothing... | |
2466 | ||
2467 | lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context | |
2468 | lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc | |
2469 | mulli r11,r11,ppSize ; Find offset to the owner per_proc | |
2470 | ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc | |
2471 | li r10,VMXowner ; Displacement to vector owner | |
2472 | add r11,r12,r11 ; Point to the owner per_proc | |
2473 | li r0,0 ; Set a 0 to invalidate context | |
2474 | ||
2475 | vtinvothr: lwarx r12,r10,r11 ; Get the owner | |
2476 | cmplw r12,r3 ; Does he still have this context? | |
2477 | bne vtnotlive ; Nope, not live anywhere... | |
2478 | stwcx. r0,r10,r11 ; Try to invalidate it | |
2479 | bne- vtinvothr ; Try again if there was a collision... | |
2480 | ||
2481 | vtnotlive: beqlr+ cr1 ; Leave if there is no savearea | |
2482 | lwz r8,SAVlevel(r9) ; Get the level of the savearea | |
2483 | cmplw r8,r11 ; Savearea for the current level? | |
2484 | bnelr+ ; No, nothing to release... | |
2485 | ||
2486 | lwz r8,SAVprev(r9) ; Pick up the previous area | |
2487 | mr. r8,r8 ; Is there a previous? | |
2488 | beq- vtnoprev ; Nope... | |
2489 | lwz r7,SAVlevel(r8) ; Get the level associated with save | |
2490 | ||
2491 | vtnoprev: stw r8,VMXsave(r3) ; Dequeue this savearea | |
2492 | stw r7,VMXlevel(r3) ; Pop the level | |
2493 | ||
2494 | mr r3,r9 ; Get the savearea to release | |
2495 | b EXT(save_ret) ; Go and toss the save area (note, we will return from there)... | |
2496 | #endif | |
2497 | ||
2498 | ; | |
2499 | ; Just some test code to force vector and/or floating point in the kernel | |
2500 | ; | |
2501 | ||
2502 | .align 5 | |
2503 | .globl EXT(fctx_test) | |
1c79356b | 2504 | |
9bccf70c A |
2505 | LEXT(fctx_test) |
2506 | ||
2507 | mfsprg r3,0 ; Get the per_proc block | |
2508 | lwz r3,PP_ACTIVE_THREAD(r3) ; Get the thread pointer | |
2509 | mr. r3,r3 ; Are we actually up and running? | |
2510 | beqlr- ; No... | |
2511 | ||
2512 | fmr f0,f0 ; Use floating point | |
2513 | mftb r4 ; Get time base for a random number | |
2514 | li r5,1 ; Get a potential vrsave to use | |
2515 | andi. r4,r4,0x3F ; Get a number from 0 - 63 | |
2516 | slw r5,r5,r4 ; Choose a register to save (should be 0 half the time) | |
2517 | mtspr vrsave,r5 ; Set VRSave | |
2518 | vor v0,v0,v0 ; Use vectors | |
2519 | blr |