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 special flags
869 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
870 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
871 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
872 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
873 xor r3,r25,r5 ; Get the real address of the savearea
874 bne- fsnuser ; We are not user state...
875 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
876 stw r10,spcFlags(r26) ; Set per_proc copy
880 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
881 li r2,0x7F07 ; (TEST/DEBUG)
882 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
886 b EXT(exception_exit) ; Exit to the fray...
889 * Initialize the registers to some bogus value
892 MakeSureThatNoTerroristsCanHurtUsByGod:
895 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
896 li r2,0x7F06 ; (TEST/DEBUG)
897 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
900 lis r5,hi16(EXT(FloatInit)) ; Get top secret floating point init value address
901 ori r5,r5,lo16(EXT(FloatInit)) ; Slam bottom
902 lfd f0,0(r5) ; Initialize FP0
903 fmr f1,f0 ; Do them all
934 b fsenable ; Finish setting it all up...
938 ; We get here when we are switching to the same context at the same level and the context
939 ; is still live. Essentially, all we are doing is turning on the faility. It may have
940 ; gotten turned off due to doing a context save for the current level or a context switch
941 ; back to the live guy.
949 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
950 li r2,0x7F0A ; (TEST/DEBUG)
951 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
954 beq- cr1,fsenable ; Not saved yet, nothing to pop, go enable and exit...
956 lwz r11,SAVlevel(r30) ; Get the level of top saved context
957 lwz r14,SAVprev(r30) ; Get the previous savearea
959 cmplw r11,r31 ; Are live and saved the same?
961 bne+ fsenable ; Level not the same, nothing to pop, go enable and exit...
963 mr r3,r30 ; Get the old savearea (we popped it before)
964 bl EXT(save_ret) ; Toss it
965 b fsenable ; Go enable and exit...
969 ; This function invalidates any live floating point context for the passed in facility_context.
970 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
974 .globl EXT(toss_live_fpu)
979 mfmsr r9 ; Get the MSR
980 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
981 rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now?
982 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off
983 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure floats are turned off
984 mtmsr r0 ; No interruptions
986 beq+ tlfnotours ; Floats off, can not be live here...
988 mfsprg r8,0 ; Get the per proc
991 ; Note that at this point, since floats are on, we are the owner
992 ; of live state on this processor
995 lwz r6,FPUowner(r8) ; Get the thread that owns the floats
996 li r0,0 ; Clear this just in case we need it
997 cmplw r6,r3 ; Are we tossing our own context?
998 bne- tlfnotours ; Nope...
1000 fsub f1,f1,f1 ; Make a 0
1001 mtfsf 0xFF,f1 ; Clear it
1003 tlfnotours: lwz r11,FPUcpu(r3) ; Get the cpu on which we last loaded context
1004 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
1005 mulli r11,r11,ppSize ; Find offset to the owner per_proc
1006 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
1007 li r10,FPUowner ; Displacement to float owner
1008 add r11,r12,r11 ; Point to the owner per_proc
1009 li r0,0 ; Set a 0 to invalidate context
1011 tlfinvothr: lwarx r12,r10,r11 ; Get the owner
1012 cmplw r12,r3 ; Does he still have this context?
1013 bne+ tlfexit ; Nope, leave...
1014 stwcx. r0,r10,r11 ; Try to invalidate it
1015 bne- tlfinvothr ; Try again if there was a collision...
1017 tlfexit: mtmsr r9 ; Restore interruptions
1018 isync ; Could be turning off floats here
1023 * Altivec stuff is here. The techniques used are pretty identical to
1024 * the floating point. Except that we will honor the VRSAVE register
1025 * settings when loading and restoring registers.
1027 * There are two indications of saved VRs: the VRSAVE register and the vrvalid
1028 * mask. VRSAVE is set by the vector user and represents the VRs that they
1029 * say that they are using. The vrvalid mask indicates which vector registers
1030 * are saved in the savearea. Whenever context is saved, it is saved according
1031 * to the VRSAVE register. It is loaded based on VRSAVE anded with
1032 * vrvalid (all other registers are splatted with 0s). This is done because we
1033 * don't want to load any registers we don't have a copy of, we want to set them
1036 * Note that there are some oddities here when we save a context we are using.
1037 * It is really not too cool to do this, but what the hey... Anyway,
1038 * we turn vectors and fpu off before we leave.
1039 * The oddity is that if you use vectors after this, the
1040 * savearea containing the context just saved will go away. So, bottom line is
1041 * that don't use vectors until after you are done with the saved context.
1046 .globl EXT(vec_save)
1050 mfmsr r0 ; Get the MSR
1051 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off when we leave
1052 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
1053 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
1054 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp
1055 mtmsr r2 ; Set the MSR
1058 mfsprg r6,0 ; Get the per_processor block
1059 lwz r12,VMXowner(r6) ; Get the context ID for owner
1062 mr r7,r0 ; (TEST/DEBUG)
1063 li r4,0 ; (TEST/DEBUG)
1064 mr r10,r3 ; (TEST/DEBUG)
1065 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1066 mr. r3,r12 ; (TEST/DEBUG)
1067 li r2,0x5F00 ; (TEST/DEBUG)
1068 li r5,0 ; (TEST/DEBUG)
1069 beq- noowneryeu ; (TEST/DEBUG)
1070 lwz r4,VMXlevel(r12) ; (TEST/DEBUG)
1071 lwz r5,VMXsave(r12) ; (TEST/DEBUG)
1073 noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1075 mr r0,r7 ; (TEST/DEBUG)
1076 mr r3,r10 ; (TEST/DEBUG)
1078 mflr r2 ; Save the return address
1080 vsretry: mr. r12,r12 ; Anyone own the vector?
1081 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
1082 beq- vsret ; Nobody owns the vector, no save required...
1084 cmplw cr1,r3,r12 ; Is the specified context live?
1086 isync ; Force owner check first
1088 lwz r9,VMXcpu(r12) ; Get the cpu that context was last on
1089 bne- cr1,vsret ; Specified context is not live
1091 cmplw cr1,r9,r11 ; Was the context for this processor?
1092 beq+ cr1,vsgoodcpu ; Facility last used on this processor...
1094 b vsret ; Someone else claimed this...
1098 vsgoodcpu: lwz r3,VMXsave(r12) ; Get the current vector savearea for the thread
1099 lwz r10,liveVRS(r6) ; Get the right VRSave register
1100 lwz r9,VMXlevel(r12) ; Get our current level indicator
1103 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
1104 beq- cr1,vsneedone ; Never saved it, so we need an area...
1106 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
1107 mr. r10,r10 ; Is VRsave set to 0?
1108 cmplw cr1,r9,r8 ; Correct level?
1109 bne- cr1,vsneedone ; Different level, so we need to save...
1111 bne+ vsret ; VRsave is non-zero so we need to keep what is saved...
1113 lwz r4,SAVprev(r3) ; Pick up the previous area
1114 lwz r5,SAVlevel(r4) ; Get the level associated with save
1115 stw r4,VMXsave(r12) ; Dequeue this savearea
1116 stw r5,VMXlevel(r12) ; Save the level
1119 stw r3,VMXowner(r12) ; Show no live context here
1122 vsbackout: mr r12,r0 ; Set the saved MSR
1123 b EXT(save_ret_join) ; Toss the savearea and return from there...
1127 vsneedone: mr. r10,r10 ; Is VRsave set to 0?
1128 beq- vsret ; Yeah, they do not care about any of them...
1130 bl EXT(save_get) ; Get a savearea for the context
1132 mfsprg r6,0 ; Get back per_processor block
1133 li r4,SAVvector ; Get vector tag
1134 lwz r12,VMXowner(r6) ; Get back our context ID
1135 stb r4,SAVflags+2(r3) ; Mark this savearea as a vector
1136 mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it...
1137 beq- vsbackout ; If disowned, just toss savearea...
1138 lwz r4,facAct(r12) ; Get the activation associated with live context
1139 mtlr r2 ; Restore return
1140 lwz r8,VMXsave(r12) ; Get the current top vector savearea
1141 stw r4,SAVact(r3) ; Indicate the right activation for this context
1142 lwz r9,VMXlevel(r12) ; Get our current level indicator again
1143 stw r3,VMXsave(r12) ; Set this as the most current floating point context
1144 stw r8,SAVprev(r3) ; And then chain this in front
1146 stw r9,SAVlevel(r3) ; Set level in savearea
1148 mfcr r2 ; Save non-volatile CRs
1149 lwz r10,liveVRS(r6) ; Get the right VRSave register
1150 lis r9,0x5555 ; Mask with odd bits set
1151 rlwinm r11,r10,1,0,31 ; Shift over 1
1152 ori r9,r9,0x5555 ; Finish mask
1153 or r4,r10,r11 ; After this, even bits show which lines to zap
1155 andc r11,r4,r9 ; Clear out odd bits
1157 la r6,savevr0(r3) ; Point to line 0
1158 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits
1159 or r4,r11,r4 ; Set the odd bits
1160 ; (bit 0 is line 0, bit 1 is line 8,
1161 ; bit 2 is line 1, bit 3 is line 9, etc.
1162 rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1163 la r7,savevr2(r3) ; Point to line 1
1164 mtcrf 255,r4 ; Load up the CRs
1165 stw r10,savevrvalid(r3) ; Save the validity information
1166 mr r8,r6 ; Start registers off
1168 ; Save the current vector state
1171 bf 0,snol0 ; No line 0 to do...
1172 dcba br0,r6 ; Allocate cache line 0
1175 la r6,savevr4(r3) ; Point to line 2
1176 bf 2,snol1 ; No line 1 to do...
1177 dcba br0,r7 ; Allocate cache line 1
1180 la r7,savevr6(r3) ; Point to line 3
1181 bf 4,snol2 ; No line 2 to do...
1182 dcba br0,r6 ; Allocate cache line 2
1185 li r11,16 ; Get offset for odd registers
1186 bf 16,snovr0 ; Do not save VR0...
1187 stvxl v0,br0,r8 ; Save VR0
1190 la r9,savevr2(r3) ; Point to V2/V3 pair
1191 bf 17,snovr1 ; Do not save VR1...
1192 stvxl v1,r11,r8 ; Save VR1
1195 la r6,savevr8(r3) ; Point to line 4
1196 bf 6,snol3 ; No line 3 to do...
1197 dcba br0,r7 ; Allocate cache line 3
1200 la r8,savevr4(r3) ; Point to V4/V5 pair
1201 bf 18,snovr2 ; Do not save VR2...
1202 stvxl v2,br0,r9 ; Save VR2
1205 bf 19,snovr3 ; Do not save VR3...
1206 stvxl v3,r11,r9 ; Save VR3
1210 ; Note: CR4 is now free
1212 la r7,savevr10(r3) ; Point to line 5
1213 bf 8,snol4 ; No line 4 to do...
1214 dcba br0,r6 ; Allocate cache line 4
1217 la r9,savevr6(r3) ; Point to R6/R7 pair
1218 bf 20,snovr4 ; Do not save VR4...
1219 stvxl v4,br0,r8 ; Save VR4
1222 bf 21,snovr5 ; Do not save VR5...
1223 stvxl v5,r11,r8 ; Save VR5
1226 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1227 la r6,savevr12(r3) ; Point to line 6
1228 bf 10,snol5 ; No line 5 to do...
1229 dcba br0,r7 ; Allocate cache line 5
1232 la r8,savevr8(r3) ; Point to V8/V9 pair
1233 bf 22,snovr6 ; Do not save VR6...
1234 stvxl v6,br0,r9 ; Save VR6
1237 bf 23,snovr7 ; Do not save VR7...
1238 stvxl v7,r11,r9 ; Save VR7
1242 ; Note: CR5 is now free
1244 la r7,savevr14(r3) ; Point to line 7
1245 bf 12,snol6 ; No line 6 to do...
1246 dcba br0,r6 ; Allocate cache line 6
1249 la r9,savevr10(r3) ; Point to V10/V11 pair
1250 bf 24,snovr8 ; Do not save VR8...
1251 stvxl v8,br0,r8 ; Save VR8
1254 bf 25,snovr9 ; Do not save VR9...
1255 stvxl v9,r11,r8 ; Save VR9
1258 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1259 la r6,savevr16(r3) ; Point to line 8
1260 bf 14,snol7 ; No line 7 to do...
1261 dcba br0,r7 ; Allocate cache line 7
1264 la r8,savevr12(r3) ; Point to V12/V13 pair
1265 bf 26,snovr10 ; Do not save VR10...
1266 stvxl v10,br0,r9 ; Save VR10
1269 bf 27,snovr11 ; Do not save VR11...
1270 stvxl v11,r11,r9 ; Save VR11
1275 ; Note: CR6 is now free
1277 la r7,savevr18(r3) ; Point to line 9
1278 bf 1,snol8 ; No line 8 to do...
1279 dcba br0,r6 ; Allocate cache line 8
1282 la r9,savevr14(r3) ; Point to V14/V15 pair
1283 bf 28,snovr12 ; Do not save VR12...
1284 stvxl v12,br0,r8 ; Save VR12
1287 bf 29,snovr13 ; Do not save VR13...
1288 stvxl v13,r11,r8 ; Save VR13
1291 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1292 la r6,savevr20(r3) ; Point to line 10
1293 bf 3,snol9 ; No line 9 to do...
1294 dcba br0,r7 ; Allocate cache line 9
1297 la r8,savevr16(r3) ; Point to V16/V17 pair
1298 bf 30,snovr14 ; Do not save VR14...
1299 stvxl v14,br0,r9 ; Save VR14
1302 bf 31,snovr15 ; Do not save VR15...
1303 stvxl v15,r11,r9 ; Save VR15
1307 ; Note: CR7 is now free
1309 la r7,savevr22(r3) ; Point to line 11
1310 bf 5,snol10 ; No line 10 to do...
1311 dcba br0,r6 ; Allocate cache line 10
1314 la r9,savevr18(r3) ; Point to V18/V19 pair
1315 bf 16,snovr16 ; Do not save VR16...
1316 stvxl v16,br0,r8 ; Save VR16
1319 bf 17,snovr17 ; Do not save VR17...
1320 stvxl v17,r11,r8 ; Save VR17
1323 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1325 ; Note: All registers have been or are accounted for in CRs
1327 la r6,savevr24(r3) ; Point to line 12
1328 bf 7,snol11 ; No line 11 to do...
1329 dcba br0,r7 ; Allocate cache line 11
1332 la r8,savevr20(r3) ; Point to V20/V21 pair
1333 bf 18,snovr18 ; Do not save VR18...
1334 stvxl v18,br0,r9 ; Save VR18
1337 bf 19,snovr19 ; Do not save VR19...
1338 stvxl v19,r11,r9 ; Save VR19
1341 la r7,savevr26(r3) ; Point to line 13
1342 bf 9,snol12 ; No line 12 to do...
1343 dcba br0,r6 ; Allocate cache line 12
1346 la r9,savevr22(r3) ; Point to V22/V23 pair
1347 bf 20,snovr20 ; Do not save VR20...
1348 stvxl v20,br0,r8 ; Save VR20
1351 bf 21,snovr21 ; Do not save VR21...
1352 stvxl v21,r11,r8 ; Save VR21
1355 la r6,savevr28(r3) ; Point to line 14
1356 bf 11,snol13 ; No line 13 to do...
1357 dcba br0,r7 ; Allocate cache line 13
1360 la r8,savevr24(r3) ; Point to V24/V25 pair
1361 bf 22,snovr22 ; Do not save VR22...
1362 stvxl v22,br0,r9 ; Save VR22
1365 bf 23,snovr23 ; Do not save VR23...
1366 stvxl v23,r11,r9 ; Save VR23
1369 la r7,savevr30(r3) ; Point to line 15
1370 bf 13,snol14 ; No line 14 to do...
1371 dcba br0,r6 ; Allocate cache line 14
1374 la r9,savevr26(r3) ; Point to V26/V27 pair
1375 bf 24,snovr24 ; Do not save VR24...
1376 stvxl v24,br0,r8 ; Save VR24
1379 bf 25,snovr25 ; Do not save VR25...
1380 stvxl v25,r11,r8 ; Save VR25
1383 bf 15,snol15 ; No line 15 to do...
1384 dcba br0,r7 ; Allocate cache line 15
1388 ; Note: All cache lines allocated now
1390 la r8,savevr28(r3) ; Point to V28/V29 pair
1391 bf 26,snovr26 ; Do not save VR26...
1392 stvxl v26,br0,r9 ; Save VR26
1395 bf 27,snovr27 ; Do not save VR27...
1396 stvxl v27,r11,r9 ; Save VR27
1399 la r7,savevr30(r3) ; Point to V30/V31 pair
1400 bf 28,snovr28 ; Do not save VR28...
1401 stvxl v28,br0,r8 ; Save VR28
1404 bf 29,snovr29 ; Do not save VR29...
1405 stvxl v29,r11,r8 ; Save VR29
1408 bf 30,snovr30 ; Do not save VR30...
1409 stvxl v30,br0,r7 ; Save VR30
1412 bf 31,snovr31 ; Do not save VR31...
1413 stvxl v31,r11,r7 ; Save VR31
1416 mtcrf 255,r2 ; Restore all cr
1418 vsret: mtmsr r0 ; Put interrupts on if they were and vector off
1426 * Entered to handle the vector unavailable exception and
1427 * switch vector context
1429 * This code is run with virtual address mode on and interrupts off.
1431 * Upon exit, the code returns to the users context with the vector
1432 * facility turned on.
1434 * ENTRY: VM switched ON
1436 * State is saved in savearea pointed to by R4.
1437 * All other registers are free.
1442 .globl EXT(vec_switch)
1447 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1448 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1454 mfsprg r26,0 ; Get the per_processor block
1455 mfmsr r19 ; Get the current MSR
1457 mr r25,r4 ; Save the entry savearea
1458 lwz r22,VMXowner(r26) ; Get the thread that owns the vector
1459 lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread
1460 oris r19,r19,hi16(MASK(MSR_VEC)) ; Enable the vector feature
1461 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
1463 mtmsr r19 ; Enable vector instructions
1466 lwz r27,ACT_MACT_PCB(r17) ; Get the current level
1467 lwz r29,curctx(r17) ; Grab the current context anchor of the current thread
1469 ; R22 has the "old" context anchor
1470 ; R29 has the "new" context anchor
1473 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1474 li r2,0x5F01 ; (TEST/DEBUG)
1475 mr r3,r22 ; (TEST/DEBUG)
1476 mr r5,r29 ; (TEST/DEBUG)
1477 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1481 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
1483 vsvretry: mr. r22,r22 ; See if there is any live vector status
1485 beq- vsnosave ; No live context, so nothing to save...
1487 isync ; Make sure we see this in the right order
1489 lwz r30,VMXsave(r22) ; Get the top savearea
1490 cmplw cr2,r22,r29 ; Are both old and new the same context?
1491 lwz r18,VMXcpu(r22) ; Get the last CPU we ran on
1492 cmplwi cr1,r30,0 ; Anything saved yet?
1493 cmplw r18,r16 ; Make sure we are on the right processor
1494 lwz r31,VMXlevel(r22) ; Get the context level
1496 lwz r10,liveVRS(r26) ; Get the right VRSave register
1498 bne- vsnosave ; No, not on the same processor...
1501 ; Check to see if the live context has already been saved.
1502 ; Also check to see if all we are here just to re-enable the MSR
1503 ; and handle specially if so.
1506 cmplw r31,r27 ; See if the current and active levels are the same
1507 crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same
1508 li r8,0 ; Clear this
1510 beq- vsthesame ; New and old are the same, just go enable...
1512 cmplwi cr2,r10,0 ; Check VRSave to see if we really need to save anything...
1513 beq- cr1,vsmstsave ; Not saved yet, go do it...
1515 lwz r11,SAVlevel(r30) ; Get the level of top saved context
1517 cmplw r31,r11 ; Are live and saved the same?
1520 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1521 li r2,0x5F02 ; (TEST/DEBUG)
1522 mr r3,r30 ; (TEST/DEBUG)
1523 mr r5,r31 ; (TEST/DEBUG)
1524 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1528 bne- vsmstsave ; Live context has not been saved yet...
1530 bne- cr2,vsnosave ; Live context saved and VRSave not 0, no save and keep context...
1532 lwz r4,SAVprev(r30) ; Pick up the previous area
1533 li r5,0 ; Assume this is the only one (which should be the ususal case)
1534 mr. r4,r4 ; Was this the only one?
1535 stw r4,VMXsave(r22) ; Dequeue this savearea
1536 beq+ vsonlyone ; This was the only one...
1537 lwz r5,SAVlevel(r4) ; Get the level associated with previous save
1539 vsonlyone: stw r5,VMXlevel(r22) ; Save the level
1540 stw r8,VMXowner(r26) ; Clear owner
1542 mr r3,r30 ; Copy the savearea we are tossing
1543 bl EXT(save_ret) ; Toss the savearea
1544 b vsnosave ; Go load up the context...
1549 vsmstsave: stw r8,VMXowner(r26) ; Clear owner
1551 beq- cr2,vsnosave ; The VRSave was 0, so there is nothing to save...
1553 bl EXT(save_get) ; Go get a savearea
1555 lwz r12,facAct(r22) ; Get the activation associated with the context
1556 stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread
1558 stw r30,SAVprev(r3) ; Point us to the old context
1559 stw r31,SAVlevel(r3) ; Tag our level
1560 li r7,SAVvector ; Get the vector ID
1561 stw r12,SAVact(r3) ; Make sure we point to the right guy
1562 stb r7,SAVflags+2(r3) ; Set that we have a vector save area
1565 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1566 li r2,0x5F03 ; (TEST/DEBUG)
1567 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1571 lwz r10,liveVRS(r26) ; Get the right VRSave register
1572 lis r9,0x5555 ; Mask with odd bits set
1573 rlwinm r11,r10,1,0,31 ; Shift over 1
1574 ori r9,r9,0x5555 ; Finish mask
1575 or r21,r10,r11 ; After this, even bits show which lines to zap
1577 andc r13,r21,r9 ; Clear out odd bits
1579 la r11,savevr0(r3) ; Point to line 0
1580 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1581 or r24,r13,r24 ; Set the odd bits
1582 ; (bit 0 is line 0, bit 1 is line 8,
1583 ; bit 2 is line 1, bit 3 is line 9, etc.
1584 rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1585 la r21,savevr2(r3) ; Point to line 1
1586 mtcrf 255,r24 ; Load up the CRs
1587 stw r10,savevrvalid(r3) ; Save the validity information
1588 mr r12,r11 ; Start registers off
1590 ; Save the current vector state
1593 bf 0,nol0 ; No line 0 to do...
1594 dcba br0,r11 ; Allocate cache line 0
1597 la r11,savevr4(r3) ; Point to line 2
1598 bf 2,nol1 ; No line 1 to do...
1599 dcba br0,r21 ; Allocate cache line 1
1602 la r21,savevr6(r3) ; Point to line 3
1603 bf 4,nol2 ; No line 2 to do...
1604 dcba br0,r11 ; Allocate cache line 2
1607 li r14,16 ; Get offset for odd registers
1608 bf 16,novr0 ; Do not save VR0...
1609 stvxl v0,br0,r12 ; Save VR0
1612 la r13,savevr2(r3) ; Point to V2/V3 pair
1613 bf 17,novr1 ; Do not save VR1...
1614 stvxl v1,r14,r12 ; Save VR1
1617 la r11,savevr8(r3) ; Point to line 4
1618 bf 6,nol3 ; No line 3 to do...
1619 dcba br0,r21 ; Allocate cache line 3
1622 la r12,savevr4(r3) ; Point to V4/V5 pair
1623 bf 18,novr2 ; Do not save VR2...
1624 stvxl v2,br0,r13 ; Save VR2
1627 bf 19,novr3 ; Do not save VR3...
1628 stvxl v3,r14,r13 ; Save VR3
1632 ; Note: CR4 is now free
1634 la r21,savevr10(r3) ; Point to line 5
1635 bf 8,nol4 ; No line 4 to do...
1636 dcba br0,r11 ; Allocate cache line 4
1639 la r13,savevr6(r3) ; Point to R6/R7 pair
1640 bf 20,novr4 ; Do not save VR4...
1641 stvxl v4,br0,r12 ; Save VR4
1644 bf 21,novr5 ; Do not save VR5...
1645 stvxl v5,r14,r12 ; Save VR5
1648 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1649 la r11,savevr12(r3) ; Point to line 6
1650 bf 10,nol5 ; No line 5 to do...
1651 dcba br0,r21 ; Allocate cache line 5
1654 la r12,savevr8(r3) ; Point to V8/V9 pair
1655 bf 22,novr6 ; Do not save VR6...
1656 stvxl v6,br0,r13 ; Save VR6
1659 bf 23,novr7 ; Do not save VR7...
1660 stvxl v7,r14,r13 ; Save VR7
1664 ; Note: CR5 is now free
1666 la r21,savevr14(r3) ; Point to line 7
1667 bf 12,nol6 ; No line 6 to do...
1668 dcba br0,r11 ; Allocate cache line 6
1671 la r13,savevr10(r3) ; Point to V10/V11 pair
1672 bf 24,novr8 ; Do not save VR8...
1673 stvxl v8,br0,r12 ; Save VR8
1676 bf 25,novr9 ; Do not save VR9...
1677 stvxl v9,r14,r12 ; Save VR9
1680 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1681 la r11,savevr16(r3) ; Point to line 8
1682 bf 14,nol7 ; No line 7 to do...
1683 dcba br0,r21 ; Allocate cache line 7
1686 la r12,savevr12(r3) ; Point to V12/V13 pair
1687 bf 26,novr10 ; Do not save VR10...
1688 stvxl v10,br0,r13 ; Save VR10
1691 bf 27,novr11 ; Do not save VR11...
1692 stvxl v11,r14,r13 ; Save VR11
1697 ; Note: CR6 is now free
1699 la r21,savevr18(r3) ; Point to line 9
1700 bf 1,nol8 ; No line 8 to do...
1701 dcba br0,r11 ; Allocate cache line 8
1704 la r13,savevr14(r3) ; Point to V14/V15 pair
1705 bf 28,novr12 ; Do not save VR12...
1706 stvxl v12,br0,r12 ; Save VR12
1709 bf 29,novr13 ; Do not save VR13...
1710 stvxl v13,r14,r12 ; Save VR13
1713 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1714 la r11,savevr20(r3) ; Point to line 10
1715 bf 3,nol9 ; No line 9 to do...
1716 dcba br0,r21 ; Allocate cache line 9
1719 la r12,savevr16(r3) ; Point to V16/V17 pair
1720 bf 30,novr14 ; Do not save VR14...
1721 stvxl v14,br0,r13 ; Save VR14
1724 bf 31,novr15 ; Do not save VR15...
1725 stvxl v15,r14,r13 ; Save VR15
1729 ; Note: CR7 is now free
1731 la r21,savevr22(r3) ; Point to line 11
1732 bf 5,nol10 ; No line 10 to do...
1733 dcba br0,r11 ; Allocate cache line 10
1736 la r13,savevr18(r3) ; Point to V18/V19 pair
1737 bf 16,novr16 ; Do not save VR16...
1738 stvxl v16,br0,r12 ; Save VR16
1741 bf 17,novr17 ; Do not save VR17...
1742 stvxl v17,r14,r12 ; Save VR17
1745 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1747 ; Note: All registers have been or are accounted for in CRs
1749 la r11,savevr24(r3) ; Point to line 12
1750 bf 7,nol11 ; No line 11 to do...
1751 dcba br0,r21 ; Allocate cache line 11
1754 la r12,savevr20(r3) ; Point to V20/V21 pair
1755 bf 18,novr18 ; Do not save VR18...
1756 stvxl v18,br0,r13 ; Save VR18
1759 bf 19,novr19 ; Do not save VR19...
1760 stvxl v19,r14,r13 ; Save VR19
1763 la r21,savevr26(r3) ; Point to line 13
1764 bf 9,nol12 ; No line 12 to do...
1765 dcba br0,r11 ; Allocate cache line 12
1768 la r13,savevr22(r3) ; Point to V22/V23 pair
1769 bf 20,novr20 ; Do not save VR20...
1770 stvxl v20,br0,r12 ; Save VR20
1773 bf 21,novr21 ; Do not save VR21...
1774 stvxl v21,r14,r12 ; Save VR21
1777 la r11,savevr28(r3) ; Point to line 14
1778 bf 11,nol13 ; No line 13 to do...
1779 dcba br0,r21 ; Allocate cache line 13
1782 la r12,savevr24(r3) ; Point to V24/V25 pair
1783 bf 22,novr22 ; Do not save VR22...
1784 stvxl v22,br0,r13 ; Save VR22
1787 bf 23,novr23 ; Do not save VR23...
1788 stvxl v23,r14,r13 ; Save VR23
1791 la r21,savevr30(r3) ; Point to line 15
1792 bf 13,nol14 ; No line 14 to do...
1793 dcba br0,r11 ; Allocate cache line 14
1796 la r13,savevr26(r3) ; Point to V26/V27 pair
1797 bf 24,novr24 ; Do not save VR24...
1798 stvxl v24,br0,r12 ; Save VR24
1801 bf 25,novr25 ; Do not save VR25...
1802 stvxl v25,r14,r12 ; Save VR25
1805 bf 15,nol15 ; No line 15 to do...
1806 dcba br0,r21 ; Allocate cache line 15
1810 ; Note: All cache lines allocated now
1812 la r12,savevr28(r3) ; Point to V28/V29 pair
1813 bf 26,novr26 ; Do not save VR26...
1814 stvxl v26,br0,r13 ; Save VR26
1817 bf 27,novr27 ; Do not save VR27...
1818 stvxl v27,r14,r13 ; Save VR27
1821 la r13,savevr30(r3) ; Point to V30/V31 pair
1822 bf 28,novr28 ; Do not save VR28...
1823 stvxl v28,br0,r12 ; Save VR28
1826 bf 29,novr29 ; Do not save VR29...
1827 stvxl v29,r14,r12 ; Save VR29
1830 bf 30,novr30 ; Do not save VR30...
1831 stvxl v30,br0,r13 ; Save VR30
1834 bf 31,novr31 ; Do not save VR31...
1835 stvxl v31,r14,r13 ; Save VR31
1842 ; The context is all saved now and the facility is free.
1844 ; If we do not we need to fill the registers with junk, because this level has
1845 ; never used them before and some thieving bastard could hack the old values
1846 ; of some thread! Just imagine what would happen if they could! Why, nothing
1847 ; would be safe! My God! It is terrifying!
1849 ; Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian)
1850 ; constant that we may need to fill unused vector registers.
1856 vsnosave: vspltisb v31,-10 ; Get 0xF6F6F6F6
1857 lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
1858 vspltisb v30,5 ; Get 0x05050505
1859 lwz r19,VMXcpu(r29) ; Get the last CPU we ran on
1860 vspltish v29,4 ; Get 0x00040004
1861 lwz r14,VMXsave(r29) ; Point to the top of the "new" context stack
1862 vrlb v31,v31,v30 ; Get 0xDEDEDEDE
1864 stw r16,VMXcpu(r29) ; Claim context for us
1868 lwz r13,VMXlevel(r29) ; (TEST/DEBUG)
1869 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1870 li r2,0x5F04 ; (TEST/DEBUG)
1871 mr r1,r15 ; (TEST/DEBUG)
1872 mr r3,r14 ; (TEST/DEBUG)
1873 mr r5,r13 ; (TEST/DEBUG)
1874 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1878 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
1879 vspltisb v28,-2 ; Get 0xFEFEFEFE
1880 mulli r19,r19,ppSize ; Find offset to the owner per_proc
1881 vsubuhm v31,v31,v29 ; Get 0xDEDADEDA
1882 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
1883 vpkpx v30,v28,v3 ; Get 0x7FFF7FFF
1884 li r16,VMXowner ; Displacement to vector owner
1885 add r19,r18,r19 ; Point to the owner per_proc
1886 vrlb v31,v31,v29 ; Get 0xDEADDEAD
1889 vsinvothr: lwarx r18,r16,r19 ; Get the owner
1890 cmplw r18,r29 ; Does he still have this context?
1891 bne vsinvoths ; Nope...
1892 stwcx. r0,r16,r19 ; Try to invalidate it
1893 bne- vsinvothr ; Try again if there was a collision...
1896 vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
1897 vmrghh v31,v30,v31 ; Get 0x7FFFDEAD. V31 keeps this value until the bitter end
1898 stw r15,VMXlevel(r29) ; Set the "new" active level
1900 stw r29,VMXowner(r26) ; Mark us as having the live context
1902 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
1904 lwz r3,SAVprev(r14) ; Get the previous context
1905 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
1906 cmplw r0,r15 ; Top level correct to load?
1907 bne- ProtectTheAmericanWay ; No, go initialize...
1909 stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later)
1912 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1913 li r2,0x5F05 ; (TEST/DEBUG)
1914 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1918 lwz r22,savevrsave(r25) ; Get the most current VRSAVE
1919 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
1920 lis r9,0x5555 ; Mask with odd bits set
1921 and r10,r10,r22 ; Figure out just what registers need to be loaded
1922 ori r9,r9,0x5555 ; Finish mask
1923 rlwinm r11,r10,1,0,31 ; Shift over 1
1924 or r12,r10,r11 ; After this, even bits show which lines to touch
1925 andc r13,r12,r9 ; Clear out odd bits
1927 la r20,savevr0(r14) ; Point to line 0
1928 rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1929 la r21,savevr2(r3) ; Point to line 1
1930 or r3,r13,r3 ; Set the odd bits
1931 ; (bit 0 is line 0, bit 1 is line 8,
1932 ; bit 2 is line 1, bit 3 is line 9, etc.
1933 rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1934 mtcrf 255,r3 ; Load up the CRs
1935 mr r22,r20 ; Start registers off
1937 ; Load the new vector state
1940 bf 0,lnol0 ; No line 0 to do...
1941 dcbt br0,r20 ; Touch cache line 0
1944 la r20,savevr4(r14) ; Point to line 2
1945 bf 2,lnol1 ; No line 1 to do...
1946 dcbt br0,r21 ; Touch cache line 1
1949 la r21,savevr6(r14) ; Point to line 3
1950 bf 4,lnol2 ; No line 2 to do...
1951 dcbt br0,r20 ; Touch cache line 2
1954 li r30,16 ; Get offset for odd registers
1955 bf 16,lnovr0 ; Do not restore VR0...
1956 lvxl v0,br0,r22 ; Restore VR0
1959 la r23,savevr2(r14) ; Point to V2/V3 pair
1960 bf 17,lnovr1 ; Do not restore VR1...
1961 lvxl v1,r30,r22 ; Restore VR1
1964 la r20,savevr8(r14) ; Point to line 4
1965 bf 6,lnol3 ; No line 3 to do...
1966 dcbt br0,r21 ; Touch cache line 3
1969 la r22,savevr4(r14) ; Point to V4/V5 pair
1970 bf 18,lnovr2 ; Do not restore VR2...
1971 lvxl v2,br0,r23 ; Restore VR2
1974 bf 19,lnovr3 ; Do not restore VR3...
1975 lvxl v3,r30,r23 ; Restore VR3
1979 ; Note: CR4 is now free
1981 la r21,savevr10(r14) ; Point to line 5
1982 bf 8,lnol4 ; No line 4 to do...
1983 dcbt br0,r20 ; Touch cache line 4
1986 la r23,savevr6(r14) ; Point to R6/R7 pair
1987 bf 20,lnovr4 ; Do not restore VR4...
1988 lvxl v4,br0,r22 ; Restore VR4
1991 bf 21,lnovr5 ; Do not restore VR5...
1992 lvxl v5,r30,r22 ; Restore VR5
1995 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1996 la r20,savevr12(r14) ; Point to line 6
1997 bf 10,lnol5 ; No line 5 to do...
1998 dcbt br0,r21 ; Touch cache line 5
2001 la r22,savevr8(r14) ; Point to V8/V9 pair
2002 bf 22,lnovr6 ; Do not restore VR6...
2003 lvxl v6,br0,r23 ; Restore VR6
2006 bf 23,lnovr7 ; Do not restore VR7...
2007 lvxl v7,r30,r23 ; Restore VR7
2011 ; Note: CR5 is now free
2013 la r21,savevr14(r14) ; Point to line 7
2014 bf 12,lnol6 ; No line 6 to do...
2015 dcbt br0,r20 ; Touch cache line 6
2018 la r23,savevr10(r14) ; Point to V10/V11 pair
2019 bf 24,lnovr8 ; Do not restore VR8...
2020 lvxl v8,br0,r22 ; Restore VR8
2023 bf 25,lnovr9 ; Do not save VR9...
2024 lvxl v9,r30,r22 ; Restore VR9
2027 mtcrf 0x04,r10 ; Set CRs for registers 20-23
2028 la r20,savevr16(r14) ; Point to line 8
2029 bf 14,lnol7 ; No line 7 to do...
2030 dcbt br0,r21 ; Touch cache line 7
2033 la r22,savevr12(r14) ; Point to V12/V13 pair
2034 bf 26,lnovr10 ; Do not restore VR10...
2035 lvxl v10,br0,r23 ; Restore VR10
2038 bf 27,lnovr11 ; Do not restore VR11...
2039 lvxl v11,r30,r23 ; Restore VR11
2044 ; Note: CR6 is now free
2046 la r21,savevr18(r14) ; Point to line 9
2047 bf 1,lnol8 ; No line 8 to do...
2048 dcbt br0,r20 ; Touch cache line 8
2051 la r23,savevr14(r14) ; Point to V14/V15 pair
2052 bf 28,lnovr12 ; Do not restore VR12...
2053 lvxl v12,br0,r22 ; Restore VR12
2056 bf 29,lnovr13 ; Do not restore VR13...
2057 lvxl v13,r30,r22 ; Restore VR13
2060 mtcrf 0x02,r10 ; Set CRs for registers 24-27
2061 la r20,savevr20(r14) ; Point to line 10
2062 bf 3,lnol9 ; No line 9 to do...
2063 dcbt br0,r21 ; Touch cache line 9
2066 la r22,savevr16(r14) ; Point to V16/V17 pair
2067 bf 30,lnovr14 ; Do not restore VR14...
2068 lvxl v14,br0,r23 ; Restore VR14
2071 bf 31,lnovr15 ; Do not restore VR15...
2072 lvxl v15,r30,r23 ; Restore VR15
2076 ; Note: CR7 is now free
2078 la r21,savevr22(r14) ; Point to line 11
2079 bf 5,lnol10 ; No line 10 to do...
2080 dcbt br0,r20 ; Touch cache line 10
2083 la r23,savevr18(r14) ; Point to V18/V19 pair
2084 bf 16,lnovr16 ; Do not restore VR16...
2085 lvxl v16,br0,r22 ; Restore VR16
2088 bf 17,lnovr17 ; Do not restore VR17...
2089 lvxl v17,r30,r22 ; Restore VR17
2092 mtcrf 0x01,r10 ; Set CRs for registers 28-31
2094 ; Note: All registers have been or are accounted for in CRs
2096 la r20,savevr24(r14) ; Point to line 12
2097 bf 7,lnol11 ; No line 11 to do...
2098 dcbt br0,r21 ; Touch cache line 11
2101 la r22,savevr20(r14) ; Point to V20/V21 pair
2102 bf 18,lnovr18 ; Do not restore VR18...
2103 lvxl v18,br0,r23 ; Restore VR18
2106 bf 19,lnovr19 ; Do not restore VR19...
2107 lvxl v19,r30,r23 ; Restore VR19
2110 la r21,savevr26(r14) ; Point to line 13
2111 bf 9,lnol12 ; No line 12 to do...
2112 dcbt br0,r20 ; Touch cache line 12
2115 la r23,savevr22(r14) ; Point to V22/V23 pair
2116 bf 20,lnovr20 ; Do not restore VR20...
2117 lvxl v20,br0,r22 ; Restore VR20
2120 bf 21,lnovr21 ; Do not restore VR21...
2121 lvxl v21,r30,r22 ; Restore VR21
2124 la r20,savevr28(r14) ; Point to line 14
2125 bf 11,lnol13 ; No line 13 to do...
2126 dcbt br0,r21 ; Touch cache line 13
2129 la r22,savevr24(r14) ; Point to V24/V25 pair
2130 bf 22,lnovr22 ; Do not restore VR22...
2131 lvxl v22,br0,r23 ; Restore VR22
2134 bf 23,lnovr23 ; Do not restore VR23...
2135 lvxl v23,r30,r23 ; Restore VR23
2138 la r21,savevr30(r14) ; Point to line 15
2139 bf 13,lnol14 ; No line 14 to do...
2140 dcbt br0,r20 ; Touch cache line 14
2143 la r23,savevr26(r14) ; Point to V26/V27 pair
2144 bf 24,lnovr24 ; Do not restore VR24...
2145 lvxl v24,br0,r22 ; Restore VR24
2148 bf 25,lnovr25 ; Do not restore VR25...
2149 lvxl v25,r30,r22 ; Restore VR25
2152 bf 15,lnol15 ; No line 15 to do...
2153 dcbt br0,r21 ; Touch cache line 15
2157 ; Note: All needed cache lines have been touched now
2159 la r22,savevr28(r14) ; Point to V28/V29 pair
2160 bf 26,lnovr26 ; Do not restore VR26...
2161 lvxl v26,br0,r23 ; Restore VR26
2164 bf 27,lnovr27 ; Do not restore VR27...
2165 lvxl v27,r30,r23 ; Restore VR27
2168 la r23,savevr30(r14) ; Point to V30/V31 pair
2169 bf 28,lnovr28 ; Do not restore VR28...
2170 lvxl v28,br0,r22 ; Restore VR28
2173 bf 29,lnovr29 ; Do not restore VR29...
2174 lvxl v29,r30,r22 ; Restore VR29
2177 bf 30,lnovr30 ; Do not restore VR30...
2178 lvxl v30,br0,r23 ; Restore VR30
2182 ; Everything is restored now except for VR31. We need it to get
2183 ; the QNaNBarbarian value to put into idle vector registers.
2184 ; Note: V31 was set above to QNaNbarbarian
2187 cmpwi r10,-1 ; Handle the quick case of all registers in use
2188 beq- mstlvr31 ; Not likely, but all are in use...
2189 mtcrf 255,r10 ; Get mask of valid registers
2191 bt 0,ni0 ; Register is ok already...
2192 vor v0,v31,v31 ; Copy into the next register
2194 bt 1,ni1 ; Register is ok already...
2195 vor v1,v31,v31 ; Copy into the next register
2197 bt 2,ni2 ; Register is ok already...
2198 vor v2,v31,v31 ; Copy into the next register
2200 bt 3,ni3 ; Register is ok already...
2201 vor v3,v31,v31 ; Copy into the next register
2203 bt 4,ni4 ; Register is ok already...
2204 vor v4,v31,v31 ; Copy into the next register
2206 bt 5,ni5 ; Register is ok already...
2207 vor v5,v31,v31 ; Copy into the next register
2209 bt 6,ni6 ; Register is ok already...
2210 vor v6,v31,v31 ; Copy into the next register
2212 bt 7,ni7 ; Register is ok already...
2213 vor v7,v31,v31 ; Copy into the next register
2215 bt 8,ni8 ; Register is ok already...
2216 vor v8,v31,v31 ; Copy into the next register
2218 bt 9,ni9 ; Register is ok already...
2219 vor v9,v31,v31 ; Copy into the next register
2221 bt 10,ni10 ; Register is ok already...
2222 vor v10,v31,v31 ; Copy into the next register
2224 bt 11,ni11 ; Register is ok already...
2225 vor v11,v31,v31 ; Copy into the next register
2227 bt 12,ni12 ; Register is ok already...
2228 vor v12,v31,v31 ; Copy into the next register
2230 bt 13,ni13 ; Register is ok already...
2231 vor v13,v31,v31 ; Copy into the next register
2233 bt 14,ni14 ; Register is ok already...
2234 vor v14,v31,v31 ; Copy into the next register
2236 bt 15,ni15 ; Register is ok already...
2237 vor v15,v31,v31 ; Copy into the next register
2239 bt 16,ni16 ; Register is ok already...
2240 vor v16,v31,v31 ; Copy into the next register
2242 bt 17,ni17 ; Register is ok already...
2243 vor v17,v31,v31 ; Copy into the next register
2245 bt 18,ni18 ; Register is ok already...
2246 vor v18,v31,v31 ; Copy into the next register
2248 bt 19,ni19 ; Register is ok already...
2249 vor v19,v31,v31 ; Copy into the next register
2251 bt 20,ni20 ; Register is ok already...
2252 vor v20,v31,v31 ; Copy into the next register
2254 bt 21,ni21 ; Register is ok already...
2255 vor v21,v31,v31 ; Copy into the next register
2257 bt 22,ni22 ; Register is ok already...
2258 vor v22,v31,v31 ; Copy into the next register
2260 bt 23,ni23 ; Register is ok already...
2261 vor v23,v31,v31 ; Copy into the next register
2263 bt 24,ni24 ; Register is ok already...
2264 vor v24,v31,v31 ; Copy into the next register
2266 bt 25,ni25 ; Register is ok already...
2267 vor v25,v31,v31 ; Copy into the next register
2269 bt 26,ni26 ; Register is ok already...
2270 vor v26,v31,v31 ; Copy into the next register
2272 bt 27,ni27 ; Register is ok already...
2273 vor v27,v31,v31 ; Copy into the next register
2275 bt 28,ni28 ; Register is ok already...
2276 vor v28,v31,v31 ; Copy into the next register
2278 bt 29,ni29 ; Register is ok already...
2279 vor v29,v31,v31 ; Copy into the next register
2281 bt 30,ni30 ; Register is ok already...
2282 vor v30,v31,v31 ; Copy into the next register
2284 bf 31,lnovr31 ; V31 is empty, no need to restore...
2286 mstlvr31: lvxl v31,r30,r23 ; Restore VR31
2288 lnovr31: mr r3,r14 ; Get the old savearea (we popped it before)
2289 bl EXT(save_ret) ; Toss it
2291 vrenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
2292 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
2293 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
2294 lwz r10,ACT_MACT_SPF(r17) ; Get the special flags
2295 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
2296 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2297 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
2298 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
2299 xor r3,r25,r5 ; Get the real address of the savearea
2300 bne- vrnuser ; We are not user state...
2301 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
2302 stw r10,spcFlags(r26) ; Set per_proc copy
2306 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2307 li r2,0x5F07 ; (TEST/DEBUG)
2308 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2311 b EXT(exception_exit) ; Exit to the fray...
2314 * Initialize the registers to some bogus value
2317 ProtectTheAmericanWay:
2320 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2321 li r2,0x5F06 ; (TEST/DEBUG)
2322 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2326 vor v0,v31,v31 ; Copy into the next register
2327 vor v1,v31,v31 ; Copy into the next register
2328 vor v2,v31,v31 ; Copy into the next register
2329 vor v3,v31,v31 ; Copy into the next register
2330 vor v4,v31,v31 ; Copy into the next register
2331 vor v5,v31,v31 ; Copy into the next register
2332 vor v6,v31,v31 ; Copy into the next register
2333 vor v7,v31,v31 ; Copy into the next register
2334 vor v8,v31,v31 ; Copy into the next register
2335 vor v9,v31,v31 ; Copy into the next register
2336 vor v10,v31,v31 ; Copy into the next register
2337 vor v11,v31,v31 ; Copy into the next register
2338 vor v12,v31,v31 ; Copy into the next register
2339 vor v13,v31,v31 ; Copy into the next register
2340 vor v14,v31,v31 ; Copy into the next register
2341 vor v15,v31,v31 ; Copy into the next register
2342 vor v16,v31,v31 ; Copy into the next register
2343 vor v17,v31,v31 ; Copy into the next register
2344 vor v18,v31,v31 ; Copy into the next register
2345 vor v19,v31,v31 ; Copy into the next register
2346 vor v20,v31,v31 ; Copy into the next register
2347 vor v21,v31,v31 ; Copy into the next register
2348 vor v22,v31,v31 ; Copy into the next register
2349 vor v23,v31,v31 ; Copy into the next register
2350 vor v24,v31,v31 ; Copy into the next register
2351 vor v25,v31,v31 ; Copy into the next register
2352 vor v26,v31,v31 ; Copy into the next register
2353 vor v27,v31,v31 ; Copy into the next register
2354 vor v28,v31,v31 ; Copy into the next register
2355 vor v29,v31,v31 ; Copy into the next register
2356 vor v30,v31,v31 ; Copy into the next register
2357 b vrenable ; Finish setting it all up...
2362 ; We get here when we are switching to the same context at the same level and the context
2363 ; is still live. Essentially, all we are doing is turning on the faility. It may have
2364 ; gotten turned off due to doing a context save for the current level or a context switch
2365 ; back to the live guy.
2373 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2374 li r2,0x5F0A ; (TEST/DEBUG)
2375 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2378 beq- cr1,vrenable ; Not saved yet, nothing to pop, go enable and exit...
2380 lwz r11,SAVlevel(r30) ; Get the level of top saved context
2381 lwz r14,SAVprev(r30) ; Get the previous savearea
2383 cmplw r11,r31 ; Are live and saved the same?
2385 bne+ vrenable ; Level not the same, nothing to pop, go enable and exit...
2387 mr r3,r30 ; Get the old savearea (we popped it before)
2388 bl EXT(save_ret) ; Toss it
2389 b vrenable ; Go enable and exit...
2393 ; This function invalidates any live vector context for the passed in facility_context.
2394 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
2398 .globl EXT(toss_live_vec)
2402 mfmsr r9 ; Get the MSR
2403 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
2404 rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now?
2405 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vector is turned off
2406 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure fpu is turned off
2407 mtmsr r0 ; No interruptions
2409 beq+ tlvnotours ; Vector off, can not be live here...
2411 mfsprg r8,0 ; Get the per proc
2414 ; Note that at this point, since vecs are on, we are the owner
2415 ; of live state on this processor
2418 lwz r6,VMXowner(r8) ; Get the thread that owns the vector
2419 li r0,0 ; Clear this just in case we need it
2420 cmplw r6,r3 ; Are we tossing our own context?
2421 bne- tlvnotours ; Nope...
2423 vspltish v1,1 ; Turn on the non-Java bit and saturate
2424 vspltisw v0,1 ; Turn on the saturate bit
2425 vxor v1,v1,v0 ; Turn off saturate
2426 mtspr vrsave,r0 ; Clear VRSAVE
2427 mtvscr v1 ; Set the non-java, no saturate status
2429 tlvnotours: lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2430 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2431 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2432 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2433 li r10,VMXowner ; Displacement to vector owner
2434 add r11,r12,r11 ; Point to the owner per_proc
2435 li r0,0 ; Set a 0 to invalidate context
2437 tlvinvothr: lwarx r12,r10,r11 ; Get the owner
2438 cmplw r12,r3 ; Does he still have this context?
2439 bne+ tlvexit ; Nope, leave...
2440 stwcx. r0,r10,r11 ; Try to invalidate it
2441 bne- tlvinvothr ; Try again if there was a collision...
2443 tlvexit: mtmsr r9 ; Restore interruptions
2444 isync ; Could be turning off vectors here
2449 ; This function invalidates any live vector context for the passed in facility_context
2450 ; if the level is current. It also tosses the corresponding savearea if there is one.
2451 ; This function is primarily used whenever we detect a VRSave that is all zeros.
2455 .globl EXT(vec_trash)
2459 lwz r12,facAct(r3) ; Get the activation
2460 lwz r11,VMXlevel(r3) ; Get the context level
2461 lwz r10,ACT_MACT_PCB(r12) ; Grab the current level for the thread
2462 lwz r9,VMXsave(r3) ; Get the savearea, if any
2463 cmplw r10,r11 ; Are we at the right level?
2464 cmplwi cr1,r9,0 ; Remember if there is a savearea
2465 bnelr+ ; No, we do nothing...
2467 lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2468 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2469 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2470 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2471 li r10,VMXowner ; Displacement to vector owner
2472 add r11,r12,r11 ; Point to the owner per_proc
2473 li r0,0 ; Set a 0 to invalidate context
2475 vtinvothr: lwarx r12,r10,r11 ; Get the owner
2476 cmplw r12,r3 ; Does he still have this context?
2477 bne vtnotlive ; Nope, not live anywhere...
2478 stwcx. r0,r10,r11 ; Try to invalidate it
2479 bne- vtinvothr ; Try again if there was a collision...
2481 vtnotlive: beqlr+ cr1 ; Leave if there is no savearea
2482 lwz r8,SAVlevel(r9) ; Get the level of the savearea
2483 cmplw r8,r11 ; Savearea for the current level?
2484 bnelr+ ; No, nothing to release...
2486 lwz r8,SAVprev(r9) ; Pick up the previous area
2487 mr. r8,r8 ; Is there a previous?
2488 beq- vtnoprev ; Nope...
2489 lwz r7,SAVlevel(r8) ; Get the level associated with save
2491 vtnoprev: stw r8,VMXsave(r3) ; Dequeue this savearea
2492 stw r7,VMXlevel(r3) ; Pop the level
2494 mr r3,r9 ; Get the savearea to release
2495 b EXT(save_ret) ; Go and toss the save area (note, we will return from there)...
2499 ; Just some test code to force vector and/or floating point in the kernel
2503 .globl EXT(fctx_test)
2507 mfsprg r3,0 ; Get the per_proc block
2508 lwz r3,PP_ACTIVE_THREAD(r3) ; Get the thread pointer
2509 mr. r3,r3 ; Are we actually up and running?
2512 fmr f0,f0 ; Use floating point
2513 mftb r4 ; Get time base for a random number
2514 li r5,1 ; Get a potential vrsave to use
2515 andi. r4,r4,0x3F ; Get a number from 0 - 63
2516 slw r5,r5,r4 ; Choose a register to save (should be 0 half the time)
2517 mtspr vrsave,r5 ; Set VRSave
2518 vor v0,v0,v0 ; Use vectors