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