2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
27 #include <ppc/proc_reg.h>
31 #include <mach/ppc/vm_param.h>
32 #include <ppc/exception.h>
33 #include <ppc/savearea.h>
41 * void load_context(thread_t thread)
43 * Load the context for the first kernel thread, and go.
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.
51 .globl EXT(load_context)
55 .globl EXT(Load_context)
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
68 * get new thread pointer and set it into the active_threads pointer
73 lwz r0,PP_INTSTACK_TOP_SS(r6)
74 stw r0,PP_ISTACKPTR(r6)
75 stw r3,PP_ACTIVE_THREAD(r6)
77 /* Find the new stack and store it in active_stacks */
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 */
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... */
98 /* struct thread_shuttle *Switch_context(struct thread_shuttle *old,
100 * struct thread_shuttle *new)
102 * Switch from one thread to another. If a continuation is supplied, then
103 * we do not need to save callee save registers.
107 /* void Call_continuation( void (*continuation)(void), vm_offset_t stack_ptr)
111 .globl EXT(Call_continuation)
113 LEXT(Call_continuation)
116 mr r1, r4 /* Load new stack pointer */
117 blr /* Jump to the continuation */
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
128 /* Context switches are double jumps. We pass the following to the
129 * context switch firmware call:
131 * R3 = switchee's savearea
136 * savesrr0 is set to go to switch_in
137 * savesrr1 is set to uninterruptible with translation on
142 .globl EXT(Switch_context)
146 mfsprg r12,0 ; Get the per_proc block
147 lwz r10,PP_ACTIVE_STACKS(r12) ; Get the pointer to the current stack
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
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
159 * Make the new thread the current thread.
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
165 lwz r11,THREAD_KERNEL_STACK(r5) ; Get the new stack pointer
167 lwz r5,THREAD_TOP_ACT(r5) ; Get the new activation
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
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)
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"
184 lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment
186 lwz r7,ACT_MACT_SPF(r5) ; Get the special flags
188 lwz r10,ACT_KLOADED(r5)
189 stw r11,ppbbTaskEnv(r12) ; Save the bb task env
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
200 stw r0,0(r10) /* act_kloaded = 0 */
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
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 */
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 */
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...
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...
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...
243 mr. r10,r10 ; Is there a savearea here?
244 ori r6,r6,lo16(MASK(MSR_FP)) ; Enable floating point
246 beq- cswnofloat ; No savearea to check...
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?
252 bne+ cswnofloat ; Nope...
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
261 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
262 li r2,0x4401 ; (TEST/DEBUG)
263 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
265 lhz r0,PP_CPU_NUMBER(r12) ; (TEST/DEBUG)
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...
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...
281 cswnofloat: bne+ cr5,cswnovect ; Vector is not ours...
283 lwz r10,VMXlevel(r2) ; Get the live level
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...
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...
293 mr. r10,r10 ; Is there a savearea here?
294 oris r6,r6,hi16(MASK(MSR_VEC)) ; Enable vector
296 beq- cswnovect ; No savearea to check...
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?
302 bne+ cswnovect ; Nope...
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
311 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
312 li r2,0x4501 ; (TEST/DEBUG)
313 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
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...
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...
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 */
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 */
344 bne cr1,swtchtocont ; Switch to the continuation
345 sc /* Switch to the new context */
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.
351 blr /* Jump into the new thread */
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.
358 ; Note that we do the same kind of thing a chkfac in hw_exceptions.s
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
367 b EXT(exception_exit) ; Blocking on continuation, toss old context...
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!
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
388 .globl EXT(switch_in)
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 */
398 stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */
399 stw r10,SAVprev(r3) /* Chain on the old one */
401 mr r3,r4 /* Pass back the old thread */
403 mtsrr0 r5 /* Set return point */
404 mtsrr1 r6 /* Set return MSR */
418 * void fpu_save(facility_context ctx)
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.
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
440 mfsprg r6,0 ; Get the per_processor block
441 lwz r12,FPUowner(r6) ; Get the context ID for owner
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)
455 noowneryet: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
457 mr r0,r7 ; (TEST/DEBUG)
458 mr r3,r10 ; (TEST/DEBUG)
460 mflr r2 ; Save the return address
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...
466 cmplw cr1,r3,r12 ; Is the specified context live?
468 isync ; Force owner check first
470 lwz r9,FPUcpu(r12) ; Get the cpu that context was last on
471 bne- cr1,fsret ; No, it is not...
473 cmplw cr1,r9,r11 ; Was the context for this processor?
474 beq- cr1,fsgoodcpu ; Facility last used on this processor...
476 b fsret ; Someone else claimed it...
480 fsgoodcpu: lwz r3,FPUsave(r12) ; Get the current FPU savearea for the thread
481 lwz r9,FPUlevel(r12) ; Get our current level indicator
483 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
484 beq- cr1,fsneedone ; Never saved it, so go do it...
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...
490 fsneedone: bl EXT(save_get) ; Get a savearea for the context
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
506 stw r9,SAVlevel(r3) ; Show level in savearea
509 ; Save the current FPU state into the PCB of the thread that owns it.
512 la r11,savefp0(r3) ; Point to the 1st line
513 dcbz 0,r11 ; Allocate the first savearea line
515 la r11,savefp4(r3) ; Point to the 2nd line
517 dcbz 0,r11 ; Allocate it
520 la r11,savefp8(r3) ; Point to the 3rd line
522 dcbz 0,r11 ; Allocate it
526 la r11,savefp12(r3) ; Point to the 4th line
528 dcbz 0,r11 ; Allocate it
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)
558 stfd f29,savefp29(r3)
559 stfd f30,savefp30(r3)
560 stfd f31,savefp31(r3)
562 fsret: mtmsr r0 ; Put interrupts on if they were and floating point off
567 fsbackout: mr r12,r0 ; Save the original MSR
568 b EXT(save_ret_join) ; Toss savearea and return from there...
573 * Entered to handle the floating-point unavailable exception and
576 * This code is run in virtual address mode on with interrupts off.
578 * Upon exit, the code returns to the users context with the floating
579 * point facility turned on.
581 * ENTRY: VM switched ON
583 * State is saved in savearea pointed to by R4.
584 * All other registers are free.
589 .globl EXT(fpu_switch)
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
601 mfsprg r26,0 ; Get the per_processor block
602 mfmsr r19 ; Get the current MSR
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
610 mtmsr r19 ; Enable floating point instructions
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
616 ; R22 has the "old" context anchor
617 ; R29 has the "new" context anchor
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)
628 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
630 fswretry: mr. r22,r22 ; See if there is any live FP status
632 beq- fsnosave ; No live context, so nothing to save...
634 isync ; Make sure we see this in the right order
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
643 bne- fsnosave ; No, not on the same processor...
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.
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
655 beq- fsthesame ; New and old are the same, just go enable...
657 beq- cr1,fsmstsave ; Not saved yet, go do it...
659 lwz r11,SAVlevel(r30) ; Get the level of top saved context
661 cmplw r31,r11 ; Are live and saved the same?
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)
672 beq+ fsnosave ; Same level, so already saved...
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
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
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
691 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
692 li r2,0x7F03 ; (TEST/DEBUG)
693 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
698 ; Now we will actually save the old context
701 la r11,savefp4(r3) ; Point to the 2nd line
703 dcbz 0,r11 ; Allocate cache
706 la r11,savefp8(r3) ; Point to the 3rd line
708 dcbz 0,r11 ; Allocate cache
712 la r11,savefp12(r3) ; Point to the 4th line
714 dcbz 0,r11 ; Allocate cache
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)
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)
751 ; The context is all saved now and the facility is free.
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!
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
764 stw r16,FPUcpu(r29) ; Claim context for us
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)
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
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...
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
795 stw r29,FPUowner(r26) ; Mark us as having the live context
797 beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load...
799 dcbt 0,r11 ; Touch line in
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...
806 stw r3,FPUsave(r29) ; Pop the context (we will toss the savearea later)
809 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
810 li r2,0x7F05 ; (TEST/DEBUG)
811 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
815 la r11,savefp4(r14) ; Point to next line
816 dcbt 0,r11 ; Touch line in
820 la r11,savefp8(r14) ; Point to next line
822 dcbt 0,r11 ; Touch line in
826 la r11,savefp12(r14) ; Point to next line
828 dcbt 0,r11 ; Touch line in
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)
862 mr r3,r14 ; Get the old savearea (we popped it before)
863 bl EXT(save_ret) ; Toss it
865 fsenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
866 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
867 ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature
868 lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags
869 lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act
870 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
871 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
872 oris r11,r11,hi16(floatUsed|floatCng) ; Set that we used floating point
873 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
874 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
875 xor r3,r25,r5 ; Get the real address of the savearea
876 beq- fsnuser ; We are not user state...
877 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
878 stw r11,spcFlags(r26) ; Set per_proc copy
882 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
883 li r2,0x7F07 ; (TEST/DEBUG)
884 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
888 b EXT(exception_exit) ; Exit to the fray...
891 * Initialize the registers to some bogus value
894 MakeSureThatNoTerroristsCanHurtUsByGod:
897 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
898 li r2,0x7F06 ; (TEST/DEBUG)
899 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
902 lis r5,hi16(EXT(FloatInit)) ; Get top secret floating point init value address
903 ori r5,r5,lo16(EXT(FloatInit)) ; Slam bottom
904 lfd f0,0(r5) ; Initialize FP0
905 fmr f1,f0 ; Do them all
936 b fsenable ; Finish setting it all up...
940 ; We get here when we are switching to the same context at the same level and the context
941 ; is still live. Essentially, all we are doing is turning on the faility. It may have
942 ; gotten turned off due to doing a context save for the current level or a context switch
943 ; back to the live guy.
951 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
952 li r2,0x7F0A ; (TEST/DEBUG)
953 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
956 beq- cr1,fsenable ; Not saved yet, nothing to pop, go enable and exit...
958 lwz r11,SAVlevel(r30) ; Get the level of top saved context
959 lwz r14,SAVprev(r30) ; Get the previous savearea
961 cmplw r11,r31 ; Are live and saved the same?
963 bne+ fsenable ; Level not the same, nothing to pop, go enable and exit...
965 mr r3,r30 ; Get the old savearea (we popped it before)
966 bl EXT(save_ret) ; Toss it
967 b fsenable ; Go enable and exit...
971 ; This function invalidates any live floating point context for the passed in facility_context.
972 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
976 .globl EXT(toss_live_fpu)
981 mfmsr r9 ; Get the MSR
982 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
983 rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now?
984 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off
985 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure floats are turned off
986 mtmsr r0 ; No interruptions
988 beq+ tlfnotours ; Floats off, can not be live here...
990 mfsprg r8,0 ; Get the per proc
993 ; Note that at this point, since floats are on, we are the owner
994 ; of live state on this processor
997 lwz r6,FPUowner(r8) ; Get the thread that owns the floats
998 li r0,0 ; Clear this just in case we need it
999 cmplw r6,r3 ; Are we tossing our own context?
1000 bne- tlfnotours ; Nope...
1002 fsub f1,f1,f1 ; Make a 0
1003 mtfsf 0xFF,f1 ; Clear it
1005 tlfnotours: lwz r11,FPUcpu(r3) ; Get the cpu on which we last loaded context
1006 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
1007 mulli r11,r11,ppSize ; Find offset to the owner per_proc
1008 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
1009 li r10,FPUowner ; Displacement to float owner
1010 add r11,r12,r11 ; Point to the owner per_proc
1011 li r0,0 ; Set a 0 to invalidate context
1013 tlfinvothr: lwarx r12,r10,r11 ; Get the owner
1014 cmplw r12,r3 ; Does he still have this context?
1015 bne+ tlfexit ; Nope, leave...
1016 stwcx. r0,r10,r11 ; Try to invalidate it
1017 bne- tlfinvothr ; Try again if there was a collision...
1019 tlfexit: mtmsr r9 ; Restore interruptions
1020 isync ; Could be turning off floats here
1025 * Altivec stuff is here. The techniques used are pretty identical to
1026 * the floating point. Except that we will honor the VRSAVE register
1027 * settings when loading and restoring registers.
1029 * There are two indications of saved VRs: the VRSAVE register and the vrvalid
1030 * mask. VRSAVE is set by the vector user and represents the VRs that they
1031 * say that they are using. The vrvalid mask indicates which vector registers
1032 * are saved in the savearea. Whenever context is saved, it is saved according
1033 * to the VRSAVE register. It is loaded based on VRSAVE anded with
1034 * vrvalid (all other registers are splatted with 0s). This is done because we
1035 * don't want to load any registers we don't have a copy of, we want to set them
1038 * Note that there are some oddities here when we save a context we are using.
1039 * It is really not too cool to do this, but what the hey... Anyway,
1040 * we turn vectors and fpu off before we leave.
1041 * The oddity is that if you use vectors after this, the
1042 * savearea containing the context just saved will go away. So, bottom line is
1043 * that don't use vectors until after you are done with the saved context.
1048 .globl EXT(vec_save)
1052 mfmsr r0 ; Get the MSR
1053 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off when we leave
1054 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
1055 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
1056 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp
1057 mtmsr r2 ; Set the MSR
1060 mfsprg r6,0 ; Get the per_processor block
1061 lwz r12,VMXowner(r6) ; Get the context ID for owner
1064 mr r7,r0 ; (TEST/DEBUG)
1065 li r4,0 ; (TEST/DEBUG)
1066 mr r10,r3 ; (TEST/DEBUG)
1067 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1068 mr. r3,r12 ; (TEST/DEBUG)
1069 li r2,0x5F00 ; (TEST/DEBUG)
1070 li r5,0 ; (TEST/DEBUG)
1071 beq- noowneryeu ; (TEST/DEBUG)
1072 lwz r4,VMXlevel(r12) ; (TEST/DEBUG)
1073 lwz r5,VMXsave(r12) ; (TEST/DEBUG)
1075 noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1077 mr r0,r7 ; (TEST/DEBUG)
1078 mr r3,r10 ; (TEST/DEBUG)
1080 mflr r2 ; Save the return address
1082 vsretry: mr. r12,r12 ; Anyone own the vector?
1083 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
1084 beq- vsret ; Nobody owns the vector, no save required...
1086 cmplw cr1,r3,r12 ; Is the specified context live?
1088 isync ; Force owner check first
1090 lwz r9,VMXcpu(r12) ; Get the cpu that context was last on
1091 bne- cr1,vsret ; Specified context is not live
1093 cmplw cr1,r9,r11 ; Was the context for this processor?
1094 beq+ cr1,vsgoodcpu ; Facility last used on this processor...
1096 b vsret ; Someone else claimed this...
1100 vsgoodcpu: lwz r3,VMXsave(r12) ; Get the current vector savearea for the thread
1101 lwz r10,liveVRS(r6) ; Get the right VRSave register
1102 lwz r9,VMXlevel(r12) ; Get our current level indicator
1105 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
1106 beq- cr1,vsneedone ; Never saved it, so we need an area...
1108 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
1109 mr. r10,r10 ; Is VRsave set to 0?
1110 cmplw cr1,r9,r8 ; Correct level?
1111 bne- cr1,vsneedone ; Different level, so we need to save...
1113 bne+ vsret ; VRsave is non-zero so we need to keep what is saved...
1115 lwz r4,SAVprev(r3) ; Pick up the previous area
1116 lwz r5,SAVlevel(r4) ; Get the level associated with save
1117 stw r4,VMXsave(r12) ; Dequeue this savearea
1118 stw r5,VMXlevel(r12) ; Save the level
1121 stw r3,VMXowner(r12) ; Show no live context here
1124 vsbackout: mr r12,r0 ; Set the saved MSR
1125 b EXT(save_ret_join) ; Toss the savearea and return from there...
1129 vsneedone: mr. r10,r10 ; Is VRsave set to 0?
1130 beq- vsret ; Yeah, they do not care about any of them...
1132 bl EXT(save_get) ; Get a savearea for the context
1134 mfsprg r6,0 ; Get back per_processor block
1135 li r4,SAVvector ; Get vector tag
1136 lwz r12,VMXowner(r6) ; Get back our context ID
1137 stb r4,SAVflags+2(r3) ; Mark this savearea as a vector
1138 mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it...
1139 beq- vsbackout ; If disowned, just toss savearea...
1140 lwz r4,facAct(r12) ; Get the activation associated with live context
1141 mtlr r2 ; Restore return
1142 lwz r8,VMXsave(r12) ; Get the current top vector savearea
1143 stw r4,SAVact(r3) ; Indicate the right activation for this context
1144 lwz r9,VMXlevel(r12) ; Get our current level indicator again
1145 stw r3,VMXsave(r12) ; Set this as the most current floating point context
1146 stw r8,SAVprev(r3) ; And then chain this in front
1148 stw r9,SAVlevel(r3) ; Set level in savearea
1150 mfcr r2 ; Save non-volatile CRs
1151 lwz r10,liveVRS(r6) ; Get the right VRSave register
1152 lis r9,0x5555 ; Mask with odd bits set
1153 rlwinm r11,r10,1,0,31 ; Shift over 1
1154 ori r9,r9,0x5555 ; Finish mask
1155 or r4,r10,r11 ; After this, even bits show which lines to zap
1157 andc r11,r4,r9 ; Clear out odd bits
1159 la r6,savevr0(r3) ; Point to line 0
1160 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits
1161 or r4,r11,r4 ; Set the odd bits
1162 ; (bit 0 is line 0, bit 1 is line 8,
1163 ; bit 2 is line 1, bit 3 is line 9, etc.
1164 rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1165 la r7,savevr2(r3) ; Point to line 1
1166 mtcrf 255,r4 ; Load up the CRs
1167 stw r10,savevrvalid(r3) ; Save the validity information
1168 mr r8,r6 ; Start registers off
1170 ; Save the current vector state
1173 bf 0,snol0 ; No line 0 to do...
1174 dcba br0,r6 ; Allocate cache line 0
1177 la r6,savevr4(r3) ; Point to line 2
1178 bf 2,snol1 ; No line 1 to do...
1179 dcba br0,r7 ; Allocate cache line 1
1182 la r7,savevr6(r3) ; Point to line 3
1183 bf 4,snol2 ; No line 2 to do...
1184 dcba br0,r6 ; Allocate cache line 2
1187 li r11,16 ; Get offset for odd registers
1188 bf 16,snovr0 ; Do not save VR0...
1189 stvxl v0,br0,r8 ; Save VR0
1192 la r9,savevr2(r3) ; Point to V2/V3 pair
1193 bf 17,snovr1 ; Do not save VR1...
1194 stvxl v1,r11,r8 ; Save VR1
1197 la r6,savevr8(r3) ; Point to line 4
1198 bf 6,snol3 ; No line 3 to do...
1199 dcba br0,r7 ; Allocate cache line 3
1202 la r8,savevr4(r3) ; Point to V4/V5 pair
1203 bf 18,snovr2 ; Do not save VR2...
1204 stvxl v2,br0,r9 ; Save VR2
1207 bf 19,snovr3 ; Do not save VR3...
1208 stvxl v3,r11,r9 ; Save VR3
1212 ; Note: CR4 is now free
1214 la r7,savevr10(r3) ; Point to line 5
1215 bf 8,snol4 ; No line 4 to do...
1216 dcba br0,r6 ; Allocate cache line 4
1219 la r9,savevr6(r3) ; Point to R6/R7 pair
1220 bf 20,snovr4 ; Do not save VR4...
1221 stvxl v4,br0,r8 ; Save VR4
1224 bf 21,snovr5 ; Do not save VR5...
1225 stvxl v5,r11,r8 ; Save VR5
1228 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1229 la r6,savevr12(r3) ; Point to line 6
1230 bf 10,snol5 ; No line 5 to do...
1231 dcba br0,r7 ; Allocate cache line 5
1234 la r8,savevr8(r3) ; Point to V8/V9 pair
1235 bf 22,snovr6 ; Do not save VR6...
1236 stvxl v6,br0,r9 ; Save VR6
1239 bf 23,snovr7 ; Do not save VR7...
1240 stvxl v7,r11,r9 ; Save VR7
1244 ; Note: CR5 is now free
1246 la r7,savevr14(r3) ; Point to line 7
1247 bf 12,snol6 ; No line 6 to do...
1248 dcba br0,r6 ; Allocate cache line 6
1251 la r9,savevr10(r3) ; Point to V10/V11 pair
1252 bf 24,snovr8 ; Do not save VR8...
1253 stvxl v8,br0,r8 ; Save VR8
1256 bf 25,snovr9 ; Do not save VR9...
1257 stvxl v9,r11,r8 ; Save VR9
1260 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1261 la r6,savevr16(r3) ; Point to line 8
1262 bf 14,snol7 ; No line 7 to do...
1263 dcba br0,r7 ; Allocate cache line 7
1266 la r8,savevr12(r3) ; Point to V12/V13 pair
1267 bf 26,snovr10 ; Do not save VR10...
1268 stvxl v10,br0,r9 ; Save VR10
1271 bf 27,snovr11 ; Do not save VR11...
1272 stvxl v11,r11,r9 ; Save VR11
1277 ; Note: CR6 is now free
1279 la r7,savevr18(r3) ; Point to line 9
1280 bf 1,snol8 ; No line 8 to do...
1281 dcba br0,r6 ; Allocate cache line 8
1284 la r9,savevr14(r3) ; Point to V14/V15 pair
1285 bf 28,snovr12 ; Do not save VR12...
1286 stvxl v12,br0,r8 ; Save VR12
1289 bf 29,snovr13 ; Do not save VR13...
1290 stvxl v13,r11,r8 ; Save VR13
1293 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1294 la r6,savevr20(r3) ; Point to line 10
1295 bf 3,snol9 ; No line 9 to do...
1296 dcba br0,r7 ; Allocate cache line 9
1299 la r8,savevr16(r3) ; Point to V16/V17 pair
1300 bf 30,snovr14 ; Do not save VR14...
1301 stvxl v14,br0,r9 ; Save VR14
1304 bf 31,snovr15 ; Do not save VR15...
1305 stvxl v15,r11,r9 ; Save VR15
1309 ; Note: CR7 is now free
1311 la r7,savevr22(r3) ; Point to line 11
1312 bf 5,snol10 ; No line 10 to do...
1313 dcba br0,r6 ; Allocate cache line 10
1316 la r9,savevr18(r3) ; Point to V18/V19 pair
1317 bf 16,snovr16 ; Do not save VR16...
1318 stvxl v16,br0,r8 ; Save VR16
1321 bf 17,snovr17 ; Do not save VR17...
1322 stvxl v17,r11,r8 ; Save VR17
1325 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1327 ; Note: All registers have been or are accounted for in CRs
1329 la r6,savevr24(r3) ; Point to line 12
1330 bf 7,snol11 ; No line 11 to do...
1331 dcba br0,r7 ; Allocate cache line 11
1334 la r8,savevr20(r3) ; Point to V20/V21 pair
1335 bf 18,snovr18 ; Do not save VR18...
1336 stvxl v18,br0,r9 ; Save VR18
1339 bf 19,snovr19 ; Do not save VR19...
1340 stvxl v19,r11,r9 ; Save VR19
1343 la r7,savevr26(r3) ; Point to line 13
1344 bf 9,snol12 ; No line 12 to do...
1345 dcba br0,r6 ; Allocate cache line 12
1348 la r9,savevr22(r3) ; Point to V22/V23 pair
1349 bf 20,snovr20 ; Do not save VR20...
1350 stvxl v20,br0,r8 ; Save VR20
1353 bf 21,snovr21 ; Do not save VR21...
1354 stvxl v21,r11,r8 ; Save VR21
1357 la r6,savevr28(r3) ; Point to line 14
1358 bf 11,snol13 ; No line 13 to do...
1359 dcba br0,r7 ; Allocate cache line 13
1362 la r8,savevr24(r3) ; Point to V24/V25 pair
1363 bf 22,snovr22 ; Do not save VR22...
1364 stvxl v22,br0,r9 ; Save VR22
1367 bf 23,snovr23 ; Do not save VR23...
1368 stvxl v23,r11,r9 ; Save VR23
1371 la r7,savevr30(r3) ; Point to line 15
1372 bf 13,snol14 ; No line 14 to do...
1373 dcba br0,r6 ; Allocate cache line 14
1376 la r9,savevr26(r3) ; Point to V26/V27 pair
1377 bf 24,snovr24 ; Do not save VR24...
1378 stvxl v24,br0,r8 ; Save VR24
1381 bf 25,snovr25 ; Do not save VR25...
1382 stvxl v25,r11,r8 ; Save VR25
1385 bf 15,snol15 ; No line 15 to do...
1386 dcba br0,r7 ; Allocate cache line 15
1390 ; Note: All cache lines allocated now
1392 la r8,savevr28(r3) ; Point to V28/V29 pair
1393 bf 26,snovr26 ; Do not save VR26...
1394 stvxl v26,br0,r9 ; Save VR26
1397 bf 27,snovr27 ; Do not save VR27...
1398 stvxl v27,r11,r9 ; Save VR27
1401 la r7,savevr30(r3) ; Point to V30/V31 pair
1402 bf 28,snovr28 ; Do not save VR28...
1403 stvxl v28,br0,r8 ; Save VR28
1406 bf 29,snovr29 ; Do not save VR29...
1407 stvxl v29,r11,r8 ; Save VR29
1410 bf 30,snovr30 ; Do not save VR30...
1411 stvxl v30,br0,r7 ; Save VR30
1414 bf 31,snovr31 ; Do not save VR31...
1415 stvxl v31,r11,r7 ; Save VR31
1418 mtcrf 255,r2 ; Restore all cr
1420 vsret: mtmsr r0 ; Put interrupts on if they were and vector off
1428 * Entered to handle the vector unavailable exception and
1429 * switch vector context
1431 * This code is run with virtual address mode on and interrupts off.
1433 * Upon exit, the code returns to the users context with the vector
1434 * facility turned on.
1436 * ENTRY: VM switched ON
1438 * State is saved in savearea pointed to by R4.
1439 * All other registers are free.
1444 .globl EXT(vec_switch)
1449 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1450 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1456 mfsprg r26,0 ; Get the per_processor block
1457 mfmsr r19 ; Get the current MSR
1459 mr r25,r4 ; Save the entry savearea
1460 lwz r22,VMXowner(r26) ; Get the thread that owns the vector
1461 lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread
1462 oris r19,r19,hi16(MASK(MSR_VEC)) ; Enable the vector feature
1463 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
1465 mtmsr r19 ; Enable vector instructions
1468 lwz r27,ACT_MACT_PCB(r17) ; Get the current level
1469 lwz r29,curctx(r17) ; Grab the current context anchor of the current thread
1471 ; R22 has the "old" context anchor
1472 ; R29 has the "new" context anchor
1475 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1476 li r2,0x5F01 ; (TEST/DEBUG)
1477 mr r3,r22 ; (TEST/DEBUG)
1478 mr r5,r29 ; (TEST/DEBUG)
1479 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1483 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
1485 vsvretry: mr. r22,r22 ; See if there is any live vector status
1487 beq- vsnosave ; No live context, so nothing to save...
1489 isync ; Make sure we see this in the right order
1491 lwz r30,VMXsave(r22) ; Get the top savearea
1492 cmplw cr2,r22,r29 ; Are both old and new the same context?
1493 lwz r18,VMXcpu(r22) ; Get the last CPU we ran on
1494 cmplwi cr1,r30,0 ; Anything saved yet?
1495 cmplw r18,r16 ; Make sure we are on the right processor
1496 lwz r31,VMXlevel(r22) ; Get the context level
1498 lwz r10,liveVRS(r26) ; Get the right VRSave register
1500 bne- vsnosave ; No, not on the same processor...
1503 ; Check to see if the live context has already been saved.
1504 ; Also check to see if all we are here just to re-enable the MSR
1505 ; and handle specially if so.
1508 cmplw r31,r27 ; See if the current and active levels are the same
1509 crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same
1510 li r8,0 ; Clear this
1512 beq- vsthesame ; New and old are the same, just go enable...
1514 cmplwi cr2,r10,0 ; Check VRSave to see if we really need to save anything...
1515 beq- cr1,vsmstsave ; Not saved yet, go do it...
1517 lwz r11,SAVlevel(r30) ; Get the level of top saved context
1519 cmplw r31,r11 ; Are live and saved the same?
1522 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1523 li r2,0x5F02 ; (TEST/DEBUG)
1524 mr r3,r30 ; (TEST/DEBUG)
1525 mr r5,r31 ; (TEST/DEBUG)
1526 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1530 bne- vsmstsave ; Live context has not been saved yet...
1532 bne- cr2,vsnosave ; Live context saved and VRSave not 0, no save and keep context...
1534 lwz r4,SAVprev(r30) ; Pick up the previous area
1535 li r5,0 ; Assume this is the only one (which should be the ususal case)
1536 mr. r4,r4 ; Was this the only one?
1537 stw r4,VMXsave(r22) ; Dequeue this savearea
1538 beq+ vsonlyone ; This was the only one...
1539 lwz r5,SAVlevel(r4) ; Get the level associated with previous save
1541 vsonlyone: stw r5,VMXlevel(r22) ; Save the level
1542 stw r8,VMXowner(r26) ; Clear owner
1544 mr r3,r30 ; Copy the savearea we are tossing
1545 bl EXT(save_ret) ; Toss the savearea
1546 b vsnosave ; Go load up the context...
1551 vsmstsave: stw r8,VMXowner(r26) ; Clear owner
1553 beq- cr2,vsnosave ; The VRSave was 0, so there is nothing to save...
1555 bl EXT(save_get) ; Go get a savearea
1557 lwz r12,facAct(r22) ; Get the activation associated with the context
1558 stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread
1560 stw r30,SAVprev(r3) ; Point us to the old context
1561 stw r31,SAVlevel(r3) ; Tag our level
1562 li r7,SAVvector ; Get the vector ID
1563 stw r12,SAVact(r3) ; Make sure we point to the right guy
1564 stb r7,SAVflags+2(r3) ; Set that we have a vector save area
1567 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1568 li r2,0x5F03 ; (TEST/DEBUG)
1569 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1573 lwz r10,liveVRS(r26) ; Get the right VRSave register
1574 lis r9,0x5555 ; Mask with odd bits set
1575 rlwinm r11,r10,1,0,31 ; Shift over 1
1576 ori r9,r9,0x5555 ; Finish mask
1577 or r21,r10,r11 ; After this, even bits show which lines to zap
1579 andc r13,r21,r9 ; Clear out odd bits
1581 la r11,savevr0(r3) ; Point to line 0
1582 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1583 or r24,r13,r24 ; Set the odd bits
1584 ; (bit 0 is line 0, bit 1 is line 8,
1585 ; bit 2 is line 1, bit 3 is line 9, etc.
1586 rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1587 la r21,savevr2(r3) ; Point to line 1
1588 mtcrf 255,r24 ; Load up the CRs
1589 stw r10,savevrvalid(r3) ; Save the validity information
1590 mr r12,r11 ; Start registers off
1592 ; Save the current vector state
1595 bf 0,nol0 ; No line 0 to do...
1596 dcba br0,r11 ; Allocate cache line 0
1599 la r11,savevr4(r3) ; Point to line 2
1600 bf 2,nol1 ; No line 1 to do...
1601 dcba br0,r21 ; Allocate cache line 1
1604 la r21,savevr6(r3) ; Point to line 3
1605 bf 4,nol2 ; No line 2 to do...
1606 dcba br0,r11 ; Allocate cache line 2
1609 li r14,16 ; Get offset for odd registers
1610 bf 16,novr0 ; Do not save VR0...
1611 stvxl v0,br0,r12 ; Save VR0
1614 la r13,savevr2(r3) ; Point to V2/V3 pair
1615 bf 17,novr1 ; Do not save VR1...
1616 stvxl v1,r14,r12 ; Save VR1
1619 la r11,savevr8(r3) ; Point to line 4
1620 bf 6,nol3 ; No line 3 to do...
1621 dcba br0,r21 ; Allocate cache line 3
1624 la r12,savevr4(r3) ; Point to V4/V5 pair
1625 bf 18,novr2 ; Do not save VR2...
1626 stvxl v2,br0,r13 ; Save VR2
1629 bf 19,novr3 ; Do not save VR3...
1630 stvxl v3,r14,r13 ; Save VR3
1634 ; Note: CR4 is now free
1636 la r21,savevr10(r3) ; Point to line 5
1637 bf 8,nol4 ; No line 4 to do...
1638 dcba br0,r11 ; Allocate cache line 4
1641 la r13,savevr6(r3) ; Point to R6/R7 pair
1642 bf 20,novr4 ; Do not save VR4...
1643 stvxl v4,br0,r12 ; Save VR4
1646 bf 21,novr5 ; Do not save VR5...
1647 stvxl v5,r14,r12 ; Save VR5
1650 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1651 la r11,savevr12(r3) ; Point to line 6
1652 bf 10,nol5 ; No line 5 to do...
1653 dcba br0,r21 ; Allocate cache line 5
1656 la r12,savevr8(r3) ; Point to V8/V9 pair
1657 bf 22,novr6 ; Do not save VR6...
1658 stvxl v6,br0,r13 ; Save VR6
1661 bf 23,novr7 ; Do not save VR7...
1662 stvxl v7,r14,r13 ; Save VR7
1666 ; Note: CR5 is now free
1668 la r21,savevr14(r3) ; Point to line 7
1669 bf 12,nol6 ; No line 6 to do...
1670 dcba br0,r11 ; Allocate cache line 6
1673 la r13,savevr10(r3) ; Point to V10/V11 pair
1674 bf 24,novr8 ; Do not save VR8...
1675 stvxl v8,br0,r12 ; Save VR8
1678 bf 25,novr9 ; Do not save VR9...
1679 stvxl v9,r14,r12 ; Save VR9
1682 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1683 la r11,savevr16(r3) ; Point to line 8
1684 bf 14,nol7 ; No line 7 to do...
1685 dcba br0,r21 ; Allocate cache line 7
1688 la r12,savevr12(r3) ; Point to V12/V13 pair
1689 bf 26,novr10 ; Do not save VR10...
1690 stvxl v10,br0,r13 ; Save VR10
1693 bf 27,novr11 ; Do not save VR11...
1694 stvxl v11,r14,r13 ; Save VR11
1699 ; Note: CR6 is now free
1701 la r21,savevr18(r3) ; Point to line 9
1702 bf 1,nol8 ; No line 8 to do...
1703 dcba br0,r11 ; Allocate cache line 8
1706 la r13,savevr14(r3) ; Point to V14/V15 pair
1707 bf 28,novr12 ; Do not save VR12...
1708 stvxl v12,br0,r12 ; Save VR12
1711 bf 29,novr13 ; Do not save VR13...
1712 stvxl v13,r14,r12 ; Save VR13
1715 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1716 la r11,savevr20(r3) ; Point to line 10
1717 bf 3,nol9 ; No line 9 to do...
1718 dcba br0,r21 ; Allocate cache line 9
1721 la r12,savevr16(r3) ; Point to V16/V17 pair
1722 bf 30,novr14 ; Do not save VR14...
1723 stvxl v14,br0,r13 ; Save VR14
1726 bf 31,novr15 ; Do not save VR15...
1727 stvxl v15,r14,r13 ; Save VR15
1731 ; Note: CR7 is now free
1733 la r21,savevr22(r3) ; Point to line 11
1734 bf 5,nol10 ; No line 10 to do...
1735 dcba br0,r11 ; Allocate cache line 10
1738 la r13,savevr18(r3) ; Point to V18/V19 pair
1739 bf 16,novr16 ; Do not save VR16...
1740 stvxl v16,br0,r12 ; Save VR16
1743 bf 17,novr17 ; Do not save VR17...
1744 stvxl v17,r14,r12 ; Save VR17
1747 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1749 ; Note: All registers have been or are accounted for in CRs
1751 la r11,savevr24(r3) ; Point to line 12
1752 bf 7,nol11 ; No line 11 to do...
1753 dcba br0,r21 ; Allocate cache line 11
1756 la r12,savevr20(r3) ; Point to V20/V21 pair
1757 bf 18,novr18 ; Do not save VR18...
1758 stvxl v18,br0,r13 ; Save VR18
1761 bf 19,novr19 ; Do not save VR19...
1762 stvxl v19,r14,r13 ; Save VR19
1765 la r21,savevr26(r3) ; Point to line 13
1766 bf 9,nol12 ; No line 12 to do...
1767 dcba br0,r11 ; Allocate cache line 12
1770 la r13,savevr22(r3) ; Point to V22/V23 pair
1771 bf 20,novr20 ; Do not save VR20...
1772 stvxl v20,br0,r12 ; Save VR20
1775 bf 21,novr21 ; Do not save VR21...
1776 stvxl v21,r14,r12 ; Save VR21
1779 la r11,savevr28(r3) ; Point to line 14
1780 bf 11,nol13 ; No line 13 to do...
1781 dcba br0,r21 ; Allocate cache line 13
1784 la r12,savevr24(r3) ; Point to V24/V25 pair
1785 bf 22,novr22 ; Do not save VR22...
1786 stvxl v22,br0,r13 ; Save VR22
1789 bf 23,novr23 ; Do not save VR23...
1790 stvxl v23,r14,r13 ; Save VR23
1793 la r21,savevr30(r3) ; Point to line 15
1794 bf 13,nol14 ; No line 14 to do...
1795 dcba br0,r11 ; Allocate cache line 14
1798 la r13,savevr26(r3) ; Point to V26/V27 pair
1799 bf 24,novr24 ; Do not save VR24...
1800 stvxl v24,br0,r12 ; Save VR24
1803 bf 25,novr25 ; Do not save VR25...
1804 stvxl v25,r14,r12 ; Save VR25
1807 bf 15,nol15 ; No line 15 to do...
1808 dcba br0,r21 ; Allocate cache line 15
1812 ; Note: All cache lines allocated now
1814 la r12,savevr28(r3) ; Point to V28/V29 pair
1815 bf 26,novr26 ; Do not save VR26...
1816 stvxl v26,br0,r13 ; Save VR26
1819 bf 27,novr27 ; Do not save VR27...
1820 stvxl v27,r14,r13 ; Save VR27
1823 la r13,savevr30(r3) ; Point to V30/V31 pair
1824 bf 28,novr28 ; Do not save VR28...
1825 stvxl v28,br0,r12 ; Save VR28
1828 bf 29,novr29 ; Do not save VR29...
1829 stvxl v29,r14,r12 ; Save VR29
1832 bf 30,novr30 ; Do not save VR30...
1833 stvxl v30,br0,r13 ; Save VR30
1836 bf 31,novr31 ; Do not save VR31...
1837 stvxl v31,r14,r13 ; Save VR31
1844 ; The context is all saved now and the facility is free.
1846 ; If we do not we need to fill the registers with junk, because this level has
1847 ; never used them before and some thieving bastard could hack the old values
1848 ; of some thread! Just imagine what would happen if they could! Why, nothing
1849 ; would be safe! My God! It is terrifying!
1851 ; Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian)
1852 ; constant that we may need to fill unused vector registers.
1858 vsnosave: vspltisb v31,-10 ; Get 0xF6F6F6F6
1859 lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
1860 vspltisb v30,5 ; Get 0x05050505
1861 lwz r19,VMXcpu(r29) ; Get the last CPU we ran on
1862 vspltish v29,4 ; Get 0x00040004
1863 lwz r14,VMXsave(r29) ; Point to the top of the "new" context stack
1864 vrlb v31,v31,v30 ; Get 0xDEDEDEDE
1866 stw r16,VMXcpu(r29) ; Claim context for us
1870 lwz r13,VMXlevel(r29) ; (TEST/DEBUG)
1871 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1872 li r2,0x5F04 ; (TEST/DEBUG)
1873 mr r1,r15 ; (TEST/DEBUG)
1874 mr r3,r14 ; (TEST/DEBUG)
1875 mr r5,r13 ; (TEST/DEBUG)
1876 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1880 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
1881 vspltisb v28,-2 ; Get 0xFEFEFEFE
1882 mulli r19,r19,ppSize ; Find offset to the owner per_proc
1883 vsubuhm v31,v31,v29 ; Get 0xDEDADEDA
1884 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
1885 vpkpx v30,v28,v3 ; Get 0x7FFF7FFF
1886 li r16,VMXowner ; Displacement to vector owner
1887 add r19,r18,r19 ; Point to the owner per_proc
1888 vrlb v31,v31,v29 ; Get 0xDEADDEAD
1891 vsinvothr: lwarx r18,r16,r19 ; Get the owner
1892 cmplw r18,r29 ; Does he still have this context?
1893 bne vsinvoths ; Nope...
1894 stwcx. r0,r16,r19 ; Try to invalidate it
1895 bne- vsinvothr ; Try again if there was a collision...
1898 vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
1899 vmrghh v31,v30,v31 ; Get 0x7FFFDEAD. V31 keeps this value until the bitter end
1900 stw r15,VMXlevel(r29) ; Set the "new" active level
1902 stw r29,VMXowner(r26) ; Mark us as having the live context
1904 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
1906 lwz r3,SAVprev(r14) ; Get the previous context
1907 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
1908 cmplw r0,r15 ; Top level correct to load?
1909 bne- ProtectTheAmericanWay ; No, go initialize...
1911 stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later)
1914 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1915 li r2,0x5F05 ; (TEST/DEBUG)
1916 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1920 lwz r22,savevrsave(r25) ; Get the most current VRSAVE
1921 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
1922 lis r9,0x5555 ; Mask with odd bits set
1923 and r10,r10,r22 ; Figure out just what registers need to be loaded
1924 ori r9,r9,0x5555 ; Finish mask
1925 rlwinm r11,r10,1,0,31 ; Shift over 1
1926 or r12,r10,r11 ; After this, even bits show which lines to touch
1927 andc r13,r12,r9 ; Clear out odd bits
1929 la r20,savevr0(r14) ; Point to line 0
1930 rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1931 la r21,savevr2(r3) ; Point to line 1
1932 or r3,r13,r3 ; Set the odd bits
1933 ; (bit 0 is line 0, bit 1 is line 8,
1934 ; bit 2 is line 1, bit 3 is line 9, etc.
1935 rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1936 mtcrf 255,r3 ; Load up the CRs
1937 mr r22,r20 ; Start registers off
1939 ; Load the new vector state
1942 bf 0,lnol0 ; No line 0 to do...
1943 dcbt br0,r20 ; Touch cache line 0
1946 la r20,savevr4(r14) ; Point to line 2
1947 bf 2,lnol1 ; No line 1 to do...
1948 dcbt br0,r21 ; Touch cache line 1
1951 la r21,savevr6(r14) ; Point to line 3
1952 bf 4,lnol2 ; No line 2 to do...
1953 dcbt br0,r20 ; Touch cache line 2
1956 li r30,16 ; Get offset for odd registers
1957 bf 16,lnovr0 ; Do not restore VR0...
1958 lvxl v0,br0,r22 ; Restore VR0
1961 la r23,savevr2(r14) ; Point to V2/V3 pair
1962 bf 17,lnovr1 ; Do not restore VR1...
1963 lvxl v1,r30,r22 ; Restore VR1
1966 la r20,savevr8(r14) ; Point to line 4
1967 bf 6,lnol3 ; No line 3 to do...
1968 dcbt br0,r21 ; Touch cache line 3
1971 la r22,savevr4(r14) ; Point to V4/V5 pair
1972 bf 18,lnovr2 ; Do not restore VR2...
1973 lvxl v2,br0,r23 ; Restore VR2
1976 bf 19,lnovr3 ; Do not restore VR3...
1977 lvxl v3,r30,r23 ; Restore VR3
1981 ; Note: CR4 is now free
1983 la r21,savevr10(r14) ; Point to line 5
1984 bf 8,lnol4 ; No line 4 to do...
1985 dcbt br0,r20 ; Touch cache line 4
1988 la r23,savevr6(r14) ; Point to R6/R7 pair
1989 bf 20,lnovr4 ; Do not restore VR4...
1990 lvxl v4,br0,r22 ; Restore VR4
1993 bf 21,lnovr5 ; Do not restore VR5...
1994 lvxl v5,r30,r22 ; Restore VR5
1997 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1998 la r20,savevr12(r14) ; Point to line 6
1999 bf 10,lnol5 ; No line 5 to do...
2000 dcbt br0,r21 ; Touch cache line 5
2003 la r22,savevr8(r14) ; Point to V8/V9 pair
2004 bf 22,lnovr6 ; Do not restore VR6...
2005 lvxl v6,br0,r23 ; Restore VR6
2008 bf 23,lnovr7 ; Do not restore VR7...
2009 lvxl v7,r30,r23 ; Restore VR7
2013 ; Note: CR5 is now free
2015 la r21,savevr14(r14) ; Point to line 7
2016 bf 12,lnol6 ; No line 6 to do...
2017 dcbt br0,r20 ; Touch cache line 6
2020 la r23,savevr10(r14) ; Point to V10/V11 pair
2021 bf 24,lnovr8 ; Do not restore VR8...
2022 lvxl v8,br0,r22 ; Restore VR8
2025 bf 25,lnovr9 ; Do not save VR9...
2026 lvxl v9,r30,r22 ; Restore VR9
2029 mtcrf 0x04,r10 ; Set CRs for registers 20-23
2030 la r20,savevr16(r14) ; Point to line 8
2031 bf 14,lnol7 ; No line 7 to do...
2032 dcbt br0,r21 ; Touch cache line 7
2035 la r22,savevr12(r14) ; Point to V12/V13 pair
2036 bf 26,lnovr10 ; Do not restore VR10...
2037 lvxl v10,br0,r23 ; Restore VR10
2040 bf 27,lnovr11 ; Do not restore VR11...
2041 lvxl v11,r30,r23 ; Restore VR11
2046 ; Note: CR6 is now free
2048 la r21,savevr18(r14) ; Point to line 9
2049 bf 1,lnol8 ; No line 8 to do...
2050 dcbt br0,r20 ; Touch cache line 8
2053 la r23,savevr14(r14) ; Point to V14/V15 pair
2054 bf 28,lnovr12 ; Do not restore VR12...
2055 lvxl v12,br0,r22 ; Restore VR12
2058 bf 29,lnovr13 ; Do not restore VR13...
2059 lvxl v13,r30,r22 ; Restore VR13
2062 mtcrf 0x02,r10 ; Set CRs for registers 24-27
2063 la r20,savevr20(r14) ; Point to line 10
2064 bf 3,lnol9 ; No line 9 to do...
2065 dcbt br0,r21 ; Touch cache line 9
2068 la r22,savevr16(r14) ; Point to V16/V17 pair
2069 bf 30,lnovr14 ; Do not restore VR14...
2070 lvxl v14,br0,r23 ; Restore VR14
2073 bf 31,lnovr15 ; Do not restore VR15...
2074 lvxl v15,r30,r23 ; Restore VR15
2078 ; Note: CR7 is now free
2080 la r21,savevr22(r14) ; Point to line 11
2081 bf 5,lnol10 ; No line 10 to do...
2082 dcbt br0,r20 ; Touch cache line 10
2085 la r23,savevr18(r14) ; Point to V18/V19 pair
2086 bf 16,lnovr16 ; Do not restore VR16...
2087 lvxl v16,br0,r22 ; Restore VR16
2090 bf 17,lnovr17 ; Do not restore VR17...
2091 lvxl v17,r30,r22 ; Restore VR17
2094 mtcrf 0x01,r10 ; Set CRs for registers 28-31
2096 ; Note: All registers have been or are accounted for in CRs
2098 la r20,savevr24(r14) ; Point to line 12
2099 bf 7,lnol11 ; No line 11 to do...
2100 dcbt br0,r21 ; Touch cache line 11
2103 la r22,savevr20(r14) ; Point to V20/V21 pair
2104 bf 18,lnovr18 ; Do not restore VR18...
2105 lvxl v18,br0,r23 ; Restore VR18
2108 bf 19,lnovr19 ; Do not restore VR19...
2109 lvxl v19,r30,r23 ; Restore VR19
2112 la r21,savevr26(r14) ; Point to line 13
2113 bf 9,lnol12 ; No line 12 to do...
2114 dcbt br0,r20 ; Touch cache line 12
2117 la r23,savevr22(r14) ; Point to V22/V23 pair
2118 bf 20,lnovr20 ; Do not restore VR20...
2119 lvxl v20,br0,r22 ; Restore VR20
2122 bf 21,lnovr21 ; Do not restore VR21...
2123 lvxl v21,r30,r22 ; Restore VR21
2126 la r20,savevr28(r14) ; Point to line 14
2127 bf 11,lnol13 ; No line 13 to do...
2128 dcbt br0,r21 ; Touch cache line 13
2131 la r22,savevr24(r14) ; Point to V24/V25 pair
2132 bf 22,lnovr22 ; Do not restore VR22...
2133 lvxl v22,br0,r23 ; Restore VR22
2136 bf 23,lnovr23 ; Do not restore VR23...
2137 lvxl v23,r30,r23 ; Restore VR23
2140 la r21,savevr30(r14) ; Point to line 15
2141 bf 13,lnol14 ; No line 14 to do...
2142 dcbt br0,r20 ; Touch cache line 14
2145 la r23,savevr26(r14) ; Point to V26/V27 pair
2146 bf 24,lnovr24 ; Do not restore VR24...
2147 lvxl v24,br0,r22 ; Restore VR24
2150 bf 25,lnovr25 ; Do not restore VR25...
2151 lvxl v25,r30,r22 ; Restore VR25
2154 bf 15,lnol15 ; No line 15 to do...
2155 dcbt br0,r21 ; Touch cache line 15
2159 ; Note: All needed cache lines have been touched now
2161 la r22,savevr28(r14) ; Point to V28/V29 pair
2162 bf 26,lnovr26 ; Do not restore VR26...
2163 lvxl v26,br0,r23 ; Restore VR26
2166 bf 27,lnovr27 ; Do not restore VR27...
2167 lvxl v27,r30,r23 ; Restore VR27
2170 la r23,savevr30(r14) ; Point to V30/V31 pair
2171 bf 28,lnovr28 ; Do not restore VR28...
2172 lvxl v28,br0,r22 ; Restore VR28
2175 bf 29,lnovr29 ; Do not restore VR29...
2176 lvxl v29,r30,r22 ; Restore VR29
2179 bf 30,lnovr30 ; Do not restore VR30...
2180 lvxl v30,br0,r23 ; Restore VR30
2184 ; Everything is restored now except for VR31. We need it to get
2185 ; the QNaNBarbarian value to put into idle vector registers.
2186 ; Note: V31 was set above to QNaNbarbarian
2189 cmpwi r10,-1 ; Handle the quick case of all registers in use
2190 beq- mstlvr31 ; Not likely, but all are in use...
2191 mtcrf 255,r10 ; Get mask of valid registers
2193 bt 0,ni0 ; Register is ok already...
2194 vor v0,v31,v31 ; Copy into the next register
2196 bt 1,ni1 ; Register is ok already...
2197 vor v1,v31,v31 ; Copy into the next register
2199 bt 2,ni2 ; Register is ok already...
2200 vor v2,v31,v31 ; Copy into the next register
2202 bt 3,ni3 ; Register is ok already...
2203 vor v3,v31,v31 ; Copy into the next register
2205 bt 4,ni4 ; Register is ok already...
2206 vor v4,v31,v31 ; Copy into the next register
2208 bt 5,ni5 ; Register is ok already...
2209 vor v5,v31,v31 ; Copy into the next register
2211 bt 6,ni6 ; Register is ok already...
2212 vor v6,v31,v31 ; Copy into the next register
2214 bt 7,ni7 ; Register is ok already...
2215 vor v7,v31,v31 ; Copy into the next register
2217 bt 8,ni8 ; Register is ok already...
2218 vor v8,v31,v31 ; Copy into the next register
2220 bt 9,ni9 ; Register is ok already...
2221 vor v9,v31,v31 ; Copy into the next register
2223 bt 10,ni10 ; Register is ok already...
2224 vor v10,v31,v31 ; Copy into the next register
2226 bt 11,ni11 ; Register is ok already...
2227 vor v11,v31,v31 ; Copy into the next register
2229 bt 12,ni12 ; Register is ok already...
2230 vor v12,v31,v31 ; Copy into the next register
2232 bt 13,ni13 ; Register is ok already...
2233 vor v13,v31,v31 ; Copy into the next register
2235 bt 14,ni14 ; Register is ok already...
2236 vor v14,v31,v31 ; Copy into the next register
2238 bt 15,ni15 ; Register is ok already...
2239 vor v15,v31,v31 ; Copy into the next register
2241 bt 16,ni16 ; Register is ok already...
2242 vor v16,v31,v31 ; Copy into the next register
2244 bt 17,ni17 ; Register is ok already...
2245 vor v17,v31,v31 ; Copy into the next register
2247 bt 18,ni18 ; Register is ok already...
2248 vor v18,v31,v31 ; Copy into the next register
2250 bt 19,ni19 ; Register is ok already...
2251 vor v19,v31,v31 ; Copy into the next register
2253 bt 20,ni20 ; Register is ok already...
2254 vor v20,v31,v31 ; Copy into the next register
2256 bt 21,ni21 ; Register is ok already...
2257 vor v21,v31,v31 ; Copy into the next register
2259 bt 22,ni22 ; Register is ok already...
2260 vor v22,v31,v31 ; Copy into the next register
2262 bt 23,ni23 ; Register is ok already...
2263 vor v23,v31,v31 ; Copy into the next register
2265 bt 24,ni24 ; Register is ok already...
2266 vor v24,v31,v31 ; Copy into the next register
2268 bt 25,ni25 ; Register is ok already...
2269 vor v25,v31,v31 ; Copy into the next register
2271 bt 26,ni26 ; Register is ok already...
2272 vor v26,v31,v31 ; Copy into the next register
2274 bt 27,ni27 ; Register is ok already...
2275 vor v27,v31,v31 ; Copy into the next register
2277 bt 28,ni28 ; Register is ok already...
2278 vor v28,v31,v31 ; Copy into the next register
2280 bt 29,ni29 ; Register is ok already...
2281 vor v29,v31,v31 ; Copy into the next register
2283 bt 30,ni30 ; Register is ok already...
2284 vor v30,v31,v31 ; Copy into the next register
2286 bf 31,lnovr31 ; V31 is empty, no need to restore...
2288 mstlvr31: lvxl v31,r30,r23 ; Restore VR31
2290 lnovr31: mr r3,r14 ; Get the old savearea (we popped it before)
2291 bl EXT(save_ret) ; Toss it
2293 vrenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
2294 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
2295 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
2296 lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags
2297 lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act
2298 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
2299 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2300 oris r11,r11,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2301 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
2302 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
2303 xor r3,r25,r5 ; Get the real address of the savearea
2304 beq- vrnuser ; We are not user state...
2305 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
2306 stw r11,spcFlags(r26) ; Set per_proc copy
2310 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2311 li r2,0x5F07 ; (TEST/DEBUG)
2312 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2315 b EXT(exception_exit) ; Exit to the fray...
2318 * Initialize the registers to some bogus value
2321 ProtectTheAmericanWay:
2324 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2325 li r2,0x5F06 ; (TEST/DEBUG)
2326 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2330 vor v0,v31,v31 ; Copy into the next register
2331 vor v1,v31,v31 ; Copy into the next register
2332 vor v2,v31,v31 ; Copy into the next register
2333 vor v3,v31,v31 ; Copy into the next register
2334 vor v4,v31,v31 ; Copy into the next register
2335 vor v5,v31,v31 ; Copy into the next register
2336 vor v6,v31,v31 ; Copy into the next register
2337 vor v7,v31,v31 ; Copy into the next register
2338 vor v8,v31,v31 ; Copy into the next register
2339 vor v9,v31,v31 ; Copy into the next register
2340 vor v10,v31,v31 ; Copy into the next register
2341 vor v11,v31,v31 ; Copy into the next register
2342 vor v12,v31,v31 ; Copy into the next register
2343 vor v13,v31,v31 ; Copy into the next register
2344 vor v14,v31,v31 ; Copy into the next register
2345 vor v15,v31,v31 ; Copy into the next register
2346 vor v16,v31,v31 ; Copy into the next register
2347 vor v17,v31,v31 ; Copy into the next register
2348 vor v18,v31,v31 ; Copy into the next register
2349 vor v19,v31,v31 ; Copy into the next register
2350 vor v20,v31,v31 ; Copy into the next register
2351 vor v21,v31,v31 ; Copy into the next register
2352 vor v22,v31,v31 ; Copy into the next register
2353 vor v23,v31,v31 ; Copy into the next register
2354 vor v24,v31,v31 ; Copy into the next register
2355 vor v25,v31,v31 ; Copy into the next register
2356 vor v26,v31,v31 ; Copy into the next register
2357 vor v27,v31,v31 ; Copy into the next register
2358 vor v28,v31,v31 ; Copy into the next register
2359 vor v29,v31,v31 ; Copy into the next register
2360 vor v30,v31,v31 ; Copy into the next register
2361 b vrenable ; Finish setting it all up...
2366 ; We get here when we are switching to the same context at the same level and the context
2367 ; is still live. Essentially, all we are doing is turning on the faility. It may have
2368 ; gotten turned off due to doing a context save for the current level or a context switch
2369 ; back to the live guy.
2377 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2378 li r2,0x5F0A ; (TEST/DEBUG)
2379 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2382 beq- cr1,vrenable ; Not saved yet, nothing to pop, go enable and exit...
2384 lwz r11,SAVlevel(r30) ; Get the level of top saved context
2385 lwz r14,SAVprev(r30) ; Get the previous savearea
2387 cmplw r11,r31 ; Are live and saved the same?
2389 bne+ vrenable ; Level not the same, nothing to pop, go enable and exit...
2391 mr r3,r30 ; Get the old savearea (we popped it before)
2392 bl EXT(save_ret) ; Toss it
2393 b vrenable ; Go enable and exit...
2397 ; This function invalidates any live vector context for the passed in facility_context.
2398 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
2402 .globl EXT(toss_live_vec)
2406 mfmsr r9 ; Get the MSR
2407 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
2408 rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now?
2409 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vector is turned off
2410 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure fpu is turned off
2411 mtmsr r0 ; No interruptions
2413 beq+ tlvnotours ; Vector off, can not be live here...
2415 mfsprg r8,0 ; Get the per proc
2418 ; Note that at this point, since vecs are on, we are the owner
2419 ; of live state on this processor
2422 lwz r6,VMXowner(r8) ; Get the thread that owns the vector
2423 li r0,0 ; Clear this just in case we need it
2424 cmplw r6,r3 ; Are we tossing our own context?
2425 bne- tlvnotours ; Nope...
2427 vspltish v1,1 ; Turn on the non-Java bit and saturate
2428 vspltisw v0,1 ; Turn on the saturate bit
2429 vxor v1,v1,v0 ; Turn off saturate
2430 mtspr vrsave,r0 ; Clear VRSAVE
2431 mtvscr v1 ; Set the non-java, no saturate status
2433 tlvnotours: lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2434 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2435 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2436 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2437 li r10,VMXowner ; Displacement to vector owner
2438 add r11,r12,r11 ; Point to the owner per_proc
2439 li r0,0 ; Set a 0 to invalidate context
2441 tlvinvothr: lwarx r12,r10,r11 ; Get the owner
2442 cmplw r12,r3 ; Does he still have this context?
2443 bne+ tlvexit ; Nope, leave...
2444 stwcx. r0,r10,r11 ; Try to invalidate it
2445 bne- tlvinvothr ; Try again if there was a collision...
2447 tlvexit: mtmsr r9 ; Restore interruptions
2448 isync ; Could be turning off vectors here
2453 ; This function invalidates any live vector context for the passed in facility_context
2454 ; if the level is current. It also tosses the corresponding savearea if there is one.
2455 ; This function is primarily used whenever we detect a VRSave that is all zeros.
2459 .globl EXT(vec_trash)
2463 lwz r12,facAct(r3) ; Get the activation
2464 lwz r11,VMXlevel(r3) ; Get the context level
2465 lwz r10,ACT_MACT_PCB(r12) ; Grab the current level for the thread
2466 lwz r9,VMXsave(r3) ; Get the savearea, if any
2467 cmplw r10,r11 ; Are we at the right level?
2468 cmplwi cr1,r9,0 ; Remember if there is a savearea
2469 bnelr+ ; No, we do nothing...
2471 lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2472 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2473 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2474 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2475 li r10,VMXowner ; Displacement to vector owner
2476 add r11,r12,r11 ; Point to the owner per_proc
2477 li r0,0 ; Set a 0 to invalidate context
2479 vtinvothr: lwarx r12,r10,r11 ; Get the owner
2480 cmplw r12,r3 ; Does he still have this context?
2481 bne vtnotlive ; Nope, not live anywhere...
2482 stwcx. r0,r10,r11 ; Try to invalidate it
2483 bne- vtinvothr ; Try again if there was a collision...
2485 vtnotlive: beqlr+ cr1 ; Leave if there is no savearea
2486 lwz r8,SAVlevel(r9) ; Get the level of the savearea
2487 cmplw r8,r11 ; Savearea for the current level?
2488 bnelr+ ; No, nothing to release...
2490 lwz r8,SAVprev(r9) ; Pick up the previous area
2491 mr. r8,r8 ; Is there a previous?
2492 beq- vtnoprev ; Nope...
2493 lwz r7,SAVlevel(r8) ; Get the level associated with save
2495 vtnoprev: stw r8,VMXsave(r3) ; Dequeue this savearea
2496 stw r7,VMXlevel(r3) ; Pop the level
2498 mr r3,r9 ; Get the savearea to release
2499 b EXT(save_ret) ; Go and toss the save area (note, we will return from there)...
2503 ; Just some test code to force vector and/or floating point in the kernel
2507 .globl EXT(fctx_test)
2511 mfsprg r3,0 ; Get the per_proc block
2512 lwz r3,PP_ACTIVE_THREAD(r3) ; Get the thread pointer
2513 mr. r3,r3 ; Are we actually up and running?
2516 fmr f0,f0 ; Use floating point
2517 mftb r4 ; Get time base for a random number
2518 li r5,1 ; Get a potential vrsave to use
2519 andi. r4,r4,0x3F ; Get a number from 0 - 63
2520 slw r5,r5,r4 ; Choose a register to save (should be 0 half the time)
2521 mtspr vrsave,r5 ; Set VRSave
2522 vor v0,v0,v0 ; Use vectors