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>
40 * void load_context(thread_t thread)
42 * Load the context for the first kernel thread, and go.
44 * NOTE - if DEBUG is set, the former routine is a piece
45 * of C capable of printing out debug info before calling the latter,
46 * otherwise both entry points are identical.
49 ENTRY2(load_context, Load_context, TAG_NO_FRAME_USED)
52 * Since this is the first thread, we came in on the interrupt
53 * stack. The first thread never returns, so there is no need to
54 * worry about saving its frame, hence we can reset the istackptr
55 * back to the saved_state structure at it's top
60 * get new thread pointer and set it into the active_threads pointer
65 lwz r0,PP_INTSTACK_TOP_SS(r6)
66 lwz r11,PP_CPU_DATA(r6)
67 stw r0,PP_ISTACKPTR(r6)
68 stw r3,CPU_ACTIVE_THREAD(r11)
70 /* Find the new stack and store it in active_stacks */
72 lwz r12,PP_ACTIVE_STACKS(r6)
73 lwz r1,THREAD_KERNEL_STACK(r3)
74 lwz r9,THREAD_TOP_ACT(r3) /* Point to the active activation */
76 li r0,0 /* Clear a register */
77 lwz r8,ACT_MACT_PCB(r9) /* Get the savearea used */
78 lwz r10,SAVflags(r8) /* Get the savearea flags */
79 rlwinm r7,r8,0,0,19 /* Switch to savearea base */
80 lwz r11,SAVprev(r8) /* Get the previous savearea */
81 mfmsr r5 /* Since we are passing control, get our MSR values */
82 lwz r1,saver1(r8) /* Load new stack pointer */
83 rlwinm r10,r10,0,1,31 /* Remove the attached flag */
84 stw r0,saver3(r8) /* Make sure we pass in a 0 for the continuation */
85 lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */
86 stw r0,FM_BACKPTR(r1) /* zero backptr */
87 stw r5,savesrr1(r8) /* Pass our MSR to the new guy */
88 stw r10,SAVflags(r8) /* Pass back the flags */
89 xor r3,r7,r8 /* Get the physical address of the new context save area */
90 stw r11,ACT_MACT_PCB(r9) /* Unstack our savearea */
91 b EXT(exception_exit) /* Go end it all... */
93 /* struct thread_shuttle *Switch_context(struct thread_shuttle *old,
95 * struct thread_shuttle *new)
97 * Switch from one thread to another. If a continuation is supplied, then
98 * we do not need to save callee save registers.
102 /* void Call_continuation( void (*continuation)(void), vm_offset_t stack_ptr)
105 ENTRY(Call_continuation, TAG_NO_FRAME_USED)
107 mr r1, r4 /* Load new stack pointer */
108 blr /* Jump to the continuation */
111 * Get the old kernel stack, and store into the thread structure.
112 * See if a continuation is supplied, and skip state save if so.
113 * NB. Continuations are no longer used, so this test is omitted,
114 * as should the second argument, but it is in generic code.
115 * We always save state. This does not hurt even if continuations
119 /* Context switches are double jumps. We pass the following to the
120 * context switch firmware call:
122 * R3 = switchee's savearea
127 * savesrr0 is set to go to switch_in
128 * savesrr1 is set to uninterruptible with translation on
132 ENTRY(Switch_context, TAG_NO_FRAME_USED)
134 mfsprg r6,0 /* Get the per_proc block */
135 lwz r12,PP_ACTIVE_STACKS(r6)
137 lwz r11,PP_ISTACKPTR(r6) ; (DEBUG/TRACE) make sure we are not
138 mr. r11,r11 ; (DEBUG/TRACE) on the interrupt
139 bne+ notonintstack ; (DEBUG/TRACE) stack
143 stw r4,THREAD_CONTINUATION(r3)
144 cmpwi cr1,r4,0 /* used waaaay down below */
147 * Make the new thread the current thread.
150 lwz r11,PP_CPU_DATA(r6)
151 stw r7,THREAD_KERNEL_STACK(r3)
152 stw r5, CPU_ACTIVE_THREAD(r11)
154 lwz r11,THREAD_KERNEL_STACK(r5)
156 lwz r5,THREAD_TOP_ACT(r5)
157 lwz r10,PP_ACTIVE_STACKS(r6)
158 lwz r7,CTHREAD_SELF(r5) ; Pick up the user assist word
159 lwz r8,ACT_MACT_PCB(r5) ; Get the PCB for the new guy
161 stw r11,0(r10) ; Save the kernel stack address
162 stw r7,UAW(r6) ; Save the assist word for the "ultra fast path"
164 lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment
166 lwz r7,ACT_MACT_SPF(r5) ; Get the special flags
168 lwz r10,ACT_KLOADED(r5)
169 stw r11,ppbbTaskEnv(r6) ; Save the bb task env
172 lwz r10,PP_ACTIVE_KLOADED(r6)
173 stw r7,spcFlags(r6) ; Set per_proc copy of the special flags
174 beq cr0,.L_sw_ctx_not_kld
180 stw r0,0(r10) /* act_kloaded = 0 */
183 lis r10,hi16(EXT(trcWork)) ; Get top of trace mask
184 rlwinm r7,r8,0,0,19 /* Switch to savearea base */
185 ori r10,r10,lo16(EXT(trcWork)) ; Get bottom of mask
186 lwz r11,SAVprev(r8) /* Get the previous of the switchee's savearea */
187 lwz r10,traceMask(r10) ; Get the enabled traces
188 lis r0,hi16(CutTrace) ; Trace FW call
189 mr. r10,r10 ; Any tracing going on?
190 ori r0,r0,lo16(CutTrace) ; Trace FW call
191 beq+ cswNoTrc ; No trace today, dude...
192 mr r10,r3 ; Save across trace
193 lwz r2,THREAD_TOP_ACT(r3) ; Trace old activation
194 mr r3,r11 ; Trace prev savearea
195 sc ; Cut trace entry of context switch
198 cswNoTrc: mfmsr r6 /* Get the MSR because the switched to thread should inherit it */
199 lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */
200 lis r0,hi16(SwitchContextCall) /* Top part of switch context */
201 lis r9,hi16(EXT(switch_in)) /* Get top of switch in routine */
202 stw r11,ACT_MACT_PCB(r5) /* Dequeue the savearea we're switching to */
204 rlwinm r6,r6,0,MSR_FP_BIT+1,MSR_FP_BIT-1 /* Turn off the FP */
205 ori r9,r9,lo16(EXT(switch_in)) /* Bottom half of switch in */
206 lwz r5,savesrr0(r8) /* Set up the new SRR0 */
207 rlwinm r6,r6,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 /* Turn off the vector */
208 mr r4,r3 /* Save our old thread to pass back */
209 stw r9,savesrr0(r8) /* Make us jump to the switch in routine */
210 li r10,MSR_SUPERVISOR_INT_OFF /* Get the switcher's MSR */
211 lwz r9,SAVflags(r8) /* Get the flags */
212 stw r10,savesrr1(r8) /* Set up for switch in */
213 rlwinm r9,r9,0,15,13 /* Reset the syscall flag */
214 ori r0,r0,lo16(SwitchContextCall) /* Bottom part of switch context */
215 rlwinm r9,r9,0,1,31 /* Clear the attached flag */
216 xor r3,r7,r8 /* Get the physical address of the new context save area */
217 stw r9,SAVflags(r8) /* Set the flags */
218 /* if blocking on continuation avoid saving state */
220 sc /* Switch to the new context */
222 /* We come back here in the new thread context
223 * R4 was set to hold the old thread pointer, but switch_in will put it into
224 * R3 where it belongs.
226 blr /* Jump into the new thread */
228 1: stw r5,savesrr0(r8) /* go to real pc */
229 stw r4,saver3(r8) /* must pass back old thread */
230 b EXT(exception_exit) /* blocking on continuation, avoid state save */
235 * All switched to threads come here first to clean up the old thread.
236 * We need to do the following contortions because we need to keep
237 * the LR clean. And because we need to manipulate the savearea chain
238 * with translation on. If we could, this should be done in lowmem_vectors
239 * before translation is turned on. But we can't, dang it!
241 * R3 = switcher's savearea
242 * saver4 = old thread in switcher's save
243 * saver5 = new SRR0 in switcher's save
244 * saver6 = new SRR1 in switcher's save
249 ENTRY(switch_in, TAG_NO_FRAME_USED)
251 lwz r4,saver4(r3) /* Get the old thread */
252 li r8,MSR_VM_OFF /* Set to everything off */
253 lwz r9,THREAD_TOP_ACT(r4) /* Get the switched from ACT */
254 lwz r5,saver5(r3) /* Get the srr0 value */
255 lwz r10,ACT_MACT_PCB(r9) /* Get the top PCB on the old thread */
256 lwz r6,saver6(r3) /* Get the srr1 value */
258 stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */
259 stw r10,SAVprev(r3) /* Chain on the old one */
261 mr r3,r4 /* Pass back the old thread */
263 mtsrr0 r5 /* Set return point */
264 mtsrr1 r6 /* Set return MSR */
278 * void fpu_save(thread_act_t act)
280 * To do the floating point and VMX, we keep three thread pointers: one
281 * to the current thread, one to the thread that has the floating point context
282 * loaded into the FPU registers, and one for the VMX owner.
284 * Each of these threads has three PCB pointers. The normal PCB, the FPU pcb,
285 * and the VMX pcb. There is also a bit for each in the savearea flags.
286 * When we take an exception, or need to use the FPU/VMX in the kernel, we call
287 * this routine. It checks to see if there is an owner thread for the facility.
288 * If so, it saves the facility's state information in the normal PCB. Then, it
289 * turns on the appropriate flag in the savearea to indicate that the state is
290 * in that particular savearea. Also, the thread pointer for the owner in
291 * the per_processor block is cleared. Note that we don't have to worry about the
292 * PCB pointers in the thread because whenever the state is loaded, the associated
293 * savearea is released and the pointer cleared. This is done so that the facility
294 * context always migrates to the normal savearea/PCB. This always insures that
295 * no more than 2 saveareas are used for a thread.
297 * When the context is loaded into the facility, the associated PCB is released if
298 * its usage flags indicate that it is empty. (Note that return from exception and
299 * context switch honor these flags and won't release a savearea if there is unrestored
300 * facility context.) The per_processor is set to point to the facility owner's
301 * thread and the associated PCB pointer within the thread is cleared because
302 * the PCB has been released.
304 * Part of loading a context is to release the savearea. If the savearea contains
305 * other context, the savearea cannot be released. So, what we're left with is
306 * that there will be no normal context savearea, but one for the as-not-yet
307 * restored facility savearea. Again, when that context is reloaded, the PCB
308 * is released, and when it is again stored, it goes into the "normal" savearea.
310 * So, what do we do when there is no general context, and we have some FPU/VMX
311 * state to save? Heck if I know, but it happens when we switch threads when
312 * we shortcut system calls. The question is: does the target thread carry the
313 * FPU/VMX context with it or not? Actually, it don't matter, not one little bit.
314 * If we are asked to save it, we gotta. It's a really lousy way to do it, but
315 * short of starting over with FPUs, it's what's what. Therefore, we'll
316 * allocate an FPU context save and attach it.
318 * Actually, it's not quite that simple: since we aren't in
319 * in interrupt handler context (that's only in fpu_switch) we can't use
320 * quickfret to merge FPU into general context. So, if there is an FPU
321 * savearea, we need to use that. So what we do is: if there is FPU context
322 * use that. If there is a general context, then use that. If neither,
323 * allocate a savearea and make that the FPU context.
325 * The next thing we have to do is to allow the kernel to use both the
326 * floating point and Altivec. It is not recommended, but there may be a
327 * good reason to do so. So, what we need to do is to treat each of the
328 * three types of context the same, by keeping a LIFO chain of states.
329 * We do have a problem with that in that there can be multiple levels of
330 * kernel context. For example, we are using floating point and we take a
331 * page fault, and somehow start using the FPU, and take another page fault,
334 * Anyway, we will hope that we only reasonably use floating point and vectors in
335 * the kernel. And try to pack the context in as few saveareas as possible.
337 * The way we keep these "levels" of floating point or vector context straight is
338 * to remember the top of the normal savearea chain when we activate the
339 * facility when it is first used. Then, when we save that context, this value
340 * is saved in its level field.
342 * What the level concept gives us is a way to distinguish between multiple
343 * independent contexts under the same thread activation. Any time we take
344 * any kind of interruption (trap, system call, I/O interruption), we are,
345 * in effect, running with a different context even though we are in the
346 * same thread. The top savearea address is used only as a marker. It does not
347 * point to any context associated with the float or vector context. For example,
348 * the top savearea pointer will always be 0 for the user context, because there
349 * it it always last on the list.
351 * As normal context is unstacked, the first facility context is checked and
352 * if there is a match, the facility savearea is released. This is because we
353 * are returning to a level before the facility saved there was used. In effect,
354 * this allows us to unwind the facility context saveareas at different rates.
356 * In conjunction with the current activation, these markers are also used to
357 * determine the state of the facility enablement. Whenever the facility context is
358 * "live," i.e., loaded in the hardware registers and belonging to the currently
359 * running context, the facility is enabled before dispatch.
361 * There is nothing special about using floating point or vector facilities,
362 * no preliminary saving, enabling, or disabling. You just use them. The only exception
363 * is during context switching on an SMP system. In this case, the context must
364 * be saved as there is no guarantee that the thread will resume on the same
365 * processor. This is not a good thing, not at all.
367 * Whenever we switch out a thread with a dirty context, we always need to save it
368 * because it can wake up on a different processor. However, once the context has
369 * been saved, we don't need to save it again until it gets dirty, nor do we need
370 * to reload it unless someone else's context has been loaded. To handle this
371 * optimization, we need 3 things. We need to know what processor the saved context
372 * was last loaded on, whether the loaded context could be dirty, and if we've already
375 * Whenever the facility is enabled, the processor ID is saved in the activation. This
376 * will show which processor has dirty data. When a context switch occurs, the facility
377 * contexts are saved, but are still remembered as live. The next time we need to
378 * context switch, we first check if the state is live, and if not, do no state
379 * saving. Then we check if the state has already been save and if not, save it.
380 * The facility is always disabled on a context switch. On a UP, this save function
383 * Whenever a facility unavailable interruption occurs, the current state is saved
384 * if it is live and unsaved. However, if the live state is the same as the new
385 * one to be loaded, the processor ID is checked and if it is the current processor
386 * the state does not need to be loaded or saved. The facility is simply enabled.
388 * Once allocated, facility saveareas are not released until a return is made to a
389 * previous level. Once a facility has been enabled, there is no way to tell if
390 * it will ever be used again, but it is likely. Therefore, discarding a savearea
391 * when its context is made live is extra overhead. So, we don't do it, but we
392 * do mark the savearea contents as invalid.
397 ; The following is the actual way it is implemented. It doesn't quite match
398 ; the above text. I need to go and fix that.
400 ; Context download (operates on owner's data):
403 ; 1) if no owner exit to context restore
404 ; 2) if context processor != current processor exit to context restore
405 ; 3) if current activation == owner activation:
406 ; 1) if curr level == active level:
407 ; 1) if top facility savearea exists:
408 ; invalidate savearea by setting level to 1
409 ; 2) enable facility for user
414 ; 4) if curr level == active level:
415 ; 1) if top facility savearea exists:
416 ; 1) if top save level == active level exit to context restore
418 ; 5) allocate savearea
419 ; 1) if there is a facility save and it is invalid, select it, and break
420 ; 2) scan normal list for free facility area, select if found, and break
421 ; 3) scan other facility for free save: select, if found, and break
422 ; 4) allocate a new save area
425 ; 7) mark facility save with curr level
426 ; 8) if reusing cached savearea (case #1) exit to context restore
427 ; 9) set facility save backchain to facility top savearea
428 ; 10) set facility top to savearea
429 ; 11) exit to context restore
432 ; Context restore/upload (operates on current activation's data):
434 ; 1) set current to activation
435 ; 2) set active level to current level
436 ; 3) set context processor to current processor
437 ; 4) if no facility savearea or top save level != curr level
438 ; initialize facility registers to empty value
440 ; 1) load registers from savearea
441 ; 2) invalidate save area by setting level to 1
443 ; 6) enable facility for user
444 ; 7) exit to interrupt return
447 ; Context save (operates on specified activation's data):
449 ; 1) if no owner exit
450 ; 2) if owner != specified activation exit
451 ; 3) if context processor != current processor
455 ; 4) if facility top savearea level exists and == active level exit
456 ; 5) if curr level != active level exit
457 ; 6) allocate savearea
458 ; 1) if there is a facility save and it is invalid, select it, and break
459 ; 2) scan normal list for free facility area, select if found, and break
460 ; 3) scan other facility for free save: select, if found, and break
461 ; 4) allocate a new save area
463 ; 8) mark facility savearea with curr level
464 ; 9) if reusing cached savearea (case #1) exit
465 ; 10) set facility save backchain to facility top savearea
466 ; 11) set facility top to savearea
470 ; Exception exit (hw_exceptions):
472 ; 1) disable return facility
473 ; 2) if returning savearea != active level
474 ; 1) if owner != current activation exit
475 ; 2) if context processor != current processor:
479 ; 3) if new level != active level exit
480 ; 4) enable return facility
483 ; 3) if no facility savearea exit
484 ; 4) if top save level == active or top is invalid
485 ; 1) dequeue top facility savearea
486 ; 2) set active level to new top savearea's level
487 ; 3) release savearea
488 ; 4) if owner == current activation clear owner
494 ; if (owner == activation) && (curr level == active level)
495 ; && (activation processor == current processor) ::= context live
498 ENTRY(fpu_save, TAG_NO_FRAME_USED)
500 mfmsr r0 ; Get the MSR
501 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Turn off floating point forever
502 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
503 ori r2,r2,MASK(MSR_FP) ; Enable the floating point feature for now also
504 mtmsr r2 ; Set the MSR
507 mfsprg r6,0 ; Get the per_processor block
508 lwz r12,PP_FPU_THREAD(r6) ; Get the thread that owns the FPU
510 mr r7,r0 ; (TEST/DEBUG)
511 li r4,0 ; (TEST/DEBUG)
512 mr r10,r3 ; (TEST/DEBUG)
513 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
514 mr. r3,r12 ; (TEST/DEBUG)
515 li r2,0x6F00 ; (TEST/DEBUG)
516 li r5,0 ; (TEST/DEBUG)
517 beq- noowneryet ; (TEST/DEBUG)
518 lwz r4,ACT_MACT_FPUlvl(r12) ; (TEST/DEBUG)
519 lwz r5,ACT_MACT_FPU(r12) ; (TEST/DEBUG)
521 noowneryet: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
523 mr r0,r7 ; (TEST/DEBUG)
524 mr r3,r10 ; (TEST/DEBUG)
526 mflr r2 ; Save the return address
527 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
529 mr. r12,r12 ; Anyone own the FPU?
530 cmplw cr1,r3,r12 ; Is the specified thread the owner?
532 beq- fsretnr ; Nobody owns the FPU, no save required...
534 li r4,ACT_MACT_FPUcpu ; Point to the CPU indication/lock word
535 bne- cr1,fsretnr ; Facility belongs to some other activation...
537 fsvSpin2: lwarx r9,r4,r12 ; Get and reserve the last used CPU
538 mr. r9,r9 ; Is it changing now?
539 oris r3,r9,hi16(fvChk) ; Set the "changing" flag
540 blt- fsvSpin2 ; Spin if changing
541 stwcx. r3,r4,r12 ; Lock it up
542 bne- fsvSpin2 ; Someone is messing right now
544 isync ; Make sure we see everything
546 cmplw cr1,r9,r11 ; Was the context for this processor?
547 li r3,0 ; Assume we need a fix-me-up
548 beq- cr1,fsgoodcpu ; Facility last used on this processor...
549 stw r3,PP_FPU_THREAD(r6) ; Clear owner because it was really on the other processor
550 b fsret ; Bail now with no save...
552 fsgoodcpu: lwz r3,ACT_MACT_FPU(r12) ; Get the current FPU savearea for the thread
553 lwz r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator
555 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
556 beq- cr1,fsneedone ; Never saved it, so we need an area...
558 lwz r8,SAVlvlfp(r3) ; Get the level this savearea is for
559 cmplwi r8,1 ; See if it is a spare
560 cmplw cr1,r9,r8 ; Correct level?
561 beq+ fsusespare ; We have a spare to use...
562 beq- cr1,fsret ; The current level is already saved, bail out...
564 fsneedone: li r3,0 ; Tell the routine to allocate an area if none found
565 bl fpsrchsave ; Find a free savearea
567 mfsprg r6,0 ; Get back per_processor block
568 oris r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
569 lwz r12,PP_FPU_THREAD(r6) ; Get back our thread
570 mtlr r2 ; Restore return
571 lwz r8,ACT_MACT_FPU(r12) ; Get the current top floating point savearea
572 lwz r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator again
573 stw r3,ACT_MACT_FPU(r12) ; Set this as the latest FPU savearea for the thread
574 stw r8,SAVprefp(r3) ; And then chain this in front
575 stw r7,SAVflags(r3) ; Set the validity flags
576 stw r12,SAVact(r3) ; Make sure we point to the right guy
578 fsusespare: stw r9,SAVlvlfp(r3) ; And set the level this savearea is for
581 ; Save the current FPU state into the PCB of the thread that owns it.
584 la r11,savefp0(r3) ; Point to the 1st line
585 dcbz 0,r11 ; Allocate the first savearea line
587 la r11,savefp4(r3) /* Point to the 2nd line */
589 dcbz 0,r11 /* allocate it */
592 la r11,savefp8(r3) /* Point to the 3rd line */
594 dcbz 0,r11 /* allocate it */
598 la r11,savefp12(r3) /* Point to the 4th line */
600 dcbz 0,r11 /* allocate it */
603 stfd f10,savefp10(r3)
604 la r11,savefp16(r3) /* Point to the 5th line */
605 stfd f11,savefp11(r3)
606 dcbz 0,r11 /* allocate it */
607 stfd f12,savefp12(r3)
608 stfd f13,savefp13(r3)
609 stfd f14,savefp14(r3)
610 la r11,savefp20(r3) /* Point to the 6th line */
611 stfd f15,savefp15(r3)
612 stfd f16,savefp16(r3)
613 stfd f17,savefp17(r3)
614 stfd f18,savefp18(r3)
615 la r11,savefp24(r3) /* Point to the 7th line */
616 stfd f19,savefp19(r3)
617 dcbz 0,r11 /* allocate it */
618 stfd f20,savefp20(r3)
619 lwz r10,liveFPSCR(r6) ; Get the previously saved FPSCR
620 stfd f21,savefp21(r3)
621 stfd f22,savefp22(r3)
622 li r9,0 ; Just clear this out
623 la r11,savefp28(r3) /* Point to the 8th line */
624 stfd f23,savefp23(r3)
625 dcbz 0,r11 /* allocate it */
626 stfd f24,savefp24(r3)
627 stfd f25,savefp25(r3)
628 stfd f26,savefp26(r3)
629 stfd f27,savefp27(r3)
630 stfd f28,savefp28(r3)
632 ; Note that we just save the FPSCR here for ease. It is really already saved
633 ; in the "normal" context area of the savearea.
635 stw r9,savefpscrpad(r3) ; Save the FPSCR pad
636 stw r10,savefpscr(r3) ; Save the FPSCR
638 stfd f29,savefp29(r3)
639 stfd f30,savefp30(r3)
640 stfd f31,savefp31(r3)
641 lfd f0,savefp0(r3) ; We need to restore F0 because we used it
645 la r9,savefp0(r3) ; (TEST/DEBUG)
646 la r10,savefp31(r3) ; (TEST/DEBUG)
649 lha r8,0(r9) ; (TEST/DEBUG)
650 addi r9,r9,8 ; (TEST/DEBUG)
651 cmpwi r8,-8 ; (TEST/DEBUG)
652 cmplw cr1,r9,r10 ; (TEST/DEBUG)
653 bne+ dontkillmedead ; (TEST/DEBUG)
654 BREAKPOINT_TRAP ; (TEST/DEBUG)
656 dontkillmedead: ; (TEST/DEBUG)
657 ble+ cr1,chkkillmedead ; (TEST/DEBUG)
660 fsret: lwz r4,ACT_MACT_FPUcpu(r12) ; Get back the owner CPU
661 rlwinm r4,r4,0,fvChkb+1,31 ; Clear lock
663 stw r4,ACT_MACT_FPUcpu(r12) ; Unlock the context
665 fsretnr: mtmsr r0 ; Put interrupts on if they were and floating point off
673 * Entered to handle the floating-point unavailable exception and
676 * This code is run in virtual address mode on with interrupts off.
678 * Upon exit, the code returns to the users context with the floating
679 * point facility turned on.
681 * ENTRY: VM switched ON
683 * State is saved in savearea pointed to by R4.
684 * All other registers are free.
688 ENTRY(fpu_switch, TAG_NO_FRAME_USED)
691 mr r7,r4 ; Save input parameter
692 lis r3,hi16(EXT(fpu_trap_count)) ; Get address of FP trap counter
693 ori r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
695 lis r5,hi16(EXT(GratefulDeb)) ; Point to top of display
696 ori r5,r5,lo16(EXT(GratefulDeb)) ; Put in bottom part
698 mtlr r5 ; Set link register
703 mr r4,r7 ; Restore the parameter
705 lis r3,hi16(EXT(fpu_trap_count)) ; Get address of FP trap counter
706 ori r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
713 mfsprg r6,0 ; Get the per_processor block
714 mfmsr r19 ; Get the current MSR
716 lwz r10,PP_CPU_DATA(r6) ; Get the CPU data pointer
717 lwz r12,PP_FPU_THREAD(r6) ; Get the thread that owns the FPU
718 lwz r10,CPU_ACTIVE_THREAD(r10) ; Get the pointer to the active thread
719 ori r19,r19,lo16(MASK(MSR_FP)) ; Enable the floating point feature
720 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
722 ; R12 has the "old" activation
723 ; R17 has the "new" activation
726 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
727 li r2,0x7F01 ; (TEST/DEBUG)
728 mr r3,r12 ; (TEST/DEBUG)
729 mr r5,r17 ; (TEST/DEBUG)
730 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
733 mr. r12,r12 ; See if there is any live FP status
735 lhz r18,PP_CPU_NUMBER(r6) ; Get the current CPU, we will need it later
737 mtmsr r19 ; Enable floating point instructions
740 beq- fsnosave ; No live context, so nothing to save...
742 li r20,ACT_MACT_FPUcpu ; Point to the CPU indication/lock word
744 fsSpin1: lwarx r19,r20,r12 ; Get and reserve the last used CPU
745 mr. r19,r19 ; Is it changing now?
746 oris r21,r19,hi16(fvChk) ; Set the "changing" flag
747 blt- fsSpin1 ; Spin if changing
748 stwcx. r21,r20,r12 ; Lock it up
749 bne- fsSpin1 ; Someone is messing right now
751 isync ; Make sure we see everything
753 lwz r15,ACT_MACT_PCB(r12) ; Get the current level of the "old" one
754 cmplw r18,r19 ; Check the CPU that the old context is live on
755 lwz r14,ACT_MACT_FPU(r12) ; Point to the top of the old context stack
756 bne- fsnosaverel ; Context is not live if used on a different CPU...
757 lwz r13,ACT_MACT_FPUlvl(r12) ; Get the "old" active level
760 ; First, check to see if all we are doing is enabling because the
761 ; "new" context is live.
764 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
765 li r2,0x7F02 ; (TEST/DEBUG)
766 mr r1,r15 ; (TEST/DEBUG)
767 mr r3,r13 ; (TEST/DEBUG)
768 mr r5,r14 ; (TEST/DEBUG)
769 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
773 cmplw cr1,r12,r17 ; Are the "old" activation and the "new" the same?
774 cmplwi cr2,r14,0 ; Is there any saved context on the "old" activation?
775 bne+ cr1,fsmstsave ; The activations are different so "old" context must be saved...
778 ; Here we know that both the "old" and "new" activations are the same. We will
779 ; check the current level and active levels. If they are the same, the context is
780 ; already live, so all we do is turn on the facility and invalidate the top
783 ; If the current level, the active level, and the top savearea level are the
784 ; same, then the context was saved as part of a thread context switch and neither
785 ; needs saving or restoration.
787 ; In all other cases, the context must be saved unless we are just re-enabling
791 cmplw r13,r15 ; Are the levels the same?
792 cmplwi cr2,r14,0 ; Is there any saved context?
793 bne- fsmstsave ; Levels are different, we need to save...
795 beq- cr2,fsenableret ; No saved context at all, enable and go...
797 lwz r20,SAVlvlfp(r14) ; Get the level of the top savearea
800 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
801 li r2,0x7F03 ; (TEST/DEBUG)
802 mr r3,r15 ; (TEST/DEBUG)
803 mr r5,r20 ; (TEST/DEBUG)
804 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
807 cmplw r15,r20 ; Is the top level the same as the current?
808 li r0,1 ; Get the invalid flag
809 bne- fsenableret ; Not the same, just enable and go...
811 stw r0,SAVlvlfp(r14) ; Invalidate that top savearea
813 sync ; Make sure everything is saved
814 stw r19,ACT_MACT_FPUcpu(r12) ; Say we are not using the context anymore
816 b fsenable ; Then enable and go...
819 ; We need to save the "old" context here. The LIFO queueing scheme works
820 ; out for all cases because if both the "new" and "old" activations are the
821 ; same, there can not be any saved state to load. the "new" level is
824 ; When we save the context, we either use a new savearea, or the free
825 ; one that is cached at the head of the list.
827 fsmstsave: beq- cr2,fsgetsave ; There is no possible cached save area
829 lwz r5,SAVlvlfp(r14) ; Get the level of first facility savearea
831 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
832 li r2,0x7F04 ; (TEST/DEBUG)
833 mr r3,r15 ; (TEST/DEBUG)
834 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
837 mr r3,r14 ; Assume we are invalid
838 cmplwi r5,1 ; Is it invalid?
839 cmplw cr1,r5,r13 ; Is the SA level the active one?
840 beq+ fsusecache ; Invalid, just use it...
841 beq- cr1,fsnosaverel ; The SA level is active, it is already saved...
843 fsgetsave: mr r3,r4 ; Use the interrupt save as the context savearea if none cached
845 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
846 li r2,0x7F05 ; (TEST/DEBUG)
847 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
851 bl fpsrchsave ; Find a free savearea
853 stw r3,ACT_MACT_FPU(r12) ; Set this as the latest context savearea for the thread
854 mfsprg r6,0 ; Get back per_processor block
855 stw r14,SAVprefp(r3) ; And then chain this in front
856 oris r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
857 stw r12,SAVact(r3) ; Make sure we point to the right guy
858 stw r7,SAVflags(r3) ; Set the allocation flags
860 fsusecache: la r11,savefp0(r3) ; Point to the 1st line in area
861 stw r13,SAVlvlfp(r3) ; Set this context level
863 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
864 li r2,0x7F06 ; (TEST/DEBUG)
865 mr r5,r13 ; (TEST/DEBUG)
866 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
871 ; Now we will actually save the old context
874 dcbz 0,r11 ; Allocate the output area
876 la r11,savefp4(r3) ; Point to the 2nd line
878 dcbz 0,r11 ; Allocate cache
881 la r11,savefp8(r3) ; Point to the 3rd line
883 dcbz 0,r11 ; Allocate cache
887 la r11,savefp12(r3) ; Point to the 4th line
889 dcbz 0,r11 ; Allocate cache
892 stfd f10,savefp10(r3)
893 la r11,savefp16(r3) ; Point to the 5th line
894 stfd f11,savefp11(r3)
895 dcbz 0,r11 ; Allocate cache
896 stfd f12,savefp12(r3)
897 stfd f13,savefp13(r3)
898 stfd f14,savefp14(r3)
899 la r11,savefp20(r3) ; Point to the 6th line
900 stfd f15,savefp15(r3)
901 dcbz 0,r11 ; Allocate cache
902 stfd f16,savefp16(r3)
903 stfd f17,savefp17(r3)
904 stfd f18,savefp18(r3)
905 la r11,savefp24(r3) ; Point to the 7th line
906 stfd f19,savefp19(r3)
907 dcbz 0,r11 ; Allocate cache
908 stfd f20,savefp20(r3)
910 li r14,0 ; Clear this for now
911 lwz r15,liveFPSCR(r6) ; Get the previously saved FPSCR
913 stfd f21,savefp21(r3)
914 stfd f22,savefp22(r3)
915 la r11,savefp28(r3) ; Point to the 8th line
916 stfd f23,savefp23(r3)
917 dcbz 0,r11 ; allocate it
918 stfd f24,savefp24(r3)
919 stfd f25,savefp25(r3)
920 stfd f26,savefp26(r3)
921 la r11,savefpscrpad(r3) ; Point to the 9th line
922 stfd f27,savefp27(r3)
923 dcbz 0,r11 ; allocate it
924 stfd f28,savefp28(r3)
925 stfd f29,savefp29(r3)
926 stfd f30,savefp30(r3)
927 stfd f31,savefp31(r3)
929 ; Note that we just save the FPSCR here for ease. It is really already saved
930 ; in the "normal" context area of the savearea.
932 stw r14,savefpscrpad(r3) ; Save the FPSCR pad
933 stw r15,savefpscr(r3) ; Save the FPSCR
936 ; The context is all saved now and the facility is free.
938 ; Now check out the "new" and see if we need to load up his context.
939 ; If we do (and this should be the normal case), do it and then invalidate the
940 ; savearea. (This will keep it cached for quick access next time around.)
942 ; If we do not (remember, we already took care of the case where we just enable
943 ; the FPU), we need to fill the registers with junk, because this level has
944 ; never used them before and some thieving bastard could hack the old values
945 ; of some thread! Just imagine what would happen if they could! Why, nothing
946 ; would be safe! My God! It is terrifying!
951 sync ; Make sure everything is saved
952 stw r19,ACT_MACT_FPUcpu(r12) ; Say we are not using the context anymore
955 li r20,ACT_MACT_FPUcpu ; Point to the CPU indication/lock word
957 fsSpin2: lwarx r19,r20,r17 ; Get and reserve the last used CPU
958 mr. r19,r19 ; Is it changing now?
959 oris r21,r19,hi16(fvChk) ; Set the "changing" flag
960 blt- fsSpin2 ; Spin if changing
961 stwcx. r21,r20,r17 ; Lock it up
962 bne- fsSpin2 ; Someone is messing right now
964 isync ; Make sure we see everything
966 lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
967 lwz r14,ACT_MACT_FPU(r17) ; Point to the top of the "new" context stack
968 lwz r13,ACT_MACT_FPUlvl(r17) ; Get the "new" active level
970 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
971 li r2,0x7F07 ; (TEST/DEBUG)
972 mr r1,r15 ; (TEST/DEBUG)
973 mr r3,r14 ; (TEST/DEBUG)
974 mr r5,r13 ; (TEST/DEBUG)
975 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
979 cmplwi cr1,r14,0 ; Do we possibly have some context to load?
980 stw r15,ACT_MACT_FPUlvl(r17) ; Set the "new" active level
981 la r11,savefp0(r14) ; Point to first line to bring in
982 stw r17,PP_FPU_THREAD(r6) ; Store current thread address in fpu_thread to claim fpu for thread
984 beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load...
985 lwz r0,SAVlvlfp(r14) ; Get the level of first facility savearea
986 cmplw r0,r15 ; Top level correct to load?
987 bne- MakeSureThatNoTerroristsCanHurtUsByGod ; No, go initialize...
990 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
991 li r2,0x7F08 ; (TEST/DEBUG)
992 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
996 dcbt 0,r11 ; Touch line in
997 li r0,1 ; Get the level invalid indication
999 la r11,savefp4(r14) ; Point to next line
1000 dcbt 0,r11 ; Touch line in
1001 lfd f0, savefp0(r14)
1003 stw r0,SAVlvlfp(r14) ; Mark the savearea invalid because we are activating again
1005 la r11,savefp8(r14) ; Point to next line
1007 dcbt 0,r11 ; Touch line in
1011 la r11,savefp12(r14) ; Point to next line
1013 dcbt 0,r11 ; Touch line in
1016 lfd f10,savefp10(r14)
1017 la r11,savefp16(r14) ; Point to next line
1018 lfd f11,savefp11(r14)
1019 dcbt 0,r11 ; Touch line in
1020 lfd f12,savefp12(r14)
1021 lfd f13,savefp13(r14)
1022 lfd f14,savefp14(r14)
1023 la r11,savefp20(r14) ; Point to next line
1024 lfd f15,savefp15(r14)
1025 dcbt 0,r11 ; Touch line in
1026 lfd f16,savefp16(r14)
1027 lfd f17,savefp17(r14)
1028 lfd f18,savefp18(r14)
1029 la r11,savefp24(r14) ; Point to next line
1030 lfd f19,savefp19(r14)
1031 dcbt 0,r11 ; Touch line in
1032 lfd f20,savefp20(r14)
1033 lfd f21,savefp21(r14)
1034 la r11,savefp28(r14) ; Point to next line
1035 lfd f22,savefp22(r14)
1036 lfd f23,savefp23(r14)
1037 dcbt 0,r11 ; Touch line in
1038 lfd f24,savefp24(r14)
1039 lfd f25,savefp25(r14)
1040 lfd f26,savefp26(r14)
1041 lfd f27,savefp27(r14)
1042 lfd f28,savefp28(r14)
1043 lfd f29,savefp29(r14)
1044 lfd f30,savefp30(r14)
1045 lfd f31,savefp31(r14)
1047 fsenablexx: sync ; Make sure all is saved
1048 stw r18,ACT_MACT_FPUcpu(r17) ; Set the active CPU and release
1050 fsenable: lwz r9,SAVflags(r4) /* Get the flags of the current savearea */
1051 lwz r8,savesrr1(r4) ; Get the msr of the interrupted guy
1052 rlwinm r5,r4,0,0,19 /* Get the page address of the savearea */
1053 ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature
1054 lwz r10,ACT_MACT_SPF(r17) ; Get the special flags
1055 lis r7,hi16(SAVattach) /* Get the attached flag */
1056 lwz r5,SACvrswap(r5) /* Get Virtual to Real translation */
1057 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
1058 mr. r15,r15 ; See if we are doing this for user state
1059 stw r8,savesrr1(r4) ; Set the msr of the interrupted guy
1060 andc r9,r9,r7 /* Clear the attached bit */
1061 xor r3,r4,r5 /* Get the real address of the savearea */
1062 bne- fsnuser ; We are not user state...
1063 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
1064 stw r10,spcFlags(r6) ; Set per_proc copy
1068 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1069 li r2,0x7F0A ; (TEST/DEBUG)
1070 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1073 stw r9,SAVflags(r4) /* Set the flags of the current savearea */
1075 b EXT(exception_exit) /* Exit from the fray... */
1078 * Initialize the registers to some bogus value
1081 MakeSureThatNoTerroristsCanHurtUsByGod:
1084 lwz r10,savesrr1(r4) ; (TEST/DEBUG)
1085 rlwinm. r10,r10,0,MSR_PR_BIT,MSR_PR_BIT ; (TEST/DEBUG)
1086 beq- nxxxxxx ; (TEST/DEBUG)
1087 lwz r10,ACT_MACT_SPF(r17) ; (TEST/DEBUG)
1088 rlwinm. r10,r10,0,1,1 ; (TEST/DEBUG)
1090 BREAKPOINT_TRAP ; (TEST/DEBUG)
1095 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1096 li r2,0x7F09 ; (TEST/DEBUG)
1097 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1100 lis r5,hi16(EXT(FloatInit)) /* Get top secret floating point init value address */
1101 ori r5,r5,lo16(EXT(FloatInit)) /* Slam bottom */
1102 lfd f0,0(r5) /* Initialize FP0 */
1103 fmr f1,f0 ; Do them all
1120 fsub f31,f31,f31 ; Get set to initialize the FPSCR
1124 mtfsf 0xff,f31 ; Clear all FPSCR exception eanbles
1136 b fsenablexx ; Finish setting it all up...
1139 ; Finds an unused floating point area in the activation pointed
1140 ; to by R12s saved contexts. If none are found (unlikely but possible)
1141 ; and R3 is 0, a new area is allocated. If R3 is non-zero, it contains
1142 ; a pointer to an floating point savearea that is free.
1145 lwz r6,ACT_MACT_PCB(r12) ; Get the first "normal" savearea
1147 fpsrnorm: mr. r5,r6 ; Is there another?
1148 beq- fpsrvect ; No, search the vector saveareas...
1149 lwz r7,SAVflags(r5) ; Get the flags for this guy
1150 lwz r6,SAVprev(r5) ; Get the previous savearea, just in case
1151 andis. r8,r7,hi16(SAVfpuvalid) ; Have we found an empty FPU save in normal?
1152 beq+ fpsrgot ; We found one...
1153 b fpsrnorm ; Search again...
1155 fpsrvect: lwz r6,ACT_MACT_VMX(r12) ; Get the first "vector" savearea
1157 fpsrvectx: mr. r5,r6 ; Is there another?
1158 beq- fpsrget ; No, try to allocate one...
1159 lwz r7,SAVflags(r5) ; Get the flags for this guy
1160 lwz r6,SAVprevec(r5) ; Get the previous savearea, just in case
1161 andis. r8,r7,hi16(SAVfpuvalid) ; Have we found an empty FPU save in vector?
1162 bne- fpsrvectx ; Search again...
1164 fpsrgot: mr r3,r5 ; Get the savearea into the right register
1167 fpsrget: mr. r5,r3 ; Do we allocate or use existing?
1168 beq+ fpsrallo ; Allocate one...
1170 lwz r7,SAVflags(r3) ; Get the passed in area flags
1173 ; NOTE: save_get will return directly and set R7 to 0...
1175 fpsrallo: b EXT(save_get) ; Get a fresh savearea
1178 * Altivec stuff is here. The techniques used are pretty identical to
1179 * the floating point. Except that we will honor the VRSAVE register
1180 * settings when loading and restoring registers.
1182 * There are two indications of saved VRs: the VRSAVE register and the vrvalid
1183 * mask. VRSAVE is set by the vector user and represents the VRs that they
1184 * say that they are using. The vrvalid mask indicates which vector registers
1185 * are saved in the savearea. Whenever context is saved, it is saved according
1186 * to the VRSAVE register. It is loaded based on VRSAVE anded with
1187 * vrvalid (all other registers are splatted with 0s). This is done because we
1188 * don't want to load any registers we don't have a copy of, we want to set them
1193 ENTRY(vec_save, TAG_NO_FRAME_USED)
1195 mfmsr r0 ; Get the MSR
1196 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Turn off vector forever
1197 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
1198 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
1199 mtmsr r2 ; Set the MSR
1202 mfsprg r6,0 ; Get the per_processor block
1203 lwz r12,PP_VMX_THREAD(r6) ; Get the thread that owns the vector
1205 mr r7,r0 ; (TEST/DEBUG)
1206 li r4,0 ; (TEST/DEBUG)
1207 mr r10,r3 ; (TEST/DEBUG)
1208 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1209 mr. r3,r12 ; (TEST/DEBUG)
1210 li r2,0x5F00 ; (TEST/DEBUG)
1211 li r5,0 ; (TEST/DEBUG)
1212 beq- noowneryeu ; (TEST/DEBUG)
1213 lwz r4,ACT_MACT_VMXlvl(r12) ; (TEST/DEBUG)
1214 lwz r5,ACT_MACT_VMX(r12) ; (TEST/DEBUG)
1216 noowneryeu: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1218 mr r0,r7 ; (TEST/DEBUG)
1219 mr r3,r10 ; (TEST/DEBUG)
1221 mflr r2 ; Save the return address
1222 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
1224 mr. r12,r12 ; Anyone own the vector?
1225 cmplw cr1,r3,r12 ; Is the specified thread the owner?
1227 beq- vsretnr ; Nobody owns the vector, no save required...
1229 li r4,ACT_MACT_VMXcpu ; Point to the CPU indication/lock word
1230 bne- cr1,vsretnr ; Facility belongs to some other activation...
1232 vsvSpin2: lwarx r9,r4,r12 ; Get and reserve the last used CPU
1233 mr. r9,r9 ; Is it changing now?
1234 oris r3,r9,hi16(fvChk) ; Set the "changing" flag
1235 blt- vsvSpin2 ; Spin if changing
1236 stwcx. r3,r4,r12 ; Lock it up
1237 bne- vsvSpin2 ; Someone is messing right now
1239 isync ; Make sure we see everything
1241 cmplw cr1,r9,r11 ; Was the context for this processor?
1242 li r3,0 ; Assume we need a fix-me-up
1243 beq- cr1,vsgoodcpu ; Facility last used on this processor...
1244 stw r3,PP_VMX_THREAD(r6) ; Clear owner because it was really on the other processor
1245 b vsret ; Bail now with no save...
1247 vsgoodcpu: lwz r3,ACT_MACT_VMX(r12) ; Get the current vector savearea for the thread
1248 lwz r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator
1250 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
1251 beq- cr1,vsneedone ; Never saved it, so we need an area...
1253 lwz r8,SAVlvlvec(r3) ; Get the level this savearea is for
1254 cmplwi r8,1 ; See if this is a spare
1255 cmplw cr1,r9,r8 ; Correct level?
1256 beq+ vsusespare ; It is still live...
1257 beq- cr1,vsret ; The current level is already saved, bail out...
1259 vsneedone: li r3,0 ; Tell the routine to allocate an area if none found
1260 bl vsrchsave ; Find a free savearea
1262 mfsprg r6,0 ; Get back per_processor block
1263 oris r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
1264 lwz r12,PP_VMX_THREAD(r6) ; Get back our thread
1265 mtlr r2 ; Restore return
1266 lwz r8,ACT_MACT_VMX(r12) ; Get the current top vector savearea
1267 lwz r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator again
1268 stw r3,ACT_MACT_VMX(r12) ; Set this as the latest vector savearea for the thread
1269 stw r8,SAVprevec(r3) ; And then chain this in front
1270 stw r7,SAVflags(r3) ; Set the allocation flags
1271 stw r12,SAVact(r3) ; Make sure we point to the right guy
1273 vsusespare: stw r9,SAVlvlvec(r3) ; And set the level this savearea is for
1274 mfcr r2 ; Save non-volatile CRs
1275 lwz r10,liveVRS(r6) ; Get the right VRSave register
1276 lis r9,0x5555 ; Mask with odd bits set
1277 rlwinm r11,r10,1,0,31 ; Shift over 1
1278 ori r9,r9,0x5555 ; Finish mask
1279 or r4,r10,r11 ; After this, even bits show which lines to zap
1281 andc r11,r4,r9 ; Clear out odd bits
1283 la r6,savevr0(r3) ; Point to line 0
1284 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits
1285 la r9,savevrvalid(r3) ; Point to the saved register mask field
1286 or r4,r11,r4 ; Set the odd bits
1287 ; (bit 0 is line 0, bit 1 is line 8,
1288 ; bit 2 is line 1, bit 3 is line 9, etc.
1289 dcba br0,r9 ; Allocate the cache for it
1290 rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1291 la r7,savevr2(r3) ; Point to line 1
1292 mtcrf 255,r4 ; Load up the CRs
1293 stw r10,savevrvalid(r3) ; Save the validity information
1294 mr r8,r6 ; Start registers off
1296 ; Save the current vector state
1299 bf 0,snol0 ; No line 0 to do...
1300 dcba br0,r6 ; Allocate cache line 0
1303 la r6,savevr4(r3) ; Point to line 2
1304 bf 2,snol1 ; No line 1 to do...
1305 dcba br0,r7 ; Allocate cache line 1
1308 la r7,savevr6(r3) ; Point to line 3
1309 bf 4,snol2 ; No line 2 to do...
1310 dcba br0,r6 ; Allocate cache line 2
1313 li r11,16 ; Get offset for odd registers
1314 bf 16,snovr0 ; Do not save VR0...
1315 stvxl v0,br0,r8 ; Save VR0
1318 la r9,savevr2(r3) ; Point to V2/V3 pair
1319 bf 17,snovr1 ; Do not save VR1...
1320 stvxl v1,r11,r8 ; Save VR1
1323 la r6,savevr8(r3) ; Point to line 4
1324 bf 6,snol3 ; No line 3 to do...
1325 dcba br0,r7 ; Allocate cache line 3
1328 la r8,savevr4(r3) ; Point to V4/V5 pair
1329 bf 18,snovr2 ; Do not save VR2...
1330 stvxl v2,br0,r9 ; Save VR2
1333 bf 19,snovr3 ; Do not save VR3...
1334 stvxl v3,r11,r9 ; Save VR3
1338 ; Note: CR4 is now free
1340 la r7,savevr10(r3) ; Point to line 5
1341 bf 8,snol4 ; No line 4 to do...
1342 dcba br0,r6 ; Allocate cache line 4
1345 la r9,savevr6(r3) ; Point to R6/R7 pair
1346 bf 20,snovr4 ; Do not save VR4...
1347 stvxl v4,br0,r8 ; Save VR4
1350 bf 21,snovr5 ; Do not save VR5...
1351 stvxl v5,r11,r8 ; Save VR5
1354 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1355 la r6,savevr12(r3) ; Point to line 6
1356 bf 10,snol5 ; No line 5 to do...
1357 dcba br0,r7 ; Allocate cache line 5
1360 la r8,savevr8(r3) ; Point to V8/V9 pair
1361 bf 22,snovr6 ; Do not save VR6...
1362 stvxl v6,br0,r9 ; Save VR6
1365 bf 23,snovr7 ; Do not save VR7...
1366 stvxl v7,r11,r9 ; Save VR7
1370 ; Note: CR5 is now free
1372 la r7,savevr14(r3) ; Point to line 7
1373 bf 12,snol6 ; No line 6 to do...
1374 dcba br0,r6 ; Allocate cache line 6
1377 la r9,savevr10(r3) ; Point to V10/V11 pair
1378 bf 24,snovr8 ; Do not save VR8...
1379 stvxl v8,br0,r8 ; Save VR8
1382 bf 25,snovr9 ; Do not save VR9...
1383 stvxl v9,r11,r8 ; Save VR9
1386 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1387 la r6,savevr16(r3) ; Point to line 8
1388 bf 14,snol7 ; No line 7 to do...
1389 dcba br0,r7 ; Allocate cache line 7
1392 la r8,savevr12(r3) ; Point to V12/V13 pair
1393 bf 26,snovr10 ; Do not save VR10...
1394 stvxl v10,br0,r9 ; Save VR10
1397 bf 27,snovr11 ; Do not save VR11...
1398 stvxl v11,r11,r9 ; Save VR11
1403 ; Note: CR6 is now free
1405 la r7,savevr18(r3) ; Point to line 9
1406 bf 1,snol8 ; No line 8 to do...
1407 dcba br0,r6 ; Allocate cache line 8
1410 la r9,savevr14(r3) ; Point to V14/V15 pair
1411 bf 28,snovr12 ; Do not save VR12...
1412 stvxl v12,br0,r8 ; Save VR12
1415 bf 29,snovr13 ; Do not save VR13...
1416 stvxl v13,r11,r8 ; Save VR13
1419 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1420 la r6,savevr20(r3) ; Point to line 10
1421 bf 3,snol9 ; No line 9 to do...
1422 dcba br0,r7 ; Allocate cache line 9
1425 la r8,savevr16(r3) ; Point to V16/V17 pair
1426 bf 30,snovr14 ; Do not save VR14...
1427 stvxl v14,br0,r9 ; Save VR14
1430 bf 31,snovr15 ; Do not save VR15...
1431 stvxl v15,r11,r9 ; Save VR15
1435 ; Note: CR7 is now free
1437 la r7,savevr22(r3) ; Point to line 11
1438 bf 5,snol10 ; No line 10 to do...
1439 dcba br0,r6 ; Allocate cache line 10
1442 la r9,savevr18(r3) ; Point to V18/V19 pair
1443 bf 16,snovr16 ; Do not save VR16...
1444 stvxl v16,br0,r8 ; Save VR16
1447 bf 17,snovr17 ; Do not save VR17...
1448 stvxl v17,r11,r8 ; Save VR17
1451 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1453 ; Note: All registers have been or are accounted for in CRs
1455 la r6,savevr24(r3) ; Point to line 12
1456 bf 7,snol11 ; No line 11 to do...
1457 dcba br0,r7 ; Allocate cache line 11
1460 la r8,savevr20(r3) ; Point to V20/V21 pair
1461 bf 18,snovr18 ; Do not save VR18...
1462 stvxl v18,br0,r9 ; Save VR18
1465 bf 19,snovr19 ; Do not save VR19...
1466 stvxl v19,r11,r9 ; Save VR19
1469 la r7,savevr26(r3) ; Point to line 13
1470 bf 9,snol12 ; No line 12 to do...
1471 dcba br0,r6 ; Allocate cache line 12
1474 la r9,savevr22(r3) ; Point to V22/V23 pair
1475 bf 20,snovr20 ; Do not save VR20...
1476 stvxl v20,br0,r8 ; Save VR20
1479 bf 21,snovr21 ; Do not save VR21...
1480 stvxl v21,r11,r8 ; Save VR21
1483 la r6,savevr28(r3) ; Point to line 14
1484 bf 11,snol13 ; No line 13 to do...
1485 dcba br0,r7 ; Allocate cache line 13
1488 la r8,savevr24(r3) ; Point to V24/V25 pair
1489 bf 22,snovr22 ; Do not save VR22...
1490 stvxl v22,br0,r9 ; Save VR22
1493 bf 23,snovr23 ; Do not save VR23...
1494 stvxl v23,r11,r9 ; Save VR23
1497 la r7,savevr30(r3) ; Point to line 15
1498 bf 13,snol14 ; No line 14 to do...
1499 dcba br0,r6 ; Allocate cache line 14
1502 la r9,savevr26(r3) ; Point to V26/V27 pair
1503 bf 24,snovr24 ; Do not save VR24...
1504 stvxl v24,br0,r8 ; Save VR24
1507 bf 25,snovr25 ; Do not save VR25...
1508 stvxl v25,r11,r8 ; Save VR25
1511 bf 15,snol15 ; No line 15 to do...
1512 dcba br0,r7 ; Allocate cache line 15
1516 ; Note: All cache lines allocated now
1518 la r8,savevr28(r3) ; Point to V28/V29 pair
1519 bf 26,snovr26 ; Do not save VR26...
1520 stvxl v26,br0,r9 ; Save VR26
1523 bf 27,snovr27 ; Do not save VR27...
1524 stvxl v27,r11,r9 ; Save VR27
1527 la r7,savevr30(r3) ; Point to V30/V31 pair
1528 bf 28,snovr28 ; Do not save VR28...
1529 stvxl v28,br0,r8 ; Save VR28
1532 bf 29,snovr29 ; Do not save VR29...
1533 stvxl v29,r11,r8 ; Save VR29
1536 mfvscr v27 ; Get the VSCR
1537 la r8,savevscr(r3) ; Point to the VSCR save area
1538 bf 30,snovr30 ; Do not save VR30...
1539 stvxl v30,br0,r7 ; Save VR30
1542 dcba br0,r8 ; Allocate VSCR savearea
1543 bf 31,snovr31 ; Do not save VR31...
1544 stvxl v31,r11,r7 ; Save VR31
1547 add r11,r11,r9 ; Point to V27s saved value
1548 stvxl v27,br0,r8 ; Save the VSCR
1549 bt 27,v27ok ; V27 has been saved and is marked as wanted
1551 lis r11,hi16(EXT(QNaNbarbarian)) ; V27 is not wanted, so get empty value
1552 ori r11,r11,lo16(EXT(QNaNbarbarian))
1554 v27ok: mtcrf 255,r2 ; Restore all non-volatile CRs
1555 lvxl v27,br0,r11 ; Restore or load empty value into V27 because we used it
1558 ; Save the current vector state into the savearea of the thread that owns it.
1561 vsret: lwz r4,ACT_MACT_VMXcpu(r12) ; Get back the owner CPU
1562 rlwinm r4,r4,0,fvChkb+1,31 ; Clear lock
1564 stw r4,ACT_MACT_VMXcpu(r12) ; Unlock the context
1566 vsretnr: mtmsr r0 ; Put interrupts on if they were and vector off
1574 * Entered to handle the vector unavailable exception and
1575 * switch vector context
1577 * This code is run with virtual address mode on and interrupts off.
1579 * Upon exit, the code returns to the users context with the vector
1580 * facility turned on.
1582 * ENTRY: VM switched ON
1584 * State is saved in savearea pointed to by R4.
1585 * All other registers are free.
1589 ENTRY(vec_switch, TAG_NO_FRAME_USED)
1593 mr r7,r4 ; Save input parameter
1594 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1595 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1597 lis r5,hi16(EXT(GratefulDeb)) ; Point to top of display
1598 ori r5,r5,lo16(EXT(GratefulDeb)) ; Put in bottom part
1600 mtlr r5 ; Set link register
1604 blrl ; Display count
1605 mr r4,r7 ; Restore the parameter
1607 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1608 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1615 mfsprg r6,0 /* Get the per_processor block */
1616 mfmsr r19 /* Get the current MSR */
1618 lwz r10,PP_CPU_DATA(r6) /* Get the CPU data pointer */
1619 lwz r12,PP_VMX_THREAD(r6) /* Get the thread that owns the vector */
1620 lwz r10,CPU_ACTIVE_THREAD(r10) /* Get the pointer to the active thread */
1621 oris r19,r19,hi16(MASK(MSR_VEC)) /* Enable the vector feature */
1622 lwz r17,THREAD_TOP_ACT(r10) /* Now get the activation that is running */
1624 ; R12 has the "old" activation
1625 ; R17 has the "new" activation
1628 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1629 li r2,0x5F01 ; (TEST/DEBUG)
1630 mr r3,r12 ; (TEST/DEBUG)
1631 mr r5,r17 ; (TEST/DEBUG)
1632 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1635 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1636 mr r18,r4 ; Save this
1637 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1638 mr r4,r2 ; Set value
1639 mtlr r3 ; Set link register
1640 li r3,1 ; Display address
1642 mr r4,r18 ; Restore it
1643 mfsprg r6,0 ; Get the per_processor block back
1646 mr. r12,r12 ; See if there is any live vector status
1648 lhz r18,PP_CPU_NUMBER(r6) ; Get our CPU number
1650 mtmsr r19 /* Set vector available */
1653 beq- vsnosave ; No live context, so nothing to save...
1655 li r20,ACT_MACT_VMXcpu ; Point to the CPU indication/lock word
1657 vsSpin1: lwarx r19,r20,r12 ; Get and reserve the last used CPU
1658 mr. r19,r19 ; Is it changing now?
1659 oris r21,r19,hi16(fvChk) ; Set the "changing" flag
1660 blt- vsSpin1 ; Spin if changing
1661 stwcx. r21,r20,r12 ; Lock it up
1662 bne- vsSpin1 ; Someone is messing right now
1664 isync ; Make sure we see everything
1666 lwz r15,ACT_MACT_PCB(r12) ; Get the current level of the "old" one
1667 cmplw r18,r19 ; Check the CPU that the old context is live on
1668 lwz r14,ACT_MACT_VMX(r12) ; Point to the top of the old context stack
1669 bne- vsnosaverel ; Context is not live if used on a different CPU...
1670 lwz r13,ACT_MACT_VMXlvl(r12) ; Get the "old" active level
1673 ; First, check to see if all we are doing is enabling because the
1674 ; "new" context is live.
1677 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1678 li r2,0x5F02 ; (TEST/DEBUG)
1679 mr r1,r15 ; (TEST/DEBUG)
1680 mr r3,r13 ; (TEST/DEBUG)
1681 mr r5,r14 ; (TEST/DEBUG)
1682 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1685 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1686 mr r8,r4 ; Save this
1687 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1688 mr r4,r2 ; Set value
1689 mtlr r3 ; Set link register
1690 li r3,1 ; Display address
1692 mr r4,r8 ; Restore it
1696 cmplw cr1,r12,r17 ; Is the "old" activation and the "new" the same?
1697 cmplwi cr2,r14,0 ; Is there any saved context on the "old" activation?
1698 bne+ cr1,vsmstsave ; The activations are different so "old" context must be saved...
1701 ; Here we know that both the "old" and "new" activations are the same. We will
1702 ; check the current level and active levels. If they are the same, the context is
1703 ; already live, so all we do is turn on the facility and invalidate the top
1706 ; If the current level, the active level, and the top savearea level are the
1707 ; same, then the context was saved as part of a thread context switch and neither
1708 ; needs saving or restoration.
1710 ; In all other cases, the context must be saved unless we are just re-enabling
1714 cmplw r13,r15 ; Are the levels the same?
1715 cmplwi cr2,r14,0 ; Is there any saved context?
1716 bne- vsmstsave ; Levels are different, we need to save...
1718 beq- cr2,vrenableret ; No saved context at all, enable and go...
1720 lwz r20,SAVlvlvec(r14) ; Get the level of the top savearea
1723 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1724 li r2,0x5F03 ; (TEST/DEBUG)
1725 mr r3,r15 ; (TEST/DEBUG)
1726 mr r5,r20 ; (TEST/DEBUG)
1727 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1730 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1731 mr r8,r4 ; Save this
1732 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1733 mr r4,r2 ; Set value
1734 mtlr r3 ; Set link register
1735 li r3,1 ; Display address
1737 mr r4,r8 ; Restore it
1740 cmplw r15,r20 ; Is the top level the same as the current?
1741 li r0,1 ; Get the invalid flag
1742 bne- vrenableret ; Not the same, just enable and go...
1744 stw r0,SAVlvlvec(r14) ; Invalidate that top savearea
1747 sync ; Make sure everything is saved
1748 stw r19,ACT_MACT_VMXcpu(r12) ; Say we are not using the context anymore
1749 b vrenable ; Then enable and go...
1752 ; We need to save the "old" context here. The LIFO queueing scheme works
1753 ; out for all cases because if both the "new" and "old" activations are the
1754 ; same, there can not be any saved state to load. the "new" level is
1757 ; When we save the context, we either use a new savearea, or the free
1758 ; one that is cached at the head of the list.
1760 vsmstsave: beq- cr2,vsgetsave ; There is no possible cached save area
1762 lwz r5,SAVlvlvec(r14) ; Get the level of first facility savearea
1764 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1765 li r2,0x5F04 ; (TEST/DEBUG)
1766 mr r3,r15 ; (TEST/DEBUG)
1767 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1770 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1771 mr r8,r4 ; Save this
1772 mr r7,r5 ; Save this
1773 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1774 mr r4,r2 ; Set value
1775 mtlr r3 ; Set link register
1776 li r3,1 ; Display address
1778 mr r4,r8 ; Restore it
1779 mr r5,r7 ; Restore it
1782 mr r3,r14 ; Assume we are invalid
1783 cmplwi r5,1 ; Is it invalid?
1784 cmplw cr1,r5,r13 ; Is the SA level the active one?
1785 beq+ vsusecache ; Invalid, just use it...
1786 beq- cr1,vsnosaverel ; The SA level is active, it is already saved...
1788 vsgetsave: mr r3,r4 ; Use the interrupt save as the context savearea if none cached
1790 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1791 li r2,0x5F05 ; (TEST/DEBUG)
1792 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1795 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1796 mr r8,r4 ; Save this
1797 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1798 mr r4,r2 ; Set value
1799 mtlr r3 ; Set link register
1800 li r3,1 ; Display address
1802 mr r4,r8 ; Restore it
1807 bl vsrchsave ; Find a free savearea
1809 stw r3,ACT_MACT_VMX(r12) ; Set this as the latest context savearea for the thread
1810 mfsprg r6,0 ; Get back per_processor block
1811 stw r14,SAVprevec(r3) ; And then chain this in front
1812 oris r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
1813 stw r12,SAVact(r3) ; Make sure we point to the right guy
1814 stw r7,SAVflags(r3) ; Set the allocation flags
1816 vsusecache: la r11,savevr0(r3) ; Point to the 1st line in area
1817 stw r13,SAVlvlvec(r3) ; Set this context level
1819 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1820 li r2,0x5F06 ; (TEST/DEBUG)
1821 mr r5,r13 ; (TEST/DEBUG)
1822 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1826 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1827 mr r8,r4 ; Save this
1828 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1829 mr r4,r2 ; Set value
1830 mtlr r3 ; Set link register
1831 li r3,1 ; Display address
1833 mr r4,r8 ; Restore it
1835 mfsprg r6,0 ; Get back per_processor block
1840 lwz r10,liveVRS(r6) ; Get the right VRSave register
1841 lis r9,0x5555 ; Mask with odd bits set
1842 rlwinm r11,r10,1,0,31 ; Shift over 1
1843 ori r9,r9,0x5555 ; Finish mask
1844 or r21,r10,r11 ; After this, even bits show which lines to zap
1846 stw r13,SAVlvlvec(r3) ; Set the savearea level
1847 andc r13,r21,r9 ; Clear out odd bits
1849 la r20,savevr0(r3) ; Point to line 0
1850 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1851 la r23,savevrvalid(r3) ; Point to the saved register mask field
1852 or r24,r13,r24 ; Set the odd bits
1853 ; (bit 0 is line 0, bit 1 is line 8,
1854 ; bit 2 is line 1, bit 3 is line 9, etc.
1855 dcba br0,r23 ; Allocate the cache for it
1856 rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1857 la r21,savevr2(r3) ; Point to line 1
1858 mtcrf 255,r24 ; Load up the CRs
1859 stw r10,savevrvalid(r3) ; Save the validity information
1860 mr r22,r20 ; Start registers off
1862 ; Save the current vector state
1865 bf 0,nol0 ; No line 0 to do...
1866 dcba br0,r20 ; Allocate cache line 0
1869 la r20,savevr4(r3) ; Point to line 2
1870 bf 2,nol1 ; No line 1 to do...
1871 dcba br0,r21 ; Allocate cache line 1
1874 la r21,savevr6(r3) ; Point to line 3
1875 bf 4,nol2 ; No line 2 to do...
1876 dcba br0,r20 ; Allocate cache line 2
1879 li r30,16 ; Get offset for odd registers
1880 bf 16,novr0 ; Do not save VR0...
1881 stvxl v0,br0,r22 ; Save VR0
1884 la r23,savevr2(r3) ; Point to V2/V3 pair
1885 bf 17,novr1 ; Do not save VR1...
1886 stvxl v1,r30,r22 ; Save VR1
1889 la r20,savevr8(r3) ; Point to line 4
1890 bf 6,nol3 ; No line 3 to do...
1891 dcba br0,r21 ; Allocate cache line 3
1894 la r22,savevr4(r3) ; Point to V4/V5 pair
1895 bf 18,novr2 ; Do not save VR2...
1896 stvxl v2,br0,r23 ; Save VR2
1899 bf 19,novr3 ; Do not save VR3...
1900 stvxl v3,r30,r23 ; Save VR3
1904 ; Note: CR4 is now free
1906 la r21,savevr10(r3) ; Point to line 5
1907 bf 8,nol4 ; No line 4 to do...
1908 dcba br0,r20 ; Allocate cache line 4
1911 la r23,savevr6(r3) ; Point to R6/R7 pair
1912 bf 20,novr4 ; Do not save VR4...
1913 stvxl v4,br0,r22 ; Save VR4
1916 bf 21,novr5 ; Do not save VR5...
1917 stvxl v5,r30,r22 ; Save VR5
1920 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1921 la r20,savevr12(r3) ; Point to line 6
1922 bf 10,nol5 ; No line 5 to do...
1923 dcba br0,r21 ; Allocate cache line 5
1926 la r22,savevr8(r3) ; Point to V8/V9 pair
1927 bf 22,novr6 ; Do not save VR6...
1928 stvxl v6,br0,r23 ; Save VR6
1931 bf 23,novr7 ; Do not save VR7...
1932 stvxl v7,r30,r23 ; Save VR7
1936 ; Note: CR5 is now free
1938 la r21,savevr14(r3) ; Point to line 7
1939 bf 12,nol6 ; No line 6 to do...
1940 dcba br0,r20 ; Allocate cache line 6
1943 la r23,savevr10(r3) ; Point to V10/V11 pair
1944 bf 24,novr8 ; Do not save VR8...
1945 stvxl v8,br0,r22 ; Save VR8
1948 bf 25,novr9 ; Do not save VR9...
1949 stvxl v9,r30,r22 ; Save VR9
1952 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1953 la r20,savevr16(r3) ; Point to line 8
1954 bf 14,nol7 ; No line 7 to do...
1955 dcba br0,r21 ; Allocate cache line 7
1958 la r22,savevr12(r3) ; Point to V12/V13 pair
1959 bf 26,novr10 ; Do not save VR10...
1960 stvxl v10,br0,r23 ; Save VR10
1963 bf 27,novr11 ; Do not save VR11...
1964 stvxl v11,r30,r23 ; Save VR11
1969 ; Note: CR6 is now free
1971 la r21,savevr18(r3) ; Point to line 9
1972 bf 1,nol8 ; No line 8 to do...
1973 dcba br0,r20 ; Allocate cache line 8
1976 la r23,savevr14(r3) ; Point to V14/V15 pair
1977 bf 28,novr12 ; Do not save VR12...
1978 stvxl v12,br0,r22 ; Save VR12
1981 bf 29,novr13 ; Do not save VR13...
1982 stvxl v13,r30,r22 ; Save VR13
1985 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1986 la r20,savevr20(r3) ; Point to line 10
1987 bf 3,nol9 ; No line 9 to do...
1988 dcba br0,r21 ; Allocate cache line 9
1991 la r22,savevr16(r3) ; Point to V16/V17 pair
1992 bf 30,novr14 ; Do not save VR14...
1993 stvxl v14,br0,r23 ; Save VR14
1996 bf 31,novr15 ; Do not save VR15...
1997 stvxl v15,r30,r23 ; Save VR15
2001 ; Note: CR7 is now free
2003 la r21,savevr22(r3) ; Point to line 11
2004 bf 5,nol10 ; No line 10 to do...
2005 dcba br0,r20 ; Allocate cache line 10
2008 la r23,savevr18(r3) ; Point to V18/V19 pair
2009 bf 16,novr16 ; Do not save VR16...
2010 stvxl v16,br0,r22 ; Save VR16
2013 bf 17,novr17 ; Do not save VR17...
2014 stvxl v17,r30,r22 ; Save VR17
2017 mtcrf 0x01,r10 ; Set CRs for registers 28-31
2019 ; Note: All registers have been or are accounted for in CRs
2021 la r20,savevr24(r3) ; Point to line 12
2022 bf 7,nol11 ; No line 11 to do...
2023 dcba br0,r21 ; Allocate cache line 11
2026 la r22,savevr20(r3) ; Point to V20/V21 pair
2027 bf 18,novr18 ; Do not save VR18...
2028 stvxl v18,br0,r23 ; Save VR18
2031 bf 19,novr19 ; Do not save VR19...
2032 stvxl v19,r30,r23 ; Save VR19
2035 la r21,savevr26(r3) ; Point to line 13
2036 bf 9,nol12 ; No line 12 to do...
2037 dcba br0,r20 ; Allocate cache line 12
2040 la r23,savevr22(r3) ; Point to V22/V23 pair
2041 bf 20,novr20 ; Do not save VR20...
2042 stvxl v20,br0,r22 ; Save VR20
2045 bf 21,novr21 ; Do not save VR21...
2046 stvxl v21,r30,r22 ; Save VR21
2049 la r20,savevr28(r3) ; Point to line 14
2050 bf 11,nol13 ; No line 13 to do...
2051 dcba br0,r21 ; Allocate cache line 13
2054 la r22,savevr24(r3) ; Point to V24/V25 pair
2055 bf 22,novr22 ; Do not save VR22...
2056 stvxl v22,br0,r23 ; Save VR22
2059 bf 23,novr23 ; Do not save VR23...
2060 stvxl v23,r30,r23 ; Save VR23
2063 la r21,savevr30(r3) ; Point to line 15
2064 bf 13,nol14 ; No line 14 to do...
2065 dcba br0,r20 ; Allocate cache line 14
2068 la r23,savevr26(r3) ; Point to V26/V27 pair
2069 bf 24,novr24 ; Do not save VR24...
2070 stvxl v24,br0,r22 ; Save VR24
2073 bf 25,novr25 ; Do not save VR25...
2074 stvxl v25,r30,r22 ; Save VR25
2077 bf 15,nol15 ; No line 15 to do...
2078 dcba br0,r21 ; Allocate cache line 15
2082 ; Note: All cache lines allocated now
2084 la r22,savevr28(r3) ; Point to V28/V29 pair
2085 bf 26,novr26 ; Do not save VR26...
2086 stvxl v26,br0,r23 ; Save VR26
2089 bf 27,novr27 ; Do not save VR27...
2090 stvxl v27,r30,r23 ; Save VR27
2093 la r23,savevr30(r3) ; Point to V30/V31 pair
2094 bf 28,novr28 ; Do not save VR28...
2095 stvxl v28,br0,r22 ; Save VR28
2098 mfvscr v27 ; Get the VSCR
2099 bf 29,novr29 ; Do not save VR29...
2100 stvxl v29,r30,r22 ; Save VR29
2103 la r22,savevscr(r3) ; Point to the VSCR save area
2104 bf 30,novr30 ; Do not save VR30...
2105 stvxl v30,br0,r23 ; Save VR30
2108 dcba br0,r22 ; Allocate VSCR savearea
2109 bf 31,novr31 ; Do not save VR31...
2110 stvxl v31,r30,r23 ; Save VR31
2113 stvxl v27,br0,r22 ; Save the VSCR
2118 * Now check out the current thread and see if we need to load up his context.
2119 * If we do (and this should be the normal case), do it and then release the
2122 * If we don't (remember, we already took care of the case where we just enable
2123 * the vector), we need to fill the registers with garbage, because this thread has
2124 * never used them before and some thieving bastard could hack the old values
2125 * of some thread! Just imagine what would happen if they could! Why, nothing
2126 * would be safe! My Gosh! It's terrifying!
2130 sync ; Make sure everything is saved
2131 stw r19,ACT_MACT_VMXcpu(r12) ; Say we are not using the context anymore
2135 li r20,ACT_MACT_VMXcpu ; Point to the CPU indication/lock word
2137 vsSpin2: lwarx r19,r20,r17 ; Get and reserve the last used CPU
2138 mr. r19,r19 ; Is it changing now?
2139 oris r21,r19,hi16(fvChk) ; Set the "changing" flag
2140 blt- vsSpin2 ; Spin if changing
2141 stwcx. r21,r20,r17 ; Lock it up
2142 bne- vsSpin2 ; Someone is messing right now
2144 isync ; Make sure we see everything
2146 lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
2147 lwz r14,ACT_MACT_VMX(r17) ; Point to the top of the "new" context stack
2148 lwz r13,ACT_MACT_VMXlvl(r17) ; Get the "new" active level
2151 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2152 li r2,0x5F07 ; (TEST/DEBUG)
2153 mr r1,r15 ; (TEST/DEBUG)
2154 mr r3,r14 ; (TEST/DEBUG)
2155 mr r5,r13 ; (TEST/DEBUG)
2156 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2160 cmplwi cr1,r14,0 ; Do we possibly have some context to load?
2161 stw r15,ACT_MACT_VMXlvl(r17) ; Set the "new" active level
2162 la r23,savevscr(r14) ; Point to the VSCR
2163 la r20,savevr0(r14) ; Point to first line to bring in
2164 stw r17,PP_VMX_THREAD(r6) ; Store current thread address in vmx_thread to claim vector for thread
2165 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
2166 lwz r0,SAVlvlvec(r14) ; Get the level of first facility savearea
2167 cmplw r0,r15 ; Top level correct to load?
2168 bne- ProtectTheAmericanWay ; No, go initialize...
2171 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2172 li r2,0x5F08 ; (TEST/DEBUG)
2173 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2177 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
2178 mr r22,r4 ; Save this
2179 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
2180 mr r4,r2 ; Set value
2181 mtlr r3 ; Set link register
2182 li r3,1 ; Display address
2184 mr r4,r22 ; Restore it
2189 li r0,1 ; Get the level invalid indication
2190 lwz r22,savevrsave(r4) ; Get the most current VRSAVE
2191 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
2192 lis r9,0x5555 ; Mask with odd bits set
2193 and r10,r10,r22 ; Figure out just what registers need to be loaded
2194 ori r9,r9,0x5555 ; Finish mask
2195 rlwinm r11,r10,1,0,31 ; Shift over 1
2196 stw r0,SAVlvlvec(r14) ; Mark the savearea invalid because we are activating again
2197 or r12,r10,r11 ; After this, even bits show which lines to touch
2198 dcbt br0,r23 ; Touch in the VSCR
2199 andc r13,r12,r9 ; Clear out odd bits
2201 la r20,savevr0(r14) ; Point to line 0
2202 rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
2203 la r21,savevr2(r3) ; Point to line 1
2204 or r3,r13,r3 ; Set the odd bits
2205 ; (bit 0 is line 0, bit 1 is line 8,
2206 ; bit 2 is line 1, bit 3 is line 9, etc.
2207 lvxl v31,br0,r23 ; Get the VSCR
2208 rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
2209 mtvscr v31 ; Slam the VSCR value
2210 mtcrf 255,r3 ; Load up the CRs
2211 mr r22,r20 ; Start registers off
2213 ; Load the new vector state
2216 bf 0,lnol0 ; No line 0 to do...
2217 dcbt br0,r20 ; Touch cache line 0
2220 la r20,savevr4(r14) ; Point to line 2
2221 bf 2,lnol1 ; No line 1 to do...
2222 dcbt br0,r21 ; Touch cache line 1
2225 la r21,savevr6(r14) ; Point to line 3
2226 bf 4,lnol2 ; No line 2 to do...
2227 dcbt br0,r20 ; Touch cache line 2
2230 li r30,16 ; Get offset for odd registers
2231 bf 16,lnovr0 ; Do not restore VR0...
2232 lvxl v0,br0,r22 ; Restore VR0
2235 la r23,savevr2(r14) ; Point to V2/V3 pair
2236 bf 17,lnovr1 ; Do not restore VR1...
2237 lvxl v1,r30,r22 ; Restore VR1
2240 la r20,savevr8(r14) ; Point to line 4
2241 bf 6,lnol3 ; No line 3 to do...
2242 dcbt br0,r21 ; Touch cache line 3
2245 la r22,savevr4(r14) ; Point to V4/V5 pair
2246 bf 18,lnovr2 ; Do not restore VR2...
2247 lvxl v2,br0,r23 ; Restore VR2
2250 bf 19,lnovr3 ; Do not restore VR3...
2251 lvxl v3,r30,r23 ; Restore VR3
2255 ; Note: CR4 is now free
2257 la r21,savevr10(r14) ; Point to line 5
2258 bf 8,lnol4 ; No line 4 to do...
2259 dcbt br0,r20 ; Touch cache line 4
2262 la r23,savevr6(r14) ; Point to R6/R7 pair
2263 bf 20,lnovr4 ; Do not restore VR4...
2264 lvxl v4,br0,r22 ; Restore VR4
2267 bf 21,lnovr5 ; Do not restore VR5...
2268 lvxl v5,r30,r22 ; Restore VR5
2271 mtcrf 0x08,r10 ; Set CRs for registers 16-19
2272 la r20,savevr12(r14) ; Point to line 6
2273 bf 10,lnol5 ; No line 5 to do...
2274 dcbt br0,r21 ; Touch cache line 5
2277 la r22,savevr8(r14) ; Point to V8/V9 pair
2278 bf 22,lnovr6 ; Do not restore VR6...
2279 lvxl v6,br0,r23 ; Restore VR6
2282 bf 23,lnovr7 ; Do not restore VR7...
2283 lvxl v7,r30,r23 ; Restore VR7
2287 ; Note: CR5 is now free
2289 la r21,savevr14(r14) ; Point to line 7
2290 bf 12,lnol6 ; No line 6 to do...
2291 dcbt br0,r20 ; Touch cache line 6
2294 la r23,savevr10(r14) ; Point to V10/V11 pair
2295 bf 24,lnovr8 ; Do not restore VR8...
2296 lvxl v8,br0,r22 ; Restore VR8
2299 bf 25,lnovr9 ; Do not save VR9...
2300 lvxl v9,r30,r22 ; Restore VR9
2303 mtcrf 0x04,r10 ; Set CRs for registers 20-23
2304 la r20,savevr16(r14) ; Point to line 8
2305 bf 14,lnol7 ; No line 7 to do...
2306 dcbt br0,r21 ; Touch cache line 7
2309 la r22,savevr12(r14) ; Point to V12/V13 pair
2310 bf 26,lnovr10 ; Do not restore VR10...
2311 lvxl v10,br0,r23 ; Restore VR10
2314 bf 27,lnovr11 ; Do not restore VR11...
2315 lvxl v11,r30,r23 ; Restore VR11
2320 ; Note: CR6 is now free
2322 la r21,savevr18(r14) ; Point to line 9
2323 bf 1,lnol8 ; No line 8 to do...
2324 dcbt br0,r20 ; Touch cache line 8
2327 la r23,savevr14(r14) ; Point to V14/V15 pair
2328 bf 28,lnovr12 ; Do not restore VR12...
2329 lvxl v12,br0,r22 ; Restore VR12
2332 bf 29,lnovr13 ; Do not restore VR13...
2333 lvxl v13,r30,r22 ; Restore VR13
2336 mtcrf 0x02,r10 ; Set CRs for registers 24-27
2337 la r20,savevr20(r14) ; Point to line 10
2338 bf 3,lnol9 ; No line 9 to do...
2339 dcbt br0,r21 ; Touch cache line 9
2342 la r22,savevr16(r14) ; Point to V16/V17 pair
2343 bf 30,lnovr14 ; Do not restore VR14...
2344 lvxl v14,br0,r23 ; Restore VR14
2347 bf 31,lnovr15 ; Do not restore VR15...
2348 lvxl v15,r30,r23 ; Restore VR15
2352 ; Note: CR7 is now free
2354 la r21,savevr22(r14) ; Point to line 11
2355 bf 5,lnol10 ; No line 10 to do...
2356 dcbt br0,r20 ; Touch cache line 10
2359 la r23,savevr18(r14) ; Point to V18/V19 pair
2360 bf 16,lnovr16 ; Do not restore VR16...
2361 lvxl v16,br0,r22 ; Restore VR16
2364 bf 17,lnovr17 ; Do not restore VR17...
2365 lvxl v17,r30,r22 ; Restore VR17
2368 mtcrf 0x01,r10 ; Set CRs for registers 28-31
2370 ; Note: All registers have been or are accounted for in CRs
2372 la r20,savevr24(r14) ; Point to line 12
2373 bf 7,lnol11 ; No line 11 to do...
2374 dcbt br0,r21 ; Touch cache line 11
2377 la r22,savevr20(r14) ; Point to V20/V21 pair
2378 bf 18,lnovr18 ; Do not restore VR18...
2379 lvxl v18,br0,r23 ; Restore VR18
2382 bf 19,lnovr19 ; Do not restore VR19...
2383 lvxl v19,r30,r23 ; Restore VR19
2386 la r21,savevr26(r14) ; Point to line 13
2387 bf 9,lnol12 ; No line 12 to do...
2388 dcbt br0,r20 ; Touch cache line 12
2391 la r23,savevr22(r14) ; Point to V22/V23 pair
2392 bf 20,lnovr20 ; Do not restore VR20...
2393 lvxl v20,br0,r22 ; Restore VR20
2396 bf 21,lnovr21 ; Do not restore VR21...
2397 lvxl v21,r30,r22 ; Restore VR21
2400 la r20,savevr28(r14) ; Point to line 14
2401 bf 11,lnol13 ; No line 13 to do...
2402 dcbt br0,r21 ; Touch cache line 13
2405 la r22,savevr24(r14) ; Point to V24/V25 pair
2406 bf 22,lnovr22 ; Do not restore VR22...
2407 lvxl v22,br0,r23 ; Restore VR22
2410 bf 23,lnovr23 ; Do not restore VR23...
2411 lvxl v23,r30,r23 ; Restore VR23
2414 la r21,savevr30(r14) ; Point to line 15
2415 bf 13,lnol14 ; No line 14 to do...
2416 dcbt br0,r20 ; Touch cache line 14
2419 la r23,savevr26(r14) ; Point to V26/V27 pair
2420 bf 24,lnovr24 ; Do not restore VR24...
2421 lvxl v24,br0,r22 ; Restore VR24
2424 bf 25,lnovr25 ; Do not restore VR25...
2425 lvxl v25,r30,r22 ; Restore VR25
2428 bf 15,lnol15 ; No line 15 to do...
2429 dcbt br0,r21 ; Touch cache line 15
2433 ; Note: All needed cache lines have been touched now
2435 la r22,savevr28(r14) ; Point to V28/V29 pair
2436 bf 26,lnovr26 ; Do not restore VR26...
2437 lvxl v26,br0,r23 ; Restore VR26
2440 bf 27,lnovr27 ; Do not restore VR27...
2441 lvxl v27,r30,r23 ; Restore VR27
2444 la r23,savevr30(r14) ; Point to V30/V31 pair
2445 bf 28,lnovr28 ; Do not restore VR28...
2446 lvxl v28,br0,r22 ; Restore VR28
2449 bf 29,lnovr29 ; Do not restore VR29...
2450 lvxl v29,r30,r22 ; Restore VR29
2453 bf 30,lnovr30 ; Do not restore VR30...
2454 lvxl v30,br0,r23 ; Restore VR30
2458 ; Everything is restored now except for VR31. We need it to get
2459 ; the QNaNBarbarian value to put into idle vector registers
2462 lis r5,hi16(EXT(QNaNbarbarian)) ; Get address of empty value
2463 cmpwi r10,-1 ; Handle the quick case of all registers in use
2464 ori r5,r5,lo16(EXT(QNaNbarbarian)) ; Get low address of empty value
2465 beq- mstlvr31 ; Not likely, but all are in use...
2466 mtcrf 255,r10 ; Get mask of valid registers
2467 lvxl v31,br0,r5 ; Initialize VR31 to the empty value
2469 bt 0,ni0 ; Register is ok already...
2470 vor v0,v31,v31 ; Copy into the next register
2472 bt 1,ni1 ; Register is ok already...
2473 vor v1,v31,v31 ; Copy into the next register
2475 bt 2,ni2 ; Register is ok already...
2476 vor v2,v31,v31 ; Copy into the next register
2478 bt 3,ni3 ; Register is ok already...
2479 vor v3,v31,v31 ; Copy into the next register
2481 bt 4,ni4 ; Register is ok already...
2482 vor v4,v31,v31 ; Copy into the next register
2484 bt 5,ni5 ; Register is ok already...
2485 vor v5,v31,v31 ; Copy into the next register
2487 bt 6,ni6 ; Register is ok already...
2488 vor v6,v31,v31 ; Copy into the next register
2490 bt 7,ni7 ; Register is ok already...
2491 vor v7,v31,v31 ; Copy into the next register
2493 bt 8,ni8 ; Register is ok already...
2494 vor v8,v31,v31 ; Copy into the next register
2496 bt 9,ni9 ; Register is ok already...
2497 vor v9,v31,v31 ; Copy into the next register
2499 bt 10,ni10 ; Register is ok already...
2500 vor v10,v31,v31 ; Copy into the next register
2502 bt 11,ni11 ; Register is ok already...
2503 vor v11,v31,v31 ; Copy into the next register
2505 bt 12,ni12 ; Register is ok already...
2506 vor v12,v31,v31 ; Copy into the next register
2508 bt 13,ni13 ; Register is ok already...
2509 vor v13,v31,v31 ; Copy into the next register
2511 bt 14,ni14 ; Register is ok already...
2512 vor v14,v31,v31 ; Copy into the next register
2514 bt 15,ni15 ; Register is ok already...
2515 vor v15,v31,v31 ; Copy into the next register
2517 bt 16,ni16 ; Register is ok already...
2518 vor v16,v31,v31 ; Copy into the next register
2520 bt 17,ni17 ; Register is ok already...
2521 vor v17,v31,v31 ; Copy into the next register
2523 bt 18,ni18 ; Register is ok already...
2524 vor v18,v31,v31 ; Copy into the next register
2526 bt 19,ni19 ; Register is ok already...
2527 vor v19,v31,v31 ; Copy into the next register
2529 bt 20,ni20 ; Register is ok already...
2530 vor v20,v31,v31 ; Copy into the next register
2532 bt 21,ni21 ; Register is ok already...
2533 vor v21,v31,v31 ; Copy into the next register
2535 bt 22,ni22 ; Register is ok already...
2536 vor v22,v31,v31 ; Copy into the next register
2538 bt 23,ni23 ; Register is ok already...
2539 vor v23,v31,v31 ; Copy into the next register
2541 bt 24,ni24 ; Register is ok already...
2542 vor v24,v31,v31 ; Copy into the next register
2544 bt 25,ni25 ; Register is ok already...
2545 vor v25,v31,v31 ; Copy into the next register
2547 bt 26,ni26 ; Register is ok already...
2548 vor v26,v31,v31 ; Copy into the next register
2550 bt 27,ni27 ; Register is ok already...
2551 vor v27,v31,v31 ; Copy into the next register
2553 bt 28,ni28 ; Register is ok already...
2554 vor v28,v31,v31 ; Copy into the next register
2556 bt 29,ni29 ; Register is ok already...
2557 vor v29,v31,v31 ; Copy into the next register
2559 bt 30,ni30 ; Register is ok already...
2560 vor v30,v31,v31 ; Copy into the next register
2562 bf 31,lnovr31 ; R31 is empty, no need to restore...
2564 mstlvr31: lvxl v31,r30,r23 ; Restore VR31
2568 vrenablexx: sync ; Make sure all is saved
2569 stw r18,ACT_MACT_VMXcpu(r17) ; Set the active CPU and release
2572 lwz r9,SAVflags(r4) /* Get the flags of the current savearea */
2573 lwz r8,savesrr1(r4) ; Get the msr of the interrupted guy
2574 rlwinm r5,r4,0,0,19 /* Get the page address of the savearea */
2575 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
2576 lwz r10,ACT_MACT_SPF(r17) ; Get the special flags
2577 lis r7,hi16(SAVattach) /* Get the attached flag */
2578 lwz r5,SACvrswap(r5) /* Get Virtual to Real translation */
2579 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2580 mr. r15,r15 ; See if we are doing this for user state
2581 stw r8,savesrr1(r4) ; Set the msr of the interrupted guy
2582 andc r9,r9,r7 /* Clear the attached bit */
2583 xor r3,r4,r5 /* Get the real address of the savearea */
2584 stw r9,SAVflags(r4) /* Set the flags of the current savearea */
2585 bne- vrnuser ; We are not user state...
2586 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
2587 stw r10,spcFlags(r6) ; Set per_proc copy
2591 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2592 li r2,0x5F0A ; (TEST/DEBUG)
2593 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2596 mr r8,r3 ; Save this
2597 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
2598 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
2599 mr r4,r2 ; Set value
2600 mtlr r3 ; Set link register
2601 li r3,1 ; Display address
2603 mr r3,r8 ; Restore it
2606 b EXT(exception_exit) /* Exit from the fray... */
2609 * Initialize the registers to some bogus value
2610 * We make sure that non-Java mode is the default here
2613 ProtectTheAmericanWay:
2616 lwz r10,savesrr1(r4) ; (TEST/DEBUG)
2617 rlwinm. r10,r10,0,MSR_PR_BIT,MSR_PR_BIT ; (TEST/DEBUG)
2618 beq- nxxxxxx2 ; (TEST/DEBUG)
2619 lwz r10,ACT_MACT_SPF(r17) ; (TEST/DEBUG)
2620 rlwinm. r10,r10,0,2,2 ; (TEST/DEBUG)
2622 BREAKPOINT_TRAP ; (TEST/DEBUG)
2626 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2627 li r2,0x5F09 ; (TEST/DEBUG)
2628 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2631 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
2632 mr r8,r4 ; Save this
2633 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
2634 mr r4,r2 ; Set value
2635 mtlr r3 ; Set link register
2636 li r3,1 ; Display address
2638 mr r4,r8 ; Restore it
2641 lis r5,hi16(EXT(QNaNbarbarian)) ; Get address of empty value
2642 vspltish v1,1 ; Turn on the non-Java bit and saturate
2643 ori r5,r5,lo16(EXT(QNaNbarbarian)) ; Get low address of empty value
2644 vspltisw v2,1 ; Turn on the saturate bit
2645 lvxl v0,br0,r5 ; Initialize VR0
2646 vxor v1,v1,v2 ; Turn off saturate
2648 vor v2,v0,v0 ; Copy into the next register
2649 mtvscr v1 ; Clear the vector status register
2650 vor v3,v0,v0 ; Copy into the next register
2651 vor v1,v0,v0 ; Copy into the next register
2652 vor v4,v0,v0 ; Copy into the next register
2653 vor v5,v0,v0 ; Copy into the next register
2654 vor v6,v0,v0 ; Copy into the next register
2655 vor v7,v0,v0 ; Copy into the next register
2656 vor v8,v0,v0 ; Copy into the next register
2657 vor v9,v0,v0 ; Copy into the next register
2658 vor v10,v0,v0 ; Copy into the next register
2659 vor v11,v0,v0 ; Copy into the next register
2660 vor v12,v0,v0 ; Copy into the next register
2661 vor v13,v0,v0 ; Copy into the next register
2662 vor v14,v0,v0 ; Copy into the next register
2663 vor v15,v0,v0 ; Copy into the next register
2664 vor v16,v0,v0 ; Copy into the next register
2665 vor v17,v0,v0 ; Copy into the next register
2666 vor v18,v0,v0 ; Copy into the next register
2667 vor v19,v0,v0 ; Copy into the next register
2668 vor v20,v0,v0 ; Copy into the next register
2669 vor v21,v0,v0 ; Copy into the next register
2670 vor v22,v0,v0 ; Copy into the next register
2671 vor v23,v0,v0 ; Copy into the next register
2672 vor v24,v0,v0 ; Copy into the next register
2673 vor v25,v0,v0 ; Copy into the next register
2674 vor v26,v0,v0 ; Copy into the next register
2675 vor v27,v0,v0 ; Copy into the next register
2676 vor v28,v0,v0 ; Copy into the next register
2677 vor v29,v0,v0 ; Copy into the next register
2678 vor v30,v0,v0 ; Copy into the next register
2679 vor v31,v0,v0 ; Copy into the next register
2680 b vrenablexx ; Finish setting it all up...
2683 ; Finds a unused vector area in the activation pointed
2684 ; to by R12s saved contexts. If none are found (unlikely but possible)
2685 ; and R3 is 0, a new area is allocated. If R3 is non-zero, it contains
2686 ; a pointer to a vector savearea that is free.
2689 vsrchsave: lwz r6,ACT_MACT_PCB(r12) ; Get the first "normal" savearea
2691 vsrnorm: mr. r5,r6 ; Is there another?
2692 beq- vsrvect ; No, search the floating point saveareas...
2693 lwz r7,SAVflags(r5) ; Get the flags for this guy
2694 lwz r6,SAVprev(r5) ; Get the previous savearea, just in case
2695 andis. r8,r7,hi16(SAVvmxvalid) ; Have we found an empty vector save in normal?
2696 beq+ vsrgot ; We found one...
2697 b vsrnorm ; Search again...
2699 vsrvect: lwz r6,ACT_MACT_FPU(r12) ; Get the first "floating point" savearea
2701 vsrvectx: mr. r5,r6 ; Is there another?
2702 beq- vsrget ; No, try to allocate one...
2703 lwz r7,SAVflags(r5) ; Get the flags for this guy
2704 lwz r6,SAVprefp(r5) ; Get the previous savearea, just in case
2705 andis. r8,r7,hi16(SAVvmxvalid) ; Have we found an empty vector save in float?
2706 bne- vsrvectx ; Search again...
2708 vsrgot: mr r3,r5 ; Get the savearea into the right register
2711 vsrget: mr. r5,r3 ; Do we allocate or use existing?
2712 beq+ vsrallo ; Allocate one...
2714 lwz r7,SAVflags(r3) ; Get the passed in area flags
2717 ; NOTE: save_get will return directly and set R7 to 0...
2719 vsrallo: b EXT(save_get) ; Get a fresh savearea
2723 * void lfs(fpsp,fpdp)
2725 * load the single precision float to the double
2727 * This routine is used by the alignment handler.
2730 ENTRY(lfs, TAG_NO_FRAME_USED)
2736 * fpsp stfs(fpdp,fpsp)
2738 * store the double precision float to the single
2740 * This routine is used by the alignment handler.
2743 ENTRY(stfs, TAG_NO_FRAME_USED)