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