2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
30 #include <ppc/proc_reg.h>
34 #include <mach/ppc/vm_param.h>
35 #include <ppc/exception.h>
36 #include <ppc/savearea.h>
44 * void load_context(thread_t thread)
46 * Load the context for the first kernel thread, and go.
48 * NOTE - if DEBUG is set, the former routine is a piece
49 * of C capable of printing out debug info before calling the latter,
50 * otherwise both entry points are identical.
54 .globl EXT(load_context)
58 .globl EXT(Load_context)
63 * Since this is the first thread, we came in on the interrupt
64 * stack. The first thread never returns, so there is no need to
65 e worry about saving its frame, hence we can reset the istackptr
66 * back to the saved_state structure at it's top
71 * get new thread pointer and set it into the active_threads pointer
76 lwz r0,PP_INTSTACK_TOP_SS(r6)
77 stw r0,PP_ISTACKPTR(r6)
78 stw r3,PP_ACTIVE_THREAD(r6)
80 /* Find the new stack and store it in active_stacks */
82 lwz r12,PP_ACTIVE_STACKS(r6)
83 lwz r1,THREAD_KERNEL_STACK(r3)
84 lwz r9,THREAD_TOP_ACT(r3) /* Point to the active activation */
87 li r0,0 /* Clear a register */
88 lwz r8,ACT_MACT_PCB(r9) /* Get the savearea used */
89 rlwinm r7,r8,0,0,19 /* Switch to savearea base */
90 lwz r11,SAVprev(r8) /* Get the previous savearea */
91 mfmsr r5 /* Since we are passing control, get our MSR values */
92 lwz r1,saver1(r8) /* Load new stack pointer */
93 stw r0,saver3(r8) /* Make sure we pass in a 0 for the continuation */
94 lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */
95 stw r0,FM_BACKPTR(r1) /* zero backptr */
96 stw r5,savesrr1(r8) /* Pass our MSR to the new guy */
97 xor r3,r7,r8 /* Get the physical address of the new context save area */
98 stw r11,ACT_MACT_PCB(r9) /* Unstack our savearea */
99 b EXT(exception_exit) /* Go end it all... */
101 /* struct thread_shuttle *Switch_context(struct thread_shuttle *old,
102 * void (*cont)(void),
103 * struct thread_shuttle *new)
105 * Switch from one thread to another. If a continuation is supplied, then
106 * we do not need to save callee save registers.
110 /* void Call_continuation( void (*continuation)(void), vm_offset_t stack_ptr)
114 .globl EXT(Call_continuation)
116 LEXT(Call_continuation)
119 mr r1, r4 /* Load new stack pointer */
120 blr /* Jump to the continuation */
123 * Get the old kernel stack, and store into the thread structure.
124 * See if a continuation is supplied, and skip state save if so.
125 * NB. Continuations are no longer used, so this test is omitted,
126 * as should the second argument, but it is in generic code.
127 * We always save state. This does not hurt even if continuations
131 /* Context switches are double jumps. We pass the following to the
132 * context switch firmware call:
134 * R3 = switchee's savearea
139 * savesrr0 is set to go to switch_in
140 * savesrr1 is set to uninterruptible with translation on
145 .globl EXT(Switch_context)
149 mfsprg r12,0 ; Get the per_proc block
150 lwz r10,PP_ACTIVE_STACKS(r12) ; Get the pointer to the current stack
152 lwz r11,PP_ISTACKPTR(r12) ; (DEBUG/TRACE) make sure we are not
153 mr. r11,r11 ; (DEBUG/TRACE) on the interrupt
154 bne+ notonintstack ; (DEBUG/TRACE) stack
158 stw r4,THREAD_CONTINUATION(r3) ; Set continuation into the thread
159 cmpwi cr1,r4,0 ; used waaaay down below
160 lwz r7,0(r10) ; Get the current stack
162 * Make the new thread the current thread.
165 stw r7,THREAD_KERNEL_STACK(r3) ; Remember the current stack in the thread (do not need???)
166 stw r5, PP_ACTIVE_THREAD(r12) ; Make the new thread current
168 lwz r11,THREAD_KERNEL_STACK(r5) ; Get the new stack pointer
170 lwz r5,THREAD_TOP_ACT(r5) ; Get the new activation
172 lwz r7,CTHREAD_SELF(r5) ; Pick up the user assist word
173 lwz r8,ACT_MACT_PCB(r5) ; Get the PCB for the new guy
176 lwz r0,SAVflags(r8) ; (TEST/DEBUG)
177 rlwinm r0,r0,24,24,31 ; (TEST/DEBUG)
178 cmplwi r0,SAVempty ; (TEST/DEBUG)
179 bne+ nnnn ; (TEST/DEBUG)
184 stw r11,0(r10) ; Save the new kernel stack address
185 stw r7,UAW(r12) ; Save the assist word for the "ultra fast path"
187 lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment
189 lwz r7,ACT_MACT_SPF(r5) ; Get the special flags
191 lwz r10,ACT_KLOADED(r5)
192 stw r11,ppbbTaskEnv(r12) ; Save the bb task env
195 lwz r10,PP_ACTIVE_KLOADED(r12)
196 stw r7,spcFlags(r12) ; Set per_proc copy of the special flags
197 beq cr0,.L_sw_ctx_not_kld
203 stw r0,0(r10) /* act_kloaded = 0 */
206 lis r10,hi16(EXT(trcWork)) ; Get top of trace mask
207 rlwinm r7,r8,0,0,19 /* Switch to savearea base */
208 ori r10,r10,lo16(EXT(trcWork)) ; Get bottom of mask
209 lwz r11,SAVprev(r8) /* Get the previous of the switchee's savearea */
210 lwz r10,traceMask(r10) ; Get the enabled traces
211 lis r0,hi16(CutTrace) ; Trace FW call
212 mr. r10,r10 ; Any tracing going on?
213 ori r0,r0,lo16(CutTrace) ; Trace FW call
214 beq+ cswNoTrc ; No trace today, dude...
215 mr r10,r3 ; Save across trace
216 lwz r2,THREAD_TOP_ACT(r3) ; Trace old activation
217 mr r3,r11 ; Trace prev savearea
218 sc ; Cut trace entry of context switch
221 cswNoTrc: mfmsr r6 /* Get the MSR because the switched to thread should inherit it */
222 lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */
223 stw r11,ACT_MACT_PCB(r5) /* Dequeue the savearea we're switching to */
225 rlwinm r6,r6,0,MSR_FP_BIT+1,MSR_FP_BIT-1 /* Turn off the FP */
226 lwz r2,curctx(r5) ; Grab our current context pointer
227 rlwinm r6,r6,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 /* Turn off the vector */
228 mr r4,r3 /* Save our old thread to pass back */
230 lhz r0,PP_CPU_NUMBER(r12) ; Get our CPU number
231 lwz r10,FPUowner(r12) ; Grab the owner of the FPU
232 lwz r9,VMXowner(r12) ; Grab the owner of the vector
233 cmplw r10,r2 ; Do we have the live float context?
234 lwz r10,FPUlevel(r2) ; Get the live level
235 cmplw cr5,r9,r2 ; Do we have the live vector context?
236 bne+ cswnofloat ; Float is not ours...
238 cmplw r10,r11 ; Is the level the same?
239 lwz r5,FPUcpu(r2) ; Get the owning cpu
240 bne+ cswnofloat ; Level not the same, this is not live...
242 cmplw r5,r0 ; Still owned by this cpu?
243 lwz r10,FPUsave(r2) ; Get the level
244 bne+ cswnofloat ; CPU claimed by someone else...
246 mr. r10,r10 ; Is there a savearea here?
247 ori r6,r6,lo16(MASK(MSR_FP)) ; Enable floating point
249 beq- cswnofloat ; No savearea to check...
251 lwz r3,SAVlevel(r10) ; Get the level
252 lwz r5,SAVprev(r10) ; Get the previous of this savearea
253 cmplw r3,r11 ; Is it for the current level?
255 bne+ cswnofloat ; Nope...
257 stw r5,FPUsave(r2) ; Pop off this savearea
258 rlwinm r5,r10,0,0,19 ; Move back to start of page
259 lwz r5,SACvrswap(r5) ; Get the virtual to real conversion
260 la r9,quickfret(r12) ; Point to the quickfret chain header
261 xor r5,r10,r5 ; Convert savearea address to real
264 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
265 li r2,0x4401 ; (TEST/DEBUG)
266 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
268 lhz r0,PP_CPU_NUMBER(r12) ; (TEST/DEBUG)
272 ; Note: we need to do the atomic operation here because, even though
273 ; it is impossible with the current implementation, that we may take a
274 ; PTE miss between the load of the quickfret anchor and the subsequent
275 ; store. The interrupt handler will dequeue everything on the list and
276 ; we could end up using stale data. I do not like doing this...
279 cswfpudq: lwarx r3,0,r9 ; Pick up the old chain head
280 stw r3,SAVprev(r10) ; Move it to the current guy
281 stwcx. r5,0,r9 ; Save it
282 bne- cswfpudq ; Someone chaged the list...
284 cswnofloat: bne+ cr5,cswnovect ; Vector is not ours...
286 lwz r10,VMXlevel(r2) ; Get the live level
288 cmplw r10,r11 ; Is the level the same?
289 lwz r5,VMXcpu(r2) ; Get the owning cpu
290 bne+ cswnovect ; Level not the same, this is not live...
292 cmplw r5,r0 ; Still owned by this cpu?
293 lwz r10,VMXsave(r2) ; Get the level
294 bne+ cswnovect ; CPU claimed by someone else...
296 mr. r10,r10 ; Is there a savearea here?
297 oris r6,r6,hi16(MASK(MSR_VEC)) ; Enable vector
299 beq- cswnovect ; No savearea to check...
301 lwz r3,SAVlevel(r10) ; Get the level
302 lwz r5,SAVprev(r10) ; Get the previous of this savearea
303 cmplw r3,r11 ; Is it for the current level?
305 bne+ cswnovect ; Nope...
307 stw r5,VMXsave(r2) ; Pop off this savearea
308 rlwinm r5,r10,0,0,19 ; Move back to start of page
309 lwz r5,SACvrswap(r5) ; Get the virtual to real conversion
310 la r9,quickfret(r12) ; Point to the quickfret chain header
311 xor r5,r10,r5 ; Convert savearea address to real
314 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
315 li r2,0x4501 ; (TEST/DEBUG)
316 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
321 ; Note: we need to do the atomic operation here because, even though
322 ; it is impossible with the current implementation, that we may take a
323 ; PTE miss between the load of the quickfret anchor and the subsequent
324 ; store. The interrupt handler will dequeue everything on the list and
325 ; we could end up using stale data. I do not like doing this...
328 cswvecdq: lwarx r3,0,r9 ; Pick up the old chain head
329 stw r3,SAVprev(r10) ; Move it to the current guy
330 stwcx. r5,0,r9 ; Save it
331 bne- cswvecdq ; Someone chaged the list...
333 cswnovect: lis r9,hi16(EXT(switch_in)) /* Get top of switch in routine */
334 lwz r5,savesrr0(r8) /* Set up the new SRR0 */
335 ori r9,r9,lo16(EXT(switch_in)) /* Bottom half of switch in */
336 lis r0,hi16(SwitchContextCall) /* Top part of switch context */
337 stw r9,savesrr0(r8) /* Make us jump to the switch in routine */
339 li r10,MSR_SUPERVISOR_INT_OFF /* Get the switcher's MSR */
340 lwz r9,SAVflags(r8) /* Get the flags */
341 stw r10,savesrr1(r8) /* Set up for switch in */
342 rlwinm r9,r9,0,15,13 /* Reset the syscall flag */
343 ori r0,r0,lo16(SwitchContextCall) /* Bottom part of switch context */
344 xor r3,r7,r8 /* Get the physical address of the new context save area */
345 stw r9,SAVflags(r8) /* Set the flags */
347 bne cr1,swtchtocont ; Switch to the continuation
348 sc /* Switch to the new context */
350 /* We come back here in the new thread context
351 * R4 was set to hold the old thread pointer, but switch_in will put it into
352 * R3 where it belongs.
354 blr /* Jump into the new thread */
357 ; This is where we go when a continuation is set. We are actually
358 ; killing off the old context of the new guy so we need to pop off
359 ; any float or vector states for the ditched level.
361 ; Note that we do the same kind of thing a chkfac in hw_exceptions.s
366 stw r5,savesrr0(r8) ; Set the pc
367 stw r6,savesrr1(r8) ; Set the next MSR to use
368 stw r4,saver3(r8) ; Make sure we pass back the old thread
370 b EXT(exception_exit) ; Blocking on continuation, toss old context...
375 * All switched to threads come here first to clean up the old thread.
376 * We need to do the following contortions because we need to keep
377 * the LR clean. And because we need to manipulate the savearea chain
378 * with translation on. If we could, this should be done in lowmem_vectors
379 * before translation is turned on. But we can't, dang it!
381 * R3 = switcher's savearea
382 * saver4 = old thread in switcher's save
383 * saver5 = new SRR0 in switcher's save
384 * saver6 = new SRR1 in switcher's save
391 .globl EXT(switch_in)
395 lwz r4,saver4(r3) /* Get the old thread */
396 lwz r9,THREAD_TOP_ACT(r4) /* Get the switched from ACT */
397 lwz r5,saver5(r3) /* Get the srr0 value */
398 lwz r10,ACT_MACT_PCB(r9) /* Get the top PCB on the old thread */
399 lwz r6,saver6(r3) /* Get the srr1 value */
401 stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */
402 stw r10,SAVprev(r3) /* Chain on the old one */
404 mr r3,r4 /* Pass back the old thread */
406 mtsrr0 r5 /* Set return point */
407 mtsrr1 r6 /* Set return MSR */
421 * void fpu_save(facility_context ctx)
423 * Note that there are some oddities here when we save a context we are using.
424 * It is really not too cool to do this, but what the hey... Anyway,
425 * we turn fpus and vecs off before we leave., The oddity is that if you use fpus after this, the
426 * savearea containing the context just saved will go away. So, bottom line is
427 * that don't use fpus until after you are done with the saved context.
435 mfmsr r0 ; Get the MSR
436 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
437 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
438 ori r2,r2,MASK(MSR_FP) ; Enable the floating point feature for now also
439 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
440 mtmsr r2 ; Set the MSR
443 mfsprg r6,0 ; Get the per_processor block
444 lwz r12,FPUowner(r6) ; Get the context ID for owner
447 mr r7,r0 ; (TEST/DEBUG)
448 li r4,0 ; (TEST/DEBUG)
449 mr r10,r3 ; (TEST/DEBUG)
450 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
451 mr. r3,r12 ; (TEST/DEBUG)
452 li r2,0x6F00 ; (TEST/DEBUG)
453 li r5,0 ; (TEST/DEBUG)
454 beq- noowneryet ; (TEST/DEBUG)
455 lwz r4,FPUlevel(r12) ; (TEST/DEBUG)
456 lwz r5,FPUsave(r12) ; (TEST/DEBUG)
458 noowneryet: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
460 mr r0,r7 ; (TEST/DEBUG)
461 mr r3,r10 ; (TEST/DEBUG)
463 mflr r2 ; Save the return address
465 fsretry: mr. r12,r12 ; Anyone own the FPU?
466 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
467 beq- fsret ; Nobody owns the FPU, no save required...
469 cmplw cr1,r3,r12 ; Is the specified context live?
471 isync ; Force owner check first
473 lwz r9,FPUcpu(r12) ; Get the cpu that context was last on
474 bne- cr1,fsret ; No, it is not...
476 cmplw cr1,r9,r11 ; Was the context for this processor?
477 beq- cr1,fsgoodcpu ; Facility last used on this processor...
479 b fsret ; Someone else claimed it...
483 fsgoodcpu: lwz r3,FPUsave(r12) ; Get the current FPU savearea for the thread
484 lwz r9,FPUlevel(r12) ; Get our current level indicator
486 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
487 beq- cr1,fsneedone ; Never saved it, so go do it...
489 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
490 cmplw cr1,r9,r8 ; Correct level?
491 beq- cr1,fsret ; The current level is already saved, bail out...
493 fsneedone: bl EXT(save_get) ; Get a savearea for the context
495 mfsprg r6,0 ; Get back per_processor block
496 li r4,SAVfloat ; Get floating point tag
497 lwz r12,FPUowner(r6) ; Get back our thread
498 stb r4,SAVflags+2(r3) ; Mark this savearea as a float
499 mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it...
500 beq- fsbackout ; If disowned, just toss savearea...
501 lwz r4,facAct(r12) ; Get the activation associated with live context
502 mtlr r2 ; Restore return
503 lwz r8,FPUsave(r12) ; Get the current top floating point savearea
504 stw r4,SAVact(r3) ; Indicate the right activation for this context
505 lwz r9,FPUlevel(r12) ; Get our current level indicator again
506 stw r3,FPUsave(r12) ; Set this as the most current floating point context
507 stw r8,SAVprev(r3) ; And then chain this in front
509 stw r9,SAVlevel(r3) ; Show level in savearea
512 ; Save the current FPU state into the PCB of the thread that owns it.
515 la r11,savefp0(r3) ; Point to the 1st line
516 dcbz 0,r11 ; Allocate the first savearea line
518 la r11,savefp4(r3) ; Point to the 2nd line
520 dcbz 0,r11 ; Allocate it
523 la r11,savefp8(r3) ; Point to the 3rd line
525 dcbz 0,r11 ; Allocate it
529 la r11,savefp12(r3) ; Point to the 4th line
531 dcbz 0,r11 ; Allocate it
534 stfd f10,savefp10(r3)
535 la r11,savefp16(r3) ; Point to the 5th line
536 stfd f11,savefp11(r3)
537 dcbz 0,r11 ; Allocate it
538 stfd f12,savefp12(r3)
539 stfd f13,savefp13(r3)
540 stfd f14,savefp14(r3)
541 la r11,savefp20(r3) ; Point to the 6th line
542 stfd f15,savefp15(r3)
543 stfd f16,savefp16(r3)
544 stfd f17,savefp17(r3)
545 stfd f18,savefp18(r3)
546 la r11,savefp24(r3) ; Point to the 7th line
547 stfd f19,savefp19(r3)
548 dcbz 0,r11 ; Allocate it
549 stfd f20,savefp20(r3)
550 stfd f21,savefp21(r3)
551 stfd f22,savefp22(r3)
552 la r11,savefp28(r3) ; Point to the 8th line
553 stfd f23,savefp23(r3)
554 dcbz 0,r11 ; Allocate it
555 stfd f24,savefp24(r3)
556 stfd f25,savefp25(r3)
557 stfd f26,savefp26(r3)
558 stfd f27,savefp27(r3)
559 stfd f28,savefp28(r3)
561 stfd f29,savefp29(r3)
562 stfd f30,savefp30(r3)
563 stfd f31,savefp31(r3)
565 fsret: mtmsr r0 ; Put interrupts on if they were and floating point off
570 fsbackout: mr r12,r0 ; Save the original MSR
571 b EXT(save_ret_join) ; Toss savearea and return from there...
576 * Entered to handle the floating-point unavailable exception and
579 * This code is run in virtual address mode on with interrupts off.
581 * Upon exit, the code returns to the users context with the floating
582 * point facility turned on.
584 * ENTRY: VM switched ON
586 * State is saved in savearea pointed to by R4.
587 * All other registers are free.
592 .globl EXT(fpu_switch)
597 lis r3,hi16(EXT(fpu_trap_count)) ; Get address of FP trap counter
598 ori r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
604 mfsprg r26,0 ; Get the per_processor block
605 mfmsr r19 ; Get the current MSR
607 mr r25,r4 ; Save the entry savearea
608 lwz r22,FPUowner(r26) ; Get the thread that owns the FPU
609 lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread
610 ori r19,r19,lo16(MASK(MSR_FP)) ; Enable the floating point feature
611 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
613 mtmsr r19 ; Enable floating point instructions
616 lwz r27,ACT_MACT_PCB(r17) ; Get the current level
617 lwz r29,curctx(r17) ; Grab the current context anchor of the current thread
619 ; R22 has the "old" context anchor
620 ; R29 has the "new" context anchor
623 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
624 li r2,0x7F01 ; (TEST/DEBUG)
625 mr r3,r22 ; (TEST/DEBUG)
626 mr r5,r29 ; (TEST/DEBUG)
627 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
631 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
633 fswretry: mr. r22,r22 ; See if there is any live FP status
635 beq- fsnosave ; No live context, so nothing to save...
637 isync ; Make sure we see this in the right order
639 lwz r30,FPUsave(r22) ; Get the top savearea
640 cmplw cr2,r22,r29 ; Are both old and new the same context?
641 lwz r18,FPUcpu(r22) ; Get the last CPU we ran on
642 cmplwi cr1,r30,0 ; Anything saved yet?
643 cmplw r18,r16 ; Make sure we are on the right processor
644 lwz r31,FPUlevel(r22) ; Get the context level
646 bne- fsnosave ; No, not on the same processor...
649 ; Check to see if the live context has already been saved.
650 ; Also check to see if all we are here just to re-enable the MSR
651 ; and handle specially if so.
654 cmplw r31,r27 ; See if the current and active levels are the same
655 crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same
658 beq- fsthesame ; New and old are the same, just go enable...
660 beq- cr1,fsmstsave ; Not saved yet, go do it...
662 lwz r11,SAVlevel(r30) ; Get the level of top saved context
664 cmplw r31,r11 ; Are live and saved the same?
667 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
668 li r2,0x7F02 ; (TEST/DEBUG)
669 mr r3,r30 ; (TEST/DEBUG)
670 mr r5,r31 ; (TEST/DEBUG)
671 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
675 beq+ fsnosave ; Same level, so already saved...
678 fsmstsave: stw r3,FPUowner(r26) ; Kill the context now
679 eieio ; Make sure everyone sees it
680 bl EXT(save_get) ; Go get a savearea
682 la r11,savefp0(r3) ; Point to the 1st line in new savearea
683 lwz r12,facAct(r22) ; Get the activation associated with the context
684 dcbz 0,r11 ; Allocate cache
685 stw r3,FPUsave(r22) ; Set this as the latest context savearea for the thread
687 stw r30,SAVprev(r3) ; Point us to the old context
688 stw r31,SAVlevel(r3) ; Tag our level
689 li r7,SAVfloat ; Get the floating point ID
690 stw r12,SAVact(r3) ; Make sure we point to the right guy
691 stb r7,SAVflags+2(r3) ; Set that we have a floating point save area
694 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
695 li r2,0x7F03 ; (TEST/DEBUG)
696 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
701 ; Now we will actually save the old context
704 la r11,savefp4(r3) ; Point to the 2nd line
706 dcbz 0,r11 ; Allocate cache
709 la r11,savefp8(r3) ; Point to the 3rd line
711 dcbz 0,r11 ; Allocate cache
715 la r11,savefp12(r3) ; Point to the 4th line
717 dcbz 0,r11 ; Allocate cache
720 stfd f10,savefp10(r3)
721 la r11,savefp16(r3) ; Point to the 5th line
722 stfd f11,savefp11(r3)
723 dcbz 0,r11 ; Allocate cache
724 stfd f12,savefp12(r3)
725 stfd f13,savefp13(r3)
726 stfd f14,savefp14(r3)
727 la r11,savefp20(r3) ; Point to the 6th line
728 stfd f15,savefp15(r3)
729 dcbz 0,r11 ; Allocate cache
730 stfd f16,savefp16(r3)
731 stfd f17,savefp17(r3)
732 stfd f18,savefp18(r3)
733 la r11,savefp24(r3) ; Point to the 7th line
734 stfd f19,savefp19(r3)
735 dcbz 0,r11 ; Allocate cache
736 stfd f20,savefp20(r3)
738 stfd f21,savefp21(r3)
739 stfd f22,savefp22(r3)
740 la r11,savefp28(r3) ; Point to the 8th line
741 stfd f23,savefp23(r3)
742 dcbz 0,r11 ; allocate it
743 stfd f24,savefp24(r3)
744 stfd f25,savefp25(r3)
745 stfd f26,savefp26(r3)
746 stfd f27,savefp27(r3)
747 dcbz 0,r11 ; allocate it
748 stfd f28,savefp28(r3)
749 stfd f29,savefp29(r3)
750 stfd f30,savefp30(r3)
751 stfd f31,savefp31(r3)
754 ; The context is all saved now and the facility is free.
756 ; If we do not we need to fill the registers with junk, because this level has
757 ; never used them before and some thieving bastard could hack the old values
758 ; of some thread! Just imagine what would happen if they could! Why, nothing
759 ; would be safe! My God! It is terrifying!
763 fsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
764 lwz r19,FPUcpu(r29) ; Get the last CPU we ran on
765 lwz r14,FPUsave(r29) ; Point to the top of the "new" context stack
767 stw r16,FPUcpu(r29) ; Claim context for us
771 lwz r13,FPUlevel(r29) ; (TEST/DEBUG)
772 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
773 li r2,0x7F04 ; (TEST/DEBUG)
774 mr r1,r15 ; (TEST/DEBUG)
775 mr r3,r14 ; (TEST/DEBUG)
776 mr r5,r13 ; (TEST/DEBUG)
777 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
781 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
782 mulli r19,r19,ppSize ; Find offset to the owner per_proc
783 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
784 li r16,FPUowner ; Displacement to float owner
785 add r19,r18,r19 ; Point to the owner per_proc
788 fsinvothr: lwarx r18,r16,r19 ; Get the owner
789 cmplw r18,r29 ; Does he still have this context?
790 bne fsinvoths ; Nope...
791 stwcx. r0,r16,r19 ; Try to invalidate it
792 bne- fsinvothr ; Try again if there was a collision...
794 fsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
795 la r11,savefp0(r14) ; Point to first line to bring in
796 stw r15,FPUlevel(r29) ; Set the "new" active level
798 stw r29,FPUowner(r26) ; Mark us as having the live context
800 beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load...
802 dcbt 0,r11 ; Touch line in
804 lwz r3,SAVprev(r14) ; Get the previous context
805 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
806 cmplw r0,r15 ; Top level correct to load?
807 bne- MakeSureThatNoTerroristsCanHurtUsByGod ; No, go initialize...
809 stw r3,FPUsave(r29) ; Pop the context (we will toss the savearea later)
812 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
813 li r2,0x7F05 ; (TEST/DEBUG)
814 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
818 la r11,savefp4(r14) ; Point to next line
819 dcbt 0,r11 ; Touch line in
823 la r11,savefp8(r14) ; Point to next line
825 dcbt 0,r11 ; Touch line in
829 la r11,savefp12(r14) ; Point to next line
831 dcbt 0,r11 ; Touch line in
834 lfd f10,savefp10(r14)
835 la r11,savefp16(r14) ; Point to next line
836 lfd f11,savefp11(r14)
837 dcbt 0,r11 ; Touch line in
838 lfd f12,savefp12(r14)
839 lfd f13,savefp13(r14)
840 lfd f14,savefp14(r14)
841 la r11,savefp20(r14) ; Point to next line
842 lfd f15,savefp15(r14)
843 dcbt 0,r11 ; Touch line in
844 lfd f16,savefp16(r14)
845 lfd f17,savefp17(r14)
846 lfd f18,savefp18(r14)
847 la r11,savefp24(r14) ; Point to next line
848 lfd f19,savefp19(r14)
849 dcbt 0,r11 ; Touch line in
850 lfd f20,savefp20(r14)
851 lfd f21,savefp21(r14)
852 la r11,savefp28(r14) ; Point to next line
853 lfd f22,savefp22(r14)
854 lfd f23,savefp23(r14)
855 dcbt 0,r11 ; Touch line in
856 lfd f24,savefp24(r14)
857 lfd f25,savefp25(r14)
858 lfd f26,savefp26(r14)
859 lfd f27,savefp27(r14)
860 lfd f28,savefp28(r14)
861 lfd f29,savefp29(r14)
862 lfd f30,savefp30(r14)
863 lfd f31,savefp31(r14)
865 mr r3,r14 ; Get the old savearea (we popped it before)
866 bl EXT(save_ret) ; Toss it
868 fsenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
869 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
870 ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature
871 lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags
872 lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act
873 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
874 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
875 oris r11,r11,hi16(floatUsed|floatCng) ; Set that we used floating point
876 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
877 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
878 xor r3,r25,r5 ; Get the real address of the savearea
879 beq- fsnuser ; We are not user state...
880 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
881 stw r11,spcFlags(r26) ; Set per_proc copy
885 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
886 li r2,0x7F07 ; (TEST/DEBUG)
887 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
891 b EXT(exception_exit) ; Exit to the fray...
894 * Initialize the registers to some bogus value
897 MakeSureThatNoTerroristsCanHurtUsByGod:
900 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
901 li r2,0x7F06 ; (TEST/DEBUG)
902 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
905 lis r5,hi16(EXT(FloatInit)) ; Get top secret floating point init value address
906 ori r5,r5,lo16(EXT(FloatInit)) ; Slam bottom
907 lfd f0,0(r5) ; Initialize FP0
908 fmr f1,f0 ; Do them all
939 b fsenable ; Finish setting it all up...
943 ; We get here when we are switching to the same context at the same level and the context
944 ; is still live. Essentially, all we are doing is turning on the faility. It may have
945 ; gotten turned off due to doing a context save for the current level or a context switch
946 ; back to the live guy.
954 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
955 li r2,0x7F0A ; (TEST/DEBUG)
956 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
959 beq- cr1,fsenable ; Not saved yet, nothing to pop, go enable and exit...
961 lwz r11,SAVlevel(r30) ; Get the level of top saved context
962 lwz r14,SAVprev(r30) ; Get the previous savearea
964 cmplw r11,r31 ; Are live and saved the same?
966 bne+ fsenable ; Level not the same, nothing to pop, go enable and exit...
968 mr r3,r30 ; Get the old savearea (we popped it before)
969 bl EXT(save_ret) ; Toss it
970 b fsenable ; Go enable and exit...
974 ; This function invalidates any live floating point context for the passed in facility_context.
975 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
979 .globl EXT(toss_live_fpu)
984 mfmsr r9 ; Get the MSR
985 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
986 rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now?
987 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off
988 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure floats are turned off
989 mtmsr r0 ; No interruptions
991 beq+ tlfnotours ; Floats off, can not be live here...
993 mfsprg r8,0 ; Get the per proc
996 ; Note that at this point, since floats are on, we are the owner
997 ; of live state on this processor
1000 lwz r6,FPUowner(r8) ; Get the thread that owns the floats
1001 li r0,0 ; Clear this just in case we need it
1002 cmplw r6,r3 ; Are we tossing our own context?
1003 bne- tlfnotours ; Nope...
1005 fsub f1,f1,f1 ; Make a 0
1006 mtfsf 0xFF,f1 ; Clear it
1008 tlfnotours: lwz r11,FPUcpu(r3) ; Get the cpu on which we last loaded context
1009 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
1010 mulli r11,r11,ppSize ; Find offset to the owner per_proc
1011 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
1012 li r10,FPUowner ; Displacement to float owner
1013 add r11,r12,r11 ; Point to the owner per_proc
1014 li r0,0 ; Set a 0 to invalidate context
1016 tlfinvothr: lwarx r12,r10,r11 ; Get the owner
1017 cmplw r12,r3 ; Does he still have this context?
1018 bne+ tlfexit ; Nope, leave...
1019 stwcx. r0,r10,r11 ; Try to invalidate it
1020 bne- tlfinvothr ; Try again if there was a collision...
1022 tlfexit: mtmsr r9 ; Restore interruptions
1023 isync ; Could be turning off floats here
1028 * Altivec stuff is here. The techniques used are pretty identical to
1029 * the floating point. Except that we will honor the VRSAVE register
1030 * settings when loading and restoring registers.
1032 * There are two indications of saved VRs: the VRSAVE register and the vrvalid
1033 * mask. VRSAVE is set by the vector user and represents the VRs that they
1034 * say that they are using. The vrvalid mask indicates which vector registers
1035 * are saved in the savearea. Whenever context is saved, it is saved according
1036 * to the VRSAVE register. It is loaded based on VRSAVE anded with
1037 * vrvalid (all other registers are splatted with 0s). This is done because we
1038 * don't want to load any registers we don't have a copy of, we want to set them
1041 * Note that there are some oddities here when we save a context we are using.
1042 * It is really not too cool to do this, but what the hey... Anyway,
1043 * we turn vectors and fpu off before we leave.
1044 * The oddity is that if you use vectors after this, the
1045 * savearea containing the context just saved will go away. So, bottom line is
1046 * that don't use vectors until after you are done with the saved context.
1051 .globl EXT(vec_save)
1055 mfmsr r0 ; Get the MSR
1056 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off when we leave
1057 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
1058 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
1059 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp
1060 mtmsr r2 ; Set the MSR
1063 mfsprg r6,0 ; Get the per_processor block
1064 lwz r12,VMXowner(r6) ; Get the context ID for owner
1067 mr r7,r0 ; (TEST/DEBUG)
1068 li r4,0 ; (TEST/DEBUG)
1069 mr r10,r3 ; (TEST/DEBUG)
1070 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1071 mr. r3,r12 ; (TEST/DEBUG)
1072 li r2,0x5F00 ; (TEST/DEBUG)
1073 li r5,0 ; (TEST/DEBUG)
1074 beq- noowneryeu ; (TEST/DEBUG)
1075 lwz r4,VMXlevel(r12) ; (TEST/DEBUG)
1076 lwz r5,VMXsave(r12) ; (TEST/DEBUG)
1078 noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1080 mr r0,r7 ; (TEST/DEBUG)
1081 mr r3,r10 ; (TEST/DEBUG)
1083 mflr r2 ; Save the return address
1085 vsretry: mr. r12,r12 ; Anyone own the vector?
1086 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
1087 beq- vsret ; Nobody owns the vector, no save required...
1089 cmplw cr1,r3,r12 ; Is the specified context live?
1091 isync ; Force owner check first
1093 lwz r9,VMXcpu(r12) ; Get the cpu that context was last on
1094 bne- cr1,vsret ; Specified context is not live
1096 cmplw cr1,r9,r11 ; Was the context for this processor?
1097 beq+ cr1,vsgoodcpu ; Facility last used on this processor...
1099 b vsret ; Someone else claimed this...
1103 vsgoodcpu: lwz r3,VMXsave(r12) ; Get the current vector savearea for the thread
1104 lwz r10,liveVRS(r6) ; Get the right VRSave register
1105 lwz r9,VMXlevel(r12) ; Get our current level indicator
1108 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
1109 beq- cr1,vsneedone ; Never saved it, so we need an area...
1111 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
1112 mr. r10,r10 ; Is VRsave set to 0?
1113 cmplw cr1,r9,r8 ; Correct level?
1114 bne- cr1,vsneedone ; Different level, so we need to save...
1116 bne+ vsret ; VRsave is non-zero so we need to keep what is saved...
1118 lwz r4,SAVprev(r3) ; Pick up the previous area
1119 lwz r5,SAVlevel(r4) ; Get the level associated with save
1120 stw r4,VMXsave(r12) ; Dequeue this savearea
1121 stw r5,VMXlevel(r12) ; Save the level
1124 stw r3,VMXowner(r12) ; Show no live context here
1127 vsbackout: mr r12,r0 ; Set the saved MSR
1128 b EXT(save_ret_join) ; Toss the savearea and return from there...
1132 vsneedone: mr. r10,r10 ; Is VRsave set to 0?
1133 beq- vsret ; Yeah, they do not care about any of them...
1135 bl EXT(save_get) ; Get a savearea for the context
1137 mfsprg r6,0 ; Get back per_processor block
1138 li r4,SAVvector ; Get vector tag
1139 lwz r12,VMXowner(r6) ; Get back our context ID
1140 stb r4,SAVflags+2(r3) ; Mark this savearea as a vector
1141 mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it...
1142 beq- vsbackout ; If disowned, just toss savearea...
1143 lwz r4,facAct(r12) ; Get the activation associated with live context
1144 mtlr r2 ; Restore return
1145 lwz r8,VMXsave(r12) ; Get the current top vector savearea
1146 stw r4,SAVact(r3) ; Indicate the right activation for this context
1147 lwz r9,VMXlevel(r12) ; Get our current level indicator again
1148 stw r3,VMXsave(r12) ; Set this as the most current floating point context
1149 stw r8,SAVprev(r3) ; And then chain this in front
1151 stw r9,SAVlevel(r3) ; Set level in savearea
1153 mfcr r2 ; Save non-volatile CRs
1154 lwz r10,liveVRS(r6) ; Get the right VRSave register
1155 lis r9,0x5555 ; Mask with odd bits set
1156 rlwinm r11,r10,1,0,31 ; Shift over 1
1157 ori r9,r9,0x5555 ; Finish mask
1158 or r4,r10,r11 ; After this, even bits show which lines to zap
1160 andc r11,r4,r9 ; Clear out odd bits
1162 la r6,savevr0(r3) ; Point to line 0
1163 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits
1164 or r4,r11,r4 ; Set the odd bits
1165 ; (bit 0 is line 0, bit 1 is line 8,
1166 ; bit 2 is line 1, bit 3 is line 9, etc.
1167 rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1168 la r7,savevr2(r3) ; Point to line 1
1169 mtcrf 255,r4 ; Load up the CRs
1170 stw r10,savevrvalid(r3) ; Save the validity information
1171 mr r8,r6 ; Start registers off
1173 ; Save the current vector state
1176 bf 0,snol0 ; No line 0 to do...
1177 dcba br0,r6 ; Allocate cache line 0
1180 la r6,savevr4(r3) ; Point to line 2
1181 bf 2,snol1 ; No line 1 to do...
1182 dcba br0,r7 ; Allocate cache line 1
1185 la r7,savevr6(r3) ; Point to line 3
1186 bf 4,snol2 ; No line 2 to do...
1187 dcba br0,r6 ; Allocate cache line 2
1190 li r11,16 ; Get offset for odd registers
1191 bf 16,snovr0 ; Do not save VR0...
1192 stvxl v0,br0,r8 ; Save VR0
1195 la r9,savevr2(r3) ; Point to V2/V3 pair
1196 bf 17,snovr1 ; Do not save VR1...
1197 stvxl v1,r11,r8 ; Save VR1
1200 la r6,savevr8(r3) ; Point to line 4
1201 bf 6,snol3 ; No line 3 to do...
1202 dcba br0,r7 ; Allocate cache line 3
1205 la r8,savevr4(r3) ; Point to V4/V5 pair
1206 bf 18,snovr2 ; Do not save VR2...
1207 stvxl v2,br0,r9 ; Save VR2
1210 bf 19,snovr3 ; Do not save VR3...
1211 stvxl v3,r11,r9 ; Save VR3
1215 ; Note: CR4 is now free
1217 la r7,savevr10(r3) ; Point to line 5
1218 bf 8,snol4 ; No line 4 to do...
1219 dcba br0,r6 ; Allocate cache line 4
1222 la r9,savevr6(r3) ; Point to R6/R7 pair
1223 bf 20,snovr4 ; Do not save VR4...
1224 stvxl v4,br0,r8 ; Save VR4
1227 bf 21,snovr5 ; Do not save VR5...
1228 stvxl v5,r11,r8 ; Save VR5
1231 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1232 la r6,savevr12(r3) ; Point to line 6
1233 bf 10,snol5 ; No line 5 to do...
1234 dcba br0,r7 ; Allocate cache line 5
1237 la r8,savevr8(r3) ; Point to V8/V9 pair
1238 bf 22,snovr6 ; Do not save VR6...
1239 stvxl v6,br0,r9 ; Save VR6
1242 bf 23,snovr7 ; Do not save VR7...
1243 stvxl v7,r11,r9 ; Save VR7
1247 ; Note: CR5 is now free
1249 la r7,savevr14(r3) ; Point to line 7
1250 bf 12,snol6 ; No line 6 to do...
1251 dcba br0,r6 ; Allocate cache line 6
1254 la r9,savevr10(r3) ; Point to V10/V11 pair
1255 bf 24,snovr8 ; Do not save VR8...
1256 stvxl v8,br0,r8 ; Save VR8
1259 bf 25,snovr9 ; Do not save VR9...
1260 stvxl v9,r11,r8 ; Save VR9
1263 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1264 la r6,savevr16(r3) ; Point to line 8
1265 bf 14,snol7 ; No line 7 to do...
1266 dcba br0,r7 ; Allocate cache line 7
1269 la r8,savevr12(r3) ; Point to V12/V13 pair
1270 bf 26,snovr10 ; Do not save VR10...
1271 stvxl v10,br0,r9 ; Save VR10
1274 bf 27,snovr11 ; Do not save VR11...
1275 stvxl v11,r11,r9 ; Save VR11
1280 ; Note: CR6 is now free
1282 la r7,savevr18(r3) ; Point to line 9
1283 bf 1,snol8 ; No line 8 to do...
1284 dcba br0,r6 ; Allocate cache line 8
1287 la r9,savevr14(r3) ; Point to V14/V15 pair
1288 bf 28,snovr12 ; Do not save VR12...
1289 stvxl v12,br0,r8 ; Save VR12
1292 bf 29,snovr13 ; Do not save VR13...
1293 stvxl v13,r11,r8 ; Save VR13
1296 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1297 la r6,savevr20(r3) ; Point to line 10
1298 bf 3,snol9 ; No line 9 to do...
1299 dcba br0,r7 ; Allocate cache line 9
1302 la r8,savevr16(r3) ; Point to V16/V17 pair
1303 bf 30,snovr14 ; Do not save VR14...
1304 stvxl v14,br0,r9 ; Save VR14
1307 bf 31,snovr15 ; Do not save VR15...
1308 stvxl v15,r11,r9 ; Save VR15
1312 ; Note: CR7 is now free
1314 la r7,savevr22(r3) ; Point to line 11
1315 bf 5,snol10 ; No line 10 to do...
1316 dcba br0,r6 ; Allocate cache line 10
1319 la r9,savevr18(r3) ; Point to V18/V19 pair
1320 bf 16,snovr16 ; Do not save VR16...
1321 stvxl v16,br0,r8 ; Save VR16
1324 bf 17,snovr17 ; Do not save VR17...
1325 stvxl v17,r11,r8 ; Save VR17
1328 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1330 ; Note: All registers have been or are accounted for in CRs
1332 la r6,savevr24(r3) ; Point to line 12
1333 bf 7,snol11 ; No line 11 to do...
1334 dcba br0,r7 ; Allocate cache line 11
1337 la r8,savevr20(r3) ; Point to V20/V21 pair
1338 bf 18,snovr18 ; Do not save VR18...
1339 stvxl v18,br0,r9 ; Save VR18
1342 bf 19,snovr19 ; Do not save VR19...
1343 stvxl v19,r11,r9 ; Save VR19
1346 la r7,savevr26(r3) ; Point to line 13
1347 bf 9,snol12 ; No line 12 to do...
1348 dcba br0,r6 ; Allocate cache line 12
1351 la r9,savevr22(r3) ; Point to V22/V23 pair
1352 bf 20,snovr20 ; Do not save VR20...
1353 stvxl v20,br0,r8 ; Save VR20
1356 bf 21,snovr21 ; Do not save VR21...
1357 stvxl v21,r11,r8 ; Save VR21
1360 la r6,savevr28(r3) ; Point to line 14
1361 bf 11,snol13 ; No line 13 to do...
1362 dcba br0,r7 ; Allocate cache line 13
1365 la r8,savevr24(r3) ; Point to V24/V25 pair
1366 bf 22,snovr22 ; Do not save VR22...
1367 stvxl v22,br0,r9 ; Save VR22
1370 bf 23,snovr23 ; Do not save VR23...
1371 stvxl v23,r11,r9 ; Save VR23
1374 la r7,savevr30(r3) ; Point to line 15
1375 bf 13,snol14 ; No line 14 to do...
1376 dcba br0,r6 ; Allocate cache line 14
1379 la r9,savevr26(r3) ; Point to V26/V27 pair
1380 bf 24,snovr24 ; Do not save VR24...
1381 stvxl v24,br0,r8 ; Save VR24
1384 bf 25,snovr25 ; Do not save VR25...
1385 stvxl v25,r11,r8 ; Save VR25
1388 bf 15,snol15 ; No line 15 to do...
1389 dcba br0,r7 ; Allocate cache line 15
1393 ; Note: All cache lines allocated now
1395 la r8,savevr28(r3) ; Point to V28/V29 pair
1396 bf 26,snovr26 ; Do not save VR26...
1397 stvxl v26,br0,r9 ; Save VR26
1400 bf 27,snovr27 ; Do not save VR27...
1401 stvxl v27,r11,r9 ; Save VR27
1404 la r7,savevr30(r3) ; Point to V30/V31 pair
1405 bf 28,snovr28 ; Do not save VR28...
1406 stvxl v28,br0,r8 ; Save VR28
1409 bf 29,snovr29 ; Do not save VR29...
1410 stvxl v29,r11,r8 ; Save VR29
1413 bf 30,snovr30 ; Do not save VR30...
1414 stvxl v30,br0,r7 ; Save VR30
1417 bf 31,snovr31 ; Do not save VR31...
1418 stvxl v31,r11,r7 ; Save VR31
1421 mtcrf 255,r2 ; Restore all cr
1423 vsret: mtmsr r0 ; Put interrupts on if they were and vector off
1431 * Entered to handle the vector unavailable exception and
1432 * switch vector context
1434 * This code is run with virtual address mode on and interrupts off.
1436 * Upon exit, the code returns to the users context with the vector
1437 * facility turned on.
1439 * ENTRY: VM switched ON
1441 * State is saved in savearea pointed to by R4.
1442 * All other registers are free.
1447 .globl EXT(vec_switch)
1452 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1453 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1459 mfsprg r26,0 ; Get the per_processor block
1460 mfmsr r19 ; Get the current MSR
1462 mr r25,r4 ; Save the entry savearea
1463 lwz r22,VMXowner(r26) ; Get the thread that owns the vector
1464 lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread
1465 oris r19,r19,hi16(MASK(MSR_VEC)) ; Enable the vector feature
1466 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
1468 mtmsr r19 ; Enable vector instructions
1471 lwz r27,ACT_MACT_PCB(r17) ; Get the current level
1472 lwz r29,curctx(r17) ; Grab the current context anchor of the current thread
1474 ; R22 has the "old" context anchor
1475 ; R29 has the "new" context anchor
1478 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1479 li r2,0x5F01 ; (TEST/DEBUG)
1480 mr r3,r22 ; (TEST/DEBUG)
1481 mr r5,r29 ; (TEST/DEBUG)
1482 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1486 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
1488 vsvretry: mr. r22,r22 ; See if there is any live vector status
1490 beq- vsnosave ; No live context, so nothing to save...
1492 isync ; Make sure we see this in the right order
1494 lwz r30,VMXsave(r22) ; Get the top savearea
1495 cmplw cr2,r22,r29 ; Are both old and new the same context?
1496 lwz r18,VMXcpu(r22) ; Get the last CPU we ran on
1497 cmplwi cr1,r30,0 ; Anything saved yet?
1498 cmplw r18,r16 ; Make sure we are on the right processor
1499 lwz r31,VMXlevel(r22) ; Get the context level
1501 lwz r10,liveVRS(r26) ; Get the right VRSave register
1503 bne- vsnosave ; No, not on the same processor...
1506 ; Check to see if the live context has already been saved.
1507 ; Also check to see if all we are here just to re-enable the MSR
1508 ; and handle specially if so.
1511 cmplw r31,r27 ; See if the current and active levels are the same
1512 crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same
1513 li r8,0 ; Clear this
1515 beq- vsthesame ; New and old are the same, just go enable...
1517 cmplwi cr2,r10,0 ; Check VRSave to see if we really need to save anything...
1518 beq- cr1,vsmstsave ; Not saved yet, go do it...
1520 lwz r11,SAVlevel(r30) ; Get the level of top saved context
1522 cmplw r31,r11 ; Are live and saved the same?
1525 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1526 li r2,0x5F02 ; (TEST/DEBUG)
1527 mr r3,r30 ; (TEST/DEBUG)
1528 mr r5,r31 ; (TEST/DEBUG)
1529 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1533 bne- vsmstsave ; Live context has not been saved yet...
1535 bne- cr2,vsnosave ; Live context saved and VRSave not 0, no save and keep context...
1537 lwz r4,SAVprev(r30) ; Pick up the previous area
1538 li r5,0 ; Assume this is the only one (which should be the ususal case)
1539 mr. r4,r4 ; Was this the only one?
1540 stw r4,VMXsave(r22) ; Dequeue this savearea
1541 beq+ vsonlyone ; This was the only one...
1542 lwz r5,SAVlevel(r4) ; Get the level associated with previous save
1544 vsonlyone: stw r5,VMXlevel(r22) ; Save the level
1545 stw r8,VMXowner(r26) ; Clear owner
1547 mr r3,r30 ; Copy the savearea we are tossing
1548 bl EXT(save_ret) ; Toss the savearea
1549 b vsnosave ; Go load up the context...
1554 vsmstsave: stw r8,VMXowner(r26) ; Clear owner
1556 beq- cr2,vsnosave ; The VRSave was 0, so there is nothing to save...
1558 bl EXT(save_get) ; Go get a savearea
1560 lwz r12,facAct(r22) ; Get the activation associated with the context
1561 stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread
1563 stw r30,SAVprev(r3) ; Point us to the old context
1564 stw r31,SAVlevel(r3) ; Tag our level
1565 li r7,SAVvector ; Get the vector ID
1566 stw r12,SAVact(r3) ; Make sure we point to the right guy
1567 stb r7,SAVflags+2(r3) ; Set that we have a vector save area
1570 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1571 li r2,0x5F03 ; (TEST/DEBUG)
1572 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1576 lwz r10,liveVRS(r26) ; Get the right VRSave register
1577 lis r9,0x5555 ; Mask with odd bits set
1578 rlwinm r11,r10,1,0,31 ; Shift over 1
1579 ori r9,r9,0x5555 ; Finish mask
1580 or r21,r10,r11 ; After this, even bits show which lines to zap
1582 andc r13,r21,r9 ; Clear out odd bits
1584 la r11,savevr0(r3) ; Point to line 0
1585 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1586 or r24,r13,r24 ; Set the odd bits
1587 ; (bit 0 is line 0, bit 1 is line 8,
1588 ; bit 2 is line 1, bit 3 is line 9, etc.
1589 rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1590 la r21,savevr2(r3) ; Point to line 1
1591 mtcrf 255,r24 ; Load up the CRs
1592 stw r10,savevrvalid(r3) ; Save the validity information
1593 mr r12,r11 ; Start registers off
1595 ; Save the current vector state
1598 bf 0,nol0 ; No line 0 to do...
1599 dcba br0,r11 ; Allocate cache line 0
1602 la r11,savevr4(r3) ; Point to line 2
1603 bf 2,nol1 ; No line 1 to do...
1604 dcba br0,r21 ; Allocate cache line 1
1607 la r21,savevr6(r3) ; Point to line 3
1608 bf 4,nol2 ; No line 2 to do...
1609 dcba br0,r11 ; Allocate cache line 2
1612 li r14,16 ; Get offset for odd registers
1613 bf 16,novr0 ; Do not save VR0...
1614 stvxl v0,br0,r12 ; Save VR0
1617 la r13,savevr2(r3) ; Point to V2/V3 pair
1618 bf 17,novr1 ; Do not save VR1...
1619 stvxl v1,r14,r12 ; Save VR1
1622 la r11,savevr8(r3) ; Point to line 4
1623 bf 6,nol3 ; No line 3 to do...
1624 dcba br0,r21 ; Allocate cache line 3
1627 la r12,savevr4(r3) ; Point to V4/V5 pair
1628 bf 18,novr2 ; Do not save VR2...
1629 stvxl v2,br0,r13 ; Save VR2
1632 bf 19,novr3 ; Do not save VR3...
1633 stvxl v3,r14,r13 ; Save VR3
1637 ; Note: CR4 is now free
1639 la r21,savevr10(r3) ; Point to line 5
1640 bf 8,nol4 ; No line 4 to do...
1641 dcba br0,r11 ; Allocate cache line 4
1644 la r13,savevr6(r3) ; Point to R6/R7 pair
1645 bf 20,novr4 ; Do not save VR4...
1646 stvxl v4,br0,r12 ; Save VR4
1649 bf 21,novr5 ; Do not save VR5...
1650 stvxl v5,r14,r12 ; Save VR5
1653 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1654 la r11,savevr12(r3) ; Point to line 6
1655 bf 10,nol5 ; No line 5 to do...
1656 dcba br0,r21 ; Allocate cache line 5
1659 la r12,savevr8(r3) ; Point to V8/V9 pair
1660 bf 22,novr6 ; Do not save VR6...
1661 stvxl v6,br0,r13 ; Save VR6
1664 bf 23,novr7 ; Do not save VR7...
1665 stvxl v7,r14,r13 ; Save VR7
1669 ; Note: CR5 is now free
1671 la r21,savevr14(r3) ; Point to line 7
1672 bf 12,nol6 ; No line 6 to do...
1673 dcba br0,r11 ; Allocate cache line 6
1676 la r13,savevr10(r3) ; Point to V10/V11 pair
1677 bf 24,novr8 ; Do not save VR8...
1678 stvxl v8,br0,r12 ; Save VR8
1681 bf 25,novr9 ; Do not save VR9...
1682 stvxl v9,r14,r12 ; Save VR9
1685 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1686 la r11,savevr16(r3) ; Point to line 8
1687 bf 14,nol7 ; No line 7 to do...
1688 dcba br0,r21 ; Allocate cache line 7
1691 la r12,savevr12(r3) ; Point to V12/V13 pair
1692 bf 26,novr10 ; Do not save VR10...
1693 stvxl v10,br0,r13 ; Save VR10
1696 bf 27,novr11 ; Do not save VR11...
1697 stvxl v11,r14,r13 ; Save VR11
1702 ; Note: CR6 is now free
1704 la r21,savevr18(r3) ; Point to line 9
1705 bf 1,nol8 ; No line 8 to do...
1706 dcba br0,r11 ; Allocate cache line 8
1709 la r13,savevr14(r3) ; Point to V14/V15 pair
1710 bf 28,novr12 ; Do not save VR12...
1711 stvxl v12,br0,r12 ; Save VR12
1714 bf 29,novr13 ; Do not save VR13...
1715 stvxl v13,r14,r12 ; Save VR13
1718 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1719 la r11,savevr20(r3) ; Point to line 10
1720 bf 3,nol9 ; No line 9 to do...
1721 dcba br0,r21 ; Allocate cache line 9
1724 la r12,savevr16(r3) ; Point to V16/V17 pair
1725 bf 30,novr14 ; Do not save VR14...
1726 stvxl v14,br0,r13 ; Save VR14
1729 bf 31,novr15 ; Do not save VR15...
1730 stvxl v15,r14,r13 ; Save VR15
1734 ; Note: CR7 is now free
1736 la r21,savevr22(r3) ; Point to line 11
1737 bf 5,nol10 ; No line 10 to do...
1738 dcba br0,r11 ; Allocate cache line 10
1741 la r13,savevr18(r3) ; Point to V18/V19 pair
1742 bf 16,novr16 ; Do not save VR16...
1743 stvxl v16,br0,r12 ; Save VR16
1746 bf 17,novr17 ; Do not save VR17...
1747 stvxl v17,r14,r12 ; Save VR17
1750 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1752 ; Note: All registers have been or are accounted for in CRs
1754 la r11,savevr24(r3) ; Point to line 12
1755 bf 7,nol11 ; No line 11 to do...
1756 dcba br0,r21 ; Allocate cache line 11
1759 la r12,savevr20(r3) ; Point to V20/V21 pair
1760 bf 18,novr18 ; Do not save VR18...
1761 stvxl v18,br0,r13 ; Save VR18
1764 bf 19,novr19 ; Do not save VR19...
1765 stvxl v19,r14,r13 ; Save VR19
1768 la r21,savevr26(r3) ; Point to line 13
1769 bf 9,nol12 ; No line 12 to do...
1770 dcba br0,r11 ; Allocate cache line 12
1773 la r13,savevr22(r3) ; Point to V22/V23 pair
1774 bf 20,novr20 ; Do not save VR20...
1775 stvxl v20,br0,r12 ; Save VR20
1778 bf 21,novr21 ; Do not save VR21...
1779 stvxl v21,r14,r12 ; Save VR21
1782 la r11,savevr28(r3) ; Point to line 14
1783 bf 11,nol13 ; No line 13 to do...
1784 dcba br0,r21 ; Allocate cache line 13
1787 la r12,savevr24(r3) ; Point to V24/V25 pair
1788 bf 22,novr22 ; Do not save VR22...
1789 stvxl v22,br0,r13 ; Save VR22
1792 bf 23,novr23 ; Do not save VR23...
1793 stvxl v23,r14,r13 ; Save VR23
1796 la r21,savevr30(r3) ; Point to line 15
1797 bf 13,nol14 ; No line 14 to do...
1798 dcba br0,r11 ; Allocate cache line 14
1801 la r13,savevr26(r3) ; Point to V26/V27 pair
1802 bf 24,novr24 ; Do not save VR24...
1803 stvxl v24,br0,r12 ; Save VR24
1806 bf 25,novr25 ; Do not save VR25...
1807 stvxl v25,r14,r12 ; Save VR25
1810 bf 15,nol15 ; No line 15 to do...
1811 dcba br0,r21 ; Allocate cache line 15
1815 ; Note: All cache lines allocated now
1817 la r12,savevr28(r3) ; Point to V28/V29 pair
1818 bf 26,novr26 ; Do not save VR26...
1819 stvxl v26,br0,r13 ; Save VR26
1822 bf 27,novr27 ; Do not save VR27...
1823 stvxl v27,r14,r13 ; Save VR27
1826 la r13,savevr30(r3) ; Point to V30/V31 pair
1827 bf 28,novr28 ; Do not save VR28...
1828 stvxl v28,br0,r12 ; Save VR28
1831 bf 29,novr29 ; Do not save VR29...
1832 stvxl v29,r14,r12 ; Save VR29
1835 bf 30,novr30 ; Do not save VR30...
1836 stvxl v30,br0,r13 ; Save VR30
1839 bf 31,novr31 ; Do not save VR31...
1840 stvxl v31,r14,r13 ; Save VR31
1847 ; The context is all saved now and the facility is free.
1849 ; If we do not we need to fill the registers with junk, because this level has
1850 ; never used them before and some thieving bastard could hack the old values
1851 ; of some thread! Just imagine what would happen if they could! Why, nothing
1852 ; would be safe! My God! It is terrifying!
1854 ; Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian)
1855 ; constant that we may need to fill unused vector registers.
1861 vsnosave: vspltisb v31,-10 ; Get 0xF6F6F6F6
1862 lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
1863 vspltisb v30,5 ; Get 0x05050505
1864 lwz r19,VMXcpu(r29) ; Get the last CPU we ran on
1865 vspltish v29,4 ; Get 0x00040004
1866 lwz r14,VMXsave(r29) ; Point to the top of the "new" context stack
1867 vrlb v31,v31,v30 ; Get 0xDEDEDEDE
1869 stw r16,VMXcpu(r29) ; Claim context for us
1873 lwz r13,VMXlevel(r29) ; (TEST/DEBUG)
1874 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1875 li r2,0x5F04 ; (TEST/DEBUG)
1876 mr r1,r15 ; (TEST/DEBUG)
1877 mr r3,r14 ; (TEST/DEBUG)
1878 mr r5,r13 ; (TEST/DEBUG)
1879 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1883 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
1884 vspltisb v28,-2 ; Get 0xFEFEFEFE
1885 mulli r19,r19,ppSize ; Find offset to the owner per_proc
1886 vsubuhm v31,v31,v29 ; Get 0xDEDADEDA
1887 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
1888 vpkpx v30,v28,v3 ; Get 0x7FFF7FFF
1889 li r16,VMXowner ; Displacement to vector owner
1890 add r19,r18,r19 ; Point to the owner per_proc
1891 vrlb v31,v31,v29 ; Get 0xDEADDEAD
1894 vsinvothr: lwarx r18,r16,r19 ; Get the owner
1895 cmplw r18,r29 ; Does he still have this context?
1896 bne vsinvoths ; Nope...
1897 stwcx. r0,r16,r19 ; Try to invalidate it
1898 bne- vsinvothr ; Try again if there was a collision...
1901 vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
1902 vmrghh v31,v30,v31 ; Get 0x7FFFDEAD. V31 keeps this value until the bitter end
1903 stw r15,VMXlevel(r29) ; Set the "new" active level
1905 stw r29,VMXowner(r26) ; Mark us as having the live context
1907 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
1909 lwz r3,SAVprev(r14) ; Get the previous context
1910 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
1911 cmplw r0,r15 ; Top level correct to load?
1912 bne- ProtectTheAmericanWay ; No, go initialize...
1914 stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later)
1917 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1918 li r2,0x5F05 ; (TEST/DEBUG)
1919 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1923 lwz r22,savevrsave(r25) ; Get the most current VRSAVE
1924 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
1925 lis r9,0x5555 ; Mask with odd bits set
1926 and r10,r10,r22 ; Figure out just what registers need to be loaded
1927 ori r9,r9,0x5555 ; Finish mask
1928 rlwinm r11,r10,1,0,31 ; Shift over 1
1929 or r12,r10,r11 ; After this, even bits show which lines to touch
1930 andc r13,r12,r9 ; Clear out odd bits
1932 la r20,savevr0(r14) ; Point to line 0
1933 rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1934 la r21,savevr2(r3) ; Point to line 1
1935 or r3,r13,r3 ; Set the odd bits
1936 ; (bit 0 is line 0, bit 1 is line 8,
1937 ; bit 2 is line 1, bit 3 is line 9, etc.
1938 rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1939 mtcrf 255,r3 ; Load up the CRs
1940 mr r22,r20 ; Start registers off
1942 ; Load the new vector state
1945 bf 0,lnol0 ; No line 0 to do...
1946 dcbt br0,r20 ; Touch cache line 0
1949 la r20,savevr4(r14) ; Point to line 2
1950 bf 2,lnol1 ; No line 1 to do...
1951 dcbt br0,r21 ; Touch cache line 1
1954 la r21,savevr6(r14) ; Point to line 3
1955 bf 4,lnol2 ; No line 2 to do...
1956 dcbt br0,r20 ; Touch cache line 2
1959 li r30,16 ; Get offset for odd registers
1960 bf 16,lnovr0 ; Do not restore VR0...
1961 lvxl v0,br0,r22 ; Restore VR0
1964 la r23,savevr2(r14) ; Point to V2/V3 pair
1965 bf 17,lnovr1 ; Do not restore VR1...
1966 lvxl v1,r30,r22 ; Restore VR1
1969 la r20,savevr8(r14) ; Point to line 4
1970 bf 6,lnol3 ; No line 3 to do...
1971 dcbt br0,r21 ; Touch cache line 3
1974 la r22,savevr4(r14) ; Point to V4/V5 pair
1975 bf 18,lnovr2 ; Do not restore VR2...
1976 lvxl v2,br0,r23 ; Restore VR2
1979 bf 19,lnovr3 ; Do not restore VR3...
1980 lvxl v3,r30,r23 ; Restore VR3
1984 ; Note: CR4 is now free
1986 la r21,savevr10(r14) ; Point to line 5
1987 bf 8,lnol4 ; No line 4 to do...
1988 dcbt br0,r20 ; Touch cache line 4
1991 la r23,savevr6(r14) ; Point to R6/R7 pair
1992 bf 20,lnovr4 ; Do not restore VR4...
1993 lvxl v4,br0,r22 ; Restore VR4
1996 bf 21,lnovr5 ; Do not restore VR5...
1997 lvxl v5,r30,r22 ; Restore VR5
2000 mtcrf 0x08,r10 ; Set CRs for registers 16-19
2001 la r20,savevr12(r14) ; Point to line 6
2002 bf 10,lnol5 ; No line 5 to do...
2003 dcbt br0,r21 ; Touch cache line 5
2006 la r22,savevr8(r14) ; Point to V8/V9 pair
2007 bf 22,lnovr6 ; Do not restore VR6...
2008 lvxl v6,br0,r23 ; Restore VR6
2011 bf 23,lnovr7 ; Do not restore VR7...
2012 lvxl v7,r30,r23 ; Restore VR7
2016 ; Note: CR5 is now free
2018 la r21,savevr14(r14) ; Point to line 7
2019 bf 12,lnol6 ; No line 6 to do...
2020 dcbt br0,r20 ; Touch cache line 6
2023 la r23,savevr10(r14) ; Point to V10/V11 pair
2024 bf 24,lnovr8 ; Do not restore VR8...
2025 lvxl v8,br0,r22 ; Restore VR8
2028 bf 25,lnovr9 ; Do not save VR9...
2029 lvxl v9,r30,r22 ; Restore VR9
2032 mtcrf 0x04,r10 ; Set CRs for registers 20-23
2033 la r20,savevr16(r14) ; Point to line 8
2034 bf 14,lnol7 ; No line 7 to do...
2035 dcbt br0,r21 ; Touch cache line 7
2038 la r22,savevr12(r14) ; Point to V12/V13 pair
2039 bf 26,lnovr10 ; Do not restore VR10...
2040 lvxl v10,br0,r23 ; Restore VR10
2043 bf 27,lnovr11 ; Do not restore VR11...
2044 lvxl v11,r30,r23 ; Restore VR11
2049 ; Note: CR6 is now free
2051 la r21,savevr18(r14) ; Point to line 9
2052 bf 1,lnol8 ; No line 8 to do...
2053 dcbt br0,r20 ; Touch cache line 8
2056 la r23,savevr14(r14) ; Point to V14/V15 pair
2057 bf 28,lnovr12 ; Do not restore VR12...
2058 lvxl v12,br0,r22 ; Restore VR12
2061 bf 29,lnovr13 ; Do not restore VR13...
2062 lvxl v13,r30,r22 ; Restore VR13
2065 mtcrf 0x02,r10 ; Set CRs for registers 24-27
2066 la r20,savevr20(r14) ; Point to line 10
2067 bf 3,lnol9 ; No line 9 to do...
2068 dcbt br0,r21 ; Touch cache line 9
2071 la r22,savevr16(r14) ; Point to V16/V17 pair
2072 bf 30,lnovr14 ; Do not restore VR14...
2073 lvxl v14,br0,r23 ; Restore VR14
2076 bf 31,lnovr15 ; Do not restore VR15...
2077 lvxl v15,r30,r23 ; Restore VR15
2081 ; Note: CR7 is now free
2083 la r21,savevr22(r14) ; Point to line 11
2084 bf 5,lnol10 ; No line 10 to do...
2085 dcbt br0,r20 ; Touch cache line 10
2088 la r23,savevr18(r14) ; Point to V18/V19 pair
2089 bf 16,lnovr16 ; Do not restore VR16...
2090 lvxl v16,br0,r22 ; Restore VR16
2093 bf 17,lnovr17 ; Do not restore VR17...
2094 lvxl v17,r30,r22 ; Restore VR17
2097 mtcrf 0x01,r10 ; Set CRs for registers 28-31
2099 ; Note: All registers have been or are accounted for in CRs
2101 la r20,savevr24(r14) ; Point to line 12
2102 bf 7,lnol11 ; No line 11 to do...
2103 dcbt br0,r21 ; Touch cache line 11
2106 la r22,savevr20(r14) ; Point to V20/V21 pair
2107 bf 18,lnovr18 ; Do not restore VR18...
2108 lvxl v18,br0,r23 ; Restore VR18
2111 bf 19,lnovr19 ; Do not restore VR19...
2112 lvxl v19,r30,r23 ; Restore VR19
2115 la r21,savevr26(r14) ; Point to line 13
2116 bf 9,lnol12 ; No line 12 to do...
2117 dcbt br0,r20 ; Touch cache line 12
2120 la r23,savevr22(r14) ; Point to V22/V23 pair
2121 bf 20,lnovr20 ; Do not restore VR20...
2122 lvxl v20,br0,r22 ; Restore VR20
2125 bf 21,lnovr21 ; Do not restore VR21...
2126 lvxl v21,r30,r22 ; Restore VR21
2129 la r20,savevr28(r14) ; Point to line 14
2130 bf 11,lnol13 ; No line 13 to do...
2131 dcbt br0,r21 ; Touch cache line 13
2134 la r22,savevr24(r14) ; Point to V24/V25 pair
2135 bf 22,lnovr22 ; Do not restore VR22...
2136 lvxl v22,br0,r23 ; Restore VR22
2139 bf 23,lnovr23 ; Do not restore VR23...
2140 lvxl v23,r30,r23 ; Restore VR23
2143 la r21,savevr30(r14) ; Point to line 15
2144 bf 13,lnol14 ; No line 14 to do...
2145 dcbt br0,r20 ; Touch cache line 14
2148 la r23,savevr26(r14) ; Point to V26/V27 pair
2149 bf 24,lnovr24 ; Do not restore VR24...
2150 lvxl v24,br0,r22 ; Restore VR24
2153 bf 25,lnovr25 ; Do not restore VR25...
2154 lvxl v25,r30,r22 ; Restore VR25
2157 bf 15,lnol15 ; No line 15 to do...
2158 dcbt br0,r21 ; Touch cache line 15
2162 ; Note: All needed cache lines have been touched now
2164 la r22,savevr28(r14) ; Point to V28/V29 pair
2165 bf 26,lnovr26 ; Do not restore VR26...
2166 lvxl v26,br0,r23 ; Restore VR26
2169 bf 27,lnovr27 ; Do not restore VR27...
2170 lvxl v27,r30,r23 ; Restore VR27
2173 la r23,savevr30(r14) ; Point to V30/V31 pair
2174 bf 28,lnovr28 ; Do not restore VR28...
2175 lvxl v28,br0,r22 ; Restore VR28
2178 bf 29,lnovr29 ; Do not restore VR29...
2179 lvxl v29,r30,r22 ; Restore VR29
2182 bf 30,lnovr30 ; Do not restore VR30...
2183 lvxl v30,br0,r23 ; Restore VR30
2187 ; Everything is restored now except for VR31. We need it to get
2188 ; the QNaNBarbarian value to put into idle vector registers.
2189 ; Note: V31 was set above to QNaNbarbarian
2192 cmpwi r10,-1 ; Handle the quick case of all registers in use
2193 beq- mstlvr31 ; Not likely, but all are in use...
2194 mtcrf 255,r10 ; Get mask of valid registers
2196 bt 0,ni0 ; Register is ok already...
2197 vor v0,v31,v31 ; Copy into the next register
2199 bt 1,ni1 ; Register is ok already...
2200 vor v1,v31,v31 ; Copy into the next register
2202 bt 2,ni2 ; Register is ok already...
2203 vor v2,v31,v31 ; Copy into the next register
2205 bt 3,ni3 ; Register is ok already...
2206 vor v3,v31,v31 ; Copy into the next register
2208 bt 4,ni4 ; Register is ok already...
2209 vor v4,v31,v31 ; Copy into the next register
2211 bt 5,ni5 ; Register is ok already...
2212 vor v5,v31,v31 ; Copy into the next register
2214 bt 6,ni6 ; Register is ok already...
2215 vor v6,v31,v31 ; Copy into the next register
2217 bt 7,ni7 ; Register is ok already...
2218 vor v7,v31,v31 ; Copy into the next register
2220 bt 8,ni8 ; Register is ok already...
2221 vor v8,v31,v31 ; Copy into the next register
2223 bt 9,ni9 ; Register is ok already...
2224 vor v9,v31,v31 ; Copy into the next register
2226 bt 10,ni10 ; Register is ok already...
2227 vor v10,v31,v31 ; Copy into the next register
2229 bt 11,ni11 ; Register is ok already...
2230 vor v11,v31,v31 ; Copy into the next register
2232 bt 12,ni12 ; Register is ok already...
2233 vor v12,v31,v31 ; Copy into the next register
2235 bt 13,ni13 ; Register is ok already...
2236 vor v13,v31,v31 ; Copy into the next register
2238 bt 14,ni14 ; Register is ok already...
2239 vor v14,v31,v31 ; Copy into the next register
2241 bt 15,ni15 ; Register is ok already...
2242 vor v15,v31,v31 ; Copy into the next register
2244 bt 16,ni16 ; Register is ok already...
2245 vor v16,v31,v31 ; Copy into the next register
2247 bt 17,ni17 ; Register is ok already...
2248 vor v17,v31,v31 ; Copy into the next register
2250 bt 18,ni18 ; Register is ok already...
2251 vor v18,v31,v31 ; Copy into the next register
2253 bt 19,ni19 ; Register is ok already...
2254 vor v19,v31,v31 ; Copy into the next register
2256 bt 20,ni20 ; Register is ok already...
2257 vor v20,v31,v31 ; Copy into the next register
2259 bt 21,ni21 ; Register is ok already...
2260 vor v21,v31,v31 ; Copy into the next register
2262 bt 22,ni22 ; Register is ok already...
2263 vor v22,v31,v31 ; Copy into the next register
2265 bt 23,ni23 ; Register is ok already...
2266 vor v23,v31,v31 ; Copy into the next register
2268 bt 24,ni24 ; Register is ok already...
2269 vor v24,v31,v31 ; Copy into the next register
2271 bt 25,ni25 ; Register is ok already...
2272 vor v25,v31,v31 ; Copy into the next register
2274 bt 26,ni26 ; Register is ok already...
2275 vor v26,v31,v31 ; Copy into the next register
2277 bt 27,ni27 ; Register is ok already...
2278 vor v27,v31,v31 ; Copy into the next register
2280 bt 28,ni28 ; Register is ok already...
2281 vor v28,v31,v31 ; Copy into the next register
2283 bt 29,ni29 ; Register is ok already...
2284 vor v29,v31,v31 ; Copy into the next register
2286 bt 30,ni30 ; Register is ok already...
2287 vor v30,v31,v31 ; Copy into the next register
2289 bf 31,lnovr31 ; V31 is empty, no need to restore...
2291 mstlvr31: lvxl v31,r30,r23 ; Restore VR31
2293 lnovr31: mr r3,r14 ; Get the old savearea (we popped it before)
2294 bl EXT(save_ret) ; Toss it
2296 vrenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
2297 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
2298 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
2299 lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags
2300 lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act
2301 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
2302 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2303 oris r11,r11,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2304 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
2305 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
2306 xor r3,r25,r5 ; Get the real address of the savearea
2307 beq- vrnuser ; We are not user state...
2308 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
2309 stw r11,spcFlags(r26) ; Set per_proc copy
2313 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2314 li r2,0x5F07 ; (TEST/DEBUG)
2315 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2318 b EXT(exception_exit) ; Exit to the fray...
2321 * Initialize the registers to some bogus value
2324 ProtectTheAmericanWay:
2327 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2328 li r2,0x5F06 ; (TEST/DEBUG)
2329 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2333 vor v0,v31,v31 ; Copy into the next register
2334 vor v1,v31,v31 ; Copy into the next register
2335 vor v2,v31,v31 ; Copy into the next register
2336 vor v3,v31,v31 ; Copy into the next register
2337 vor v4,v31,v31 ; Copy into the next register
2338 vor v5,v31,v31 ; Copy into the next register
2339 vor v6,v31,v31 ; Copy into the next register
2340 vor v7,v31,v31 ; Copy into the next register
2341 vor v8,v31,v31 ; Copy into the next register
2342 vor v9,v31,v31 ; Copy into the next register
2343 vor v10,v31,v31 ; Copy into the next register
2344 vor v11,v31,v31 ; Copy into the next register
2345 vor v12,v31,v31 ; Copy into the next register
2346 vor v13,v31,v31 ; Copy into the next register
2347 vor v14,v31,v31 ; Copy into the next register
2348 vor v15,v31,v31 ; Copy into the next register
2349 vor v16,v31,v31 ; Copy into the next register
2350 vor v17,v31,v31 ; Copy into the next register
2351 vor v18,v31,v31 ; Copy into the next register
2352 vor v19,v31,v31 ; Copy into the next register
2353 vor v20,v31,v31 ; Copy into the next register
2354 vor v21,v31,v31 ; Copy into the next register
2355 vor v22,v31,v31 ; Copy into the next register
2356 vor v23,v31,v31 ; Copy into the next register
2357 vor v24,v31,v31 ; Copy into the next register
2358 vor v25,v31,v31 ; Copy into the next register
2359 vor v26,v31,v31 ; Copy into the next register
2360 vor v27,v31,v31 ; Copy into the next register
2361 vor v28,v31,v31 ; Copy into the next register
2362 vor v29,v31,v31 ; Copy into the next register
2363 vor v30,v31,v31 ; Copy into the next register
2364 b vrenable ; Finish setting it all up...
2369 ; We get here when we are switching to the same context at the same level and the context
2370 ; is still live. Essentially, all we are doing is turning on the faility. It may have
2371 ; gotten turned off due to doing a context save for the current level or a context switch
2372 ; back to the live guy.
2380 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2381 li r2,0x5F0A ; (TEST/DEBUG)
2382 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2385 beq- cr1,vrenable ; Not saved yet, nothing to pop, go enable and exit...
2387 lwz r11,SAVlevel(r30) ; Get the level of top saved context
2388 lwz r14,SAVprev(r30) ; Get the previous savearea
2390 cmplw r11,r31 ; Are live and saved the same?
2392 bne+ vrenable ; Level not the same, nothing to pop, go enable and exit...
2394 mr r3,r30 ; Get the old savearea (we popped it before)
2395 bl EXT(save_ret) ; Toss it
2396 b vrenable ; Go enable and exit...
2400 ; This function invalidates any live vector context for the passed in facility_context.
2401 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
2405 .globl EXT(toss_live_vec)
2409 mfmsr r9 ; Get the MSR
2410 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
2411 rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now?
2412 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vector is turned off
2413 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure fpu is turned off
2414 mtmsr r0 ; No interruptions
2416 beq+ tlvnotours ; Vector off, can not be live here...
2418 mfsprg r8,0 ; Get the per proc
2421 ; Note that at this point, since vecs are on, we are the owner
2422 ; of live state on this processor
2425 lwz r6,VMXowner(r8) ; Get the thread that owns the vector
2426 li r0,0 ; Clear this just in case we need it
2427 cmplw r6,r3 ; Are we tossing our own context?
2428 bne- tlvnotours ; Nope...
2430 vspltish v1,1 ; Turn on the non-Java bit and saturate
2431 vspltisw v0,1 ; Turn on the saturate bit
2432 vxor v1,v1,v0 ; Turn off saturate
2433 mtspr vrsave,r0 ; Clear VRSAVE
2434 mtvscr v1 ; Set the non-java, no saturate status
2436 tlvnotours: lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2437 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2438 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2439 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2440 li r10,VMXowner ; Displacement to vector owner
2441 add r11,r12,r11 ; Point to the owner per_proc
2442 li r0,0 ; Set a 0 to invalidate context
2444 tlvinvothr: lwarx r12,r10,r11 ; Get the owner
2445 cmplw r12,r3 ; Does he still have this context?
2446 bne+ tlvexit ; Nope, leave...
2447 stwcx. r0,r10,r11 ; Try to invalidate it
2448 bne- tlvinvothr ; Try again if there was a collision...
2450 tlvexit: mtmsr r9 ; Restore interruptions
2451 isync ; Could be turning off vectors here
2456 ; This function invalidates any live vector context for the passed in facility_context
2457 ; if the level is current. It also tosses the corresponding savearea if there is one.
2458 ; This function is primarily used whenever we detect a VRSave that is all zeros.
2462 .globl EXT(vec_trash)
2466 lwz r12,facAct(r3) ; Get the activation
2467 lwz r11,VMXlevel(r3) ; Get the context level
2468 lwz r10,ACT_MACT_PCB(r12) ; Grab the current level for the thread
2469 lwz r9,VMXsave(r3) ; Get the savearea, if any
2470 cmplw r10,r11 ; Are we at the right level?
2471 cmplwi cr1,r9,0 ; Remember if there is a savearea
2472 bnelr+ ; No, we do nothing...
2474 lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2475 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2476 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2477 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2478 li r10,VMXowner ; Displacement to vector owner
2479 add r11,r12,r11 ; Point to the owner per_proc
2480 li r0,0 ; Set a 0 to invalidate context
2482 vtinvothr: lwarx r12,r10,r11 ; Get the owner
2483 cmplw r12,r3 ; Does he still have this context?
2484 bne vtnotlive ; Nope, not live anywhere...
2485 stwcx. r0,r10,r11 ; Try to invalidate it
2486 bne- vtinvothr ; Try again if there was a collision...
2488 vtnotlive: beqlr+ cr1 ; Leave if there is no savearea
2489 lwz r8,SAVlevel(r9) ; Get the level of the savearea
2490 cmplw r8,r11 ; Savearea for the current level?
2491 bnelr+ ; No, nothing to release...
2493 lwz r8,SAVprev(r9) ; Pick up the previous area
2494 mr. r8,r8 ; Is there a previous?
2495 beq- vtnoprev ; Nope...
2496 lwz r7,SAVlevel(r8) ; Get the level associated with save
2498 vtnoprev: stw r8,VMXsave(r3) ; Dequeue this savearea
2499 stw r7,VMXlevel(r3) ; Pop the level
2501 mr r3,r9 ; Get the savearea to release
2502 b EXT(save_ret) ; Go and toss the save area (note, we will return from there)...
2506 ; Just some test code to force vector and/or floating point in the kernel
2510 .globl EXT(fctx_test)
2514 mfsprg r3,0 ; Get the per_proc block
2515 lwz r3,PP_ACTIVE_THREAD(r3) ; Get the thread pointer
2516 mr. r3,r3 ; Are we actually up and running?
2519 fmr f0,f0 ; Use floating point
2520 mftb r4 ; Get time base for a random number
2521 li r5,1 ; Get a potential vrsave to use
2522 andi. r4,r4,0x3F ; Get a number from 0 - 63
2523 slw r5,r5,r4 ; Choose a register to save (should be 0 half the time)
2524 mtspr vrsave,r5 ; Set VRSave
2525 vor v0,v0,v0 ; Use vectors