]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/cswtch.s
cc81fc49ef4295aa3144edc5390c4b7e9328ee38
[apple/xnu.git] / osfmk / ppc / cswtch.s
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * @OSF_COPYRIGHT@
27 */
28
29 #include <ppc/asm.h>
30 #include <ppc/proc_reg.h>
31 #include <cpus.h>
32 #include <assym.s>
33 #include <debug.h>
34 #include <mach/ppc/vm_param.h>
35 #include <ppc/exception.h>
36 #include <ppc/savearea.h>
37
38 #define FPVECDBG 0
39 #define GDDBG 0
40
41 .text
42
43 /*
44 * void load_context(thread_t thread)
45 *
46 * Load the context for the first kernel thread, and go.
47 *
48 * NOTE - if DEBUG is set, the former routine is a piece
49 * of C capable of printing out debug info before calling the latter,
50 * otherwise both entry points are identical.
51 */
52
53 .align 5
54 .globl EXT(load_context)
55
56 LEXT(load_context)
57
58 .globl EXT(Load_context)
59
60 LEXT(Load_context)
61
62 /*
63 * Since this is the first thread, we came in on the interrupt
64 * stack. The first thread never returns, so there is no need to
65 e worry about saving its frame, hence we can reset the istackptr
66 * back to the saved_state structure at it's top
67 */
68
69
70 /*
71 * get new thread pointer and set it into the active_threads pointer
72 *
73 */
74
75 mfsprg r6,0
76 lwz r0,PP_INTSTACK_TOP_SS(r6)
77 stw r0,PP_ISTACKPTR(r6)
78 stw r3,PP_ACTIVE_THREAD(r6)
79
80 /* Find the new stack and store it in active_stacks */
81
82 lwz r12,PP_ACTIVE_STACKS(r6)
83 lwz r1,THREAD_KERNEL_STACK(r3)
84 lwz r9,THREAD_TOP_ACT(r3) /* Point to the active activation */
85 mtsprg 1,r9
86 stw r1,0(r12)
87 li r0,0 /* Clear a register */
88 lwz r8,ACT_MACT_PCB(r9) /* Get the savearea used */
89 rlwinm r7,r8,0,0,19 /* Switch to savearea base */
90 lwz r11,SAVprev(r8) /* Get the previous savearea */
91 mfmsr r5 /* Since we are passing control, get our MSR values */
92 lwz r1,saver1(r8) /* Load new stack pointer */
93 stw r0,saver3(r8) /* Make sure we pass in a 0 for the continuation */
94 lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */
95 stw r0,FM_BACKPTR(r1) /* zero backptr */
96 stw r5,savesrr1(r8) /* Pass our MSR to the new guy */
97 xor r3,r7,r8 /* Get the physical address of the new context save area */
98 stw r11,ACT_MACT_PCB(r9) /* Unstack our savearea */
99 b EXT(exception_exit) /* Go end it all... */
100
101 /* struct thread_shuttle *Switch_context(struct thread_shuttle *old,
102 * void (*cont)(void),
103 * struct thread_shuttle *new)
104 *
105 * Switch from one thread to another. If a continuation is supplied, then
106 * we do not need to save callee save registers.
107 *
108 */
109
110 /* void Call_continuation( void (*continuation)(void), vm_offset_t stack_ptr)
111 */
112
113 .align 5
114 .globl EXT(Call_continuation)
115
116 LEXT(Call_continuation)
117
118 mtlr r3
119 mr r1, r4 /* Load new stack pointer */
120 blr /* Jump to the continuation */
121
122 /*
123 * Get the old kernel stack, and store into the thread structure.
124 * See if a continuation is supplied, and skip state save if so.
125 * NB. Continuations are no longer used, so this test is omitted,
126 * as should the second argument, but it is in generic code.
127 * We always save state. This does not hurt even if continuations
128 * are put back in.
129 */
130
131 /* Context switches are double jumps. We pass the following to the
132 * context switch firmware call:
133 *
134 * R3 = switchee's savearea
135 * R4 = old thread
136 * R5 = new SRR0
137 * R6 = new SRR1
138 *
139 * savesrr0 is set to go to switch_in
140 * savesrr1 is set to uninterruptible with translation on
141 */
142
143
144 .align 5
145 .globl EXT(Switch_context)
146
147 LEXT(Switch_context)
148
149 mfsprg r12,0 ; Get the per_proc block
150 lwz r10,PP_ACTIVE_STACKS(r12) ; Get the pointer to the current stack
151 #if DEBUG
152 lwz r11,PP_ISTACKPTR(r12) ; (DEBUG/TRACE) make sure we are not
153 mr. r11,r11 ; (DEBUG/TRACE) on the interrupt
154 bne+ notonintstack ; (DEBUG/TRACE) stack
155 BREAKPOINT_TRAP
156 notonintstack:
157 #endif
158 stw r4,THREAD_CONTINUATION(r3) ; Set continuation into the thread
159 cmpwi cr1,r4,0 ; used waaaay down below
160 lwz r7,0(r10) ; Get the current stack
161 /*
162 * Make the new thread the current thread.
163 */
164
165 stw r7,THREAD_KERNEL_STACK(r3) ; Remember the current stack in the thread (do not need???)
166 stw r5, PP_ACTIVE_THREAD(r12) ; Make the new thread current
167
168 lwz r11,THREAD_KERNEL_STACK(r5) ; Get the new stack pointer
169
170 lwz r5,THREAD_TOP_ACT(r5) ; Get the new activation
171 mtsprg 1,r5
172 lwz r7,CTHREAD_SELF(r5) ; Pick up the user assist word
173 lwz r8,ACT_MACT_PCB(r5) ; Get the PCB for the new guy
174
175 #if 0
176 lwz r0,SAVflags(r8) ; (TEST/DEBUG)
177 rlwinm r0,r0,24,24,31 ; (TEST/DEBUG)
178 cmplwi r0,SAVempty ; (TEST/DEBUG)
179 bne+ nnnn ; (TEST/DEBUG)
180 b . ; (TEST/DEBUG)
181 nnnn: ; (TEST/DEBUG)
182 #endif
183
184 stw r11,0(r10) ; Save the new kernel stack address
185 stw r7,UAW(r12) ; Save the assist word for the "ultra fast path"
186
187 lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment
188
189 lwz r7,ACT_MACT_SPF(r5) ; Get the special flags
190
191 lwz r10,ACT_KLOADED(r5)
192 stw r11,ppbbTaskEnv(r12) ; Save the bb task env
193 li r0,0
194 cmpwi cr0,r10,0
195 lwz r10,PP_ACTIVE_KLOADED(r12)
196 stw r7,spcFlags(r12) ; Set per_proc copy of the special flags
197 beq cr0,.L_sw_ctx_not_kld
198
199 stw r5,0(r10)
200 b .L_sw_ctx_cont
201
202 .L_sw_ctx_not_kld:
203 stw r0,0(r10) /* act_kloaded = 0 */
204
205 .L_sw_ctx_cont:
206 lis r10,hi16(EXT(trcWork)) ; Get top of trace mask
207 rlwinm r7,r8,0,0,19 /* Switch to savearea base */
208 ori r10,r10,lo16(EXT(trcWork)) ; Get bottom of mask
209 lwz r11,SAVprev(r8) /* Get the previous of the switchee's savearea */
210 lwz r10,traceMask(r10) ; Get the enabled traces
211 lis r0,hi16(CutTrace) ; Trace FW call
212 mr. r10,r10 ; Any tracing going on?
213 ori r0,r0,lo16(CutTrace) ; Trace FW call
214 beq+ cswNoTrc ; No trace today, dude...
215 mr r10,r3 ; Save across trace
216 lwz r2,THREAD_TOP_ACT(r3) ; Trace old activation
217 mr r3,r11 ; Trace prev savearea
218 sc ; Cut trace entry of context switch
219 mr r3,r10 ; Restore
220
221 cswNoTrc: mfmsr r6 /* Get the MSR because the switched to thread should inherit it */
222 lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */
223 stw r11,ACT_MACT_PCB(r5) /* Dequeue the savearea we're switching to */
224
225 rlwinm r6,r6,0,MSR_FP_BIT+1,MSR_FP_BIT-1 /* Turn off the FP */
226 lwz r2,curctx(r5) ; Grab our current context pointer
227 rlwinm r6,r6,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 /* Turn off the vector */
228 mr r4,r3 /* Save our old thread to pass back */
229
230 lhz r0,PP_CPU_NUMBER(r12) ; Get our CPU number
231 lwz r10,FPUowner(r12) ; Grab the owner of the FPU
232 lwz r9,VMXowner(r12) ; Grab the owner of the vector
233 cmplw r10,r2 ; Do we have the live float context?
234 lwz r10,FPUlevel(r2) ; Get the live level
235 cmplw cr5,r9,r2 ; Do we have the live vector context?
236 bne+ cswnofloat ; Float is not ours...
237
238 cmplw r10,r11 ; Is the level the same?
239 lwz r5,FPUcpu(r2) ; Get the owning cpu
240 bne+ cswnofloat ; Level not the same, this is not live...
241
242 cmplw r5,r0 ; Still owned by this cpu?
243 lwz r10,FPUsave(r2) ; Get the level
244 bne+ cswnofloat ; CPU claimed by someone else...
245
246 mr. r10,r10 ; Is there a savearea here?
247 ori r6,r6,lo16(MASK(MSR_FP)) ; Enable floating point
248
249 beq- cswnofloat ; No savearea to check...
250
251 lwz r3,SAVlevel(r10) ; Get the level
252 lwz r5,SAVprev(r10) ; Get the previous of this savearea
253 cmplw r3,r11 ; Is it for the current level?
254
255 bne+ cswnofloat ; Nope...
256
257 stw r5,FPUsave(r2) ; Pop off this savearea
258 rlwinm r5,r10,0,0,19 ; Move back to start of page
259 lwz r5,SACvrswap(r5) ; Get the virtual to real conversion
260 la r9,quickfret(r12) ; Point to the quickfret chain header
261 xor r5,r10,r5 ; Convert savearea address to real
262
263 #if FPVECDBG
264 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
265 li r2,0x4401 ; (TEST/DEBUG)
266 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
267 sc ; (TEST/DEBUG)
268 lhz r0,PP_CPU_NUMBER(r12) ; (TEST/DEBUG)
269 #endif
270
271 ;
272 ; Note: we need to do the atomic operation here because, even though
273 ; it is impossible with the current implementation, that we may take a
274 ; PTE miss between the load of the quickfret anchor and the subsequent
275 ; store. The interrupt handler will dequeue everything on the list and
276 ; we could end up using stale data. I do not like doing this...
277 ;
278
279 cswfpudq: lwarx r3,0,r9 ; Pick up the old chain head
280 stw r3,SAVprev(r10) ; Move it to the current guy
281 stwcx. r5,0,r9 ; Save it
282 bne- cswfpudq ; Someone chaged the list...
283
284 cswnofloat: bne+ cr5,cswnovect ; Vector is not ours...
285
286 lwz r10,VMXlevel(r2) ; Get the live level
287
288 cmplw r10,r11 ; Is the level the same?
289 lwz r5,VMXcpu(r2) ; Get the owning cpu
290 bne+ cswnovect ; Level not the same, this is not live...
291
292 cmplw r5,r0 ; Still owned by this cpu?
293 lwz r10,VMXsave(r2) ; Get the level
294 bne+ cswnovect ; CPU claimed by someone else...
295
296 mr. r10,r10 ; Is there a savearea here?
297 oris r6,r6,hi16(MASK(MSR_VEC)) ; Enable vector
298
299 beq- cswnovect ; No savearea to check...
300
301 lwz r3,SAVlevel(r10) ; Get the level
302 lwz r5,SAVprev(r10) ; Get the previous of this savearea
303 cmplw r3,r11 ; Is it for the current level?
304
305 bne+ cswnovect ; Nope...
306
307 stw r5,VMXsave(r2) ; Pop off this savearea
308 rlwinm r5,r10,0,0,19 ; Move back to start of page
309 lwz r5,SACvrswap(r5) ; Get the virtual to real conversion
310 la r9,quickfret(r12) ; Point to the quickfret chain header
311 xor r5,r10,r5 ; Convert savearea address to real
312
313 #if FPVECDBG
314 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
315 li r2,0x4501 ; (TEST/DEBUG)
316 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
317 sc ; (TEST/DEBUG)
318 #endif
319
320 ;
321 ; Note: we need to do the atomic operation here because, even though
322 ; it is impossible with the current implementation, that we may take a
323 ; PTE miss between the load of the quickfret anchor and the subsequent
324 ; store. The interrupt handler will dequeue everything on the list and
325 ; we could end up using stale data. I do not like doing this...
326 ;
327
328 cswvecdq: lwarx r3,0,r9 ; Pick up the old chain head
329 stw r3,SAVprev(r10) ; Move it to the current guy
330 stwcx. r5,0,r9 ; Save it
331 bne- cswvecdq ; Someone chaged the list...
332
333 cswnovect: lis r9,hi16(EXT(switch_in)) /* Get top of switch in routine */
334 lwz r5,savesrr0(r8) /* Set up the new SRR0 */
335 ori r9,r9,lo16(EXT(switch_in)) /* Bottom half of switch in */
336 lis r0,hi16(SwitchContextCall) /* Top part of switch context */
337 stw r9,savesrr0(r8) /* Make us jump to the switch in routine */
338
339 li r10,MSR_SUPERVISOR_INT_OFF /* Get the switcher's MSR */
340 lwz r9,SAVflags(r8) /* Get the flags */
341 stw r10,savesrr1(r8) /* Set up for switch in */
342 rlwinm r9,r9,0,15,13 /* Reset the syscall flag */
343 ori r0,r0,lo16(SwitchContextCall) /* Bottom part of switch context */
344 xor r3,r7,r8 /* Get the physical address of the new context save area */
345 stw r9,SAVflags(r8) /* Set the flags */
346
347 bne cr1,swtchtocont ; Switch to the continuation
348 sc /* Switch to the new context */
349
350 /* We come back here in the new thread context
351 * R4 was set to hold the old thread pointer, but switch_in will put it into
352 * R3 where it belongs.
353 */
354 blr /* Jump into the new thread */
355
356 ;
357 ; This is where we go when a continuation is set. We are actually
358 ; killing off the old context of the new guy so we need to pop off
359 ; any float or vector states for the ditched level.
360 ;
361 ; Note that we do the same kind of thing a chkfac in hw_exceptions.s
362 ;
363
364
365 swtchtocont:
366 stw r5,savesrr0(r8) ; Set the pc
367 stw r6,savesrr1(r8) ; Set the next MSR to use
368 stw r4,saver3(r8) ; Make sure we pass back the old thread
369
370 b EXT(exception_exit) ; Blocking on continuation, toss old context...
371
372
373
374 /*
375 * All switched to threads come here first to clean up the old thread.
376 * We need to do the following contortions because we need to keep
377 * the LR clean. And because we need to manipulate the savearea chain
378 * with translation on. If we could, this should be done in lowmem_vectors
379 * before translation is turned on. But we can't, dang it!
380 *
381 * R3 = switcher's savearea
382 * saver4 = old thread in switcher's save
383 * saver5 = new SRR0 in switcher's save
384 * saver6 = new SRR1 in switcher's save
385
386
387 */
388
389
390 .align 5
391 .globl EXT(switch_in)
392
393 LEXT(switch_in)
394
395 lwz r4,saver4(r3) /* Get the old thread */
396 lwz r9,THREAD_TOP_ACT(r4) /* Get the switched from ACT */
397 lwz r5,saver5(r3) /* Get the srr0 value */
398 lwz r10,ACT_MACT_PCB(r9) /* Get the top PCB on the old thread */
399 lwz r6,saver6(r3) /* Get the srr1 value */
400
401 stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */
402 stw r10,SAVprev(r3) /* Chain on the old one */
403
404 mr r3,r4 /* Pass back the old thread */
405
406 mtsrr0 r5 /* Set return point */
407 mtsrr1 r6 /* Set return MSR */
408 rfi /* Jam... */
409 .long 0
410 .long 0
411 .long 0
412 .long 0
413 .long 0
414 .long 0
415 .long 0
416 .long 0
417
418
419
420 /*
421 * void fpu_save(facility_context ctx)
422 *
423 * Note that there are some oddities here when we save a context we are using.
424 * It is really not too cool to do this, but what the hey... Anyway,
425 * we turn fpus and vecs off before we leave., The oddity is that if you use fpus after this, the
426 * savearea containing the context just saved will go away. So, bottom line is
427 * that don't use fpus until after you are done with the saved context.
428 */
429 .align 5
430 .globl EXT(fpu_save)
431
432 LEXT(fpu_save)
433
434
435 mfmsr r0 ; Get the MSR
436 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
437 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
438 ori r2,r2,MASK(MSR_FP) ; Enable the floating point feature for now also
439 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
440 mtmsr r2 ; Set the MSR
441 isync
442
443 mfsprg r6,0 ; Get the per_processor block
444 lwz r12,FPUowner(r6) ; Get the context ID for owner
445
446 #if FPVECDBG
447 mr r7,r0 ; (TEST/DEBUG)
448 li r4,0 ; (TEST/DEBUG)
449 mr r10,r3 ; (TEST/DEBUG)
450 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
451 mr. r3,r12 ; (TEST/DEBUG)
452 li r2,0x6F00 ; (TEST/DEBUG)
453 li r5,0 ; (TEST/DEBUG)
454 beq- noowneryet ; (TEST/DEBUG)
455 lwz r4,FPUlevel(r12) ; (TEST/DEBUG)
456 lwz r5,FPUsave(r12) ; (TEST/DEBUG)
457
458 noowneryet: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
459 sc ; (TEST/DEBUG)
460 mr r0,r7 ; (TEST/DEBUG)
461 mr r3,r10 ; (TEST/DEBUG)
462 #endif
463 mflr r2 ; Save the return address
464
465 fsretry: mr. r12,r12 ; Anyone own the FPU?
466 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
467 beq- fsret ; Nobody owns the FPU, no save required...
468
469 cmplw cr1,r3,r12 ; Is the specified context live?
470
471 isync ; Force owner check first
472
473 lwz r9,FPUcpu(r12) ; Get the cpu that context was last on
474 bne- cr1,fsret ; No, it is not...
475
476 cmplw cr1,r9,r11 ; Was the context for this processor?
477 beq- cr1,fsgoodcpu ; Facility last used on this processor...
478
479 b fsret ; Someone else claimed it...
480
481 .align 5
482
483 fsgoodcpu: lwz r3,FPUsave(r12) ; Get the current FPU savearea for the thread
484 lwz r9,FPUlevel(r12) ; Get our current level indicator
485
486 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
487 beq- cr1,fsneedone ; Never saved it, so go do it...
488
489 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
490 cmplw cr1,r9,r8 ; Correct level?
491 beq- cr1,fsret ; The current level is already saved, bail out...
492
493 fsneedone: bl EXT(save_get) ; Get a savearea for the context
494
495 mfsprg r6,0 ; Get back per_processor block
496 li r4,SAVfloat ; Get floating point tag
497 lwz r12,FPUowner(r6) ; Get back our thread
498 stb r4,SAVflags+2(r3) ; Mark this savearea as a float
499 mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it...
500 beq- fsbackout ; If disowned, just toss savearea...
501 lwz r4,facAct(r12) ; Get the activation associated with live context
502 mtlr r2 ; Restore return
503 lwz r8,FPUsave(r12) ; Get the current top floating point savearea
504 stw r4,SAVact(r3) ; Indicate the right activation for this context
505 lwz r9,FPUlevel(r12) ; Get our current level indicator again
506 stw r3,FPUsave(r12) ; Set this as the most current floating point context
507 stw r8,SAVprev(r3) ; And then chain this in front
508
509 stw r9,SAVlevel(r3) ; Show level in savearea
510
511 ;
512 ; Save the current FPU state into the PCB of the thread that owns it.
513 ;
514
515 la r11,savefp0(r3) ; Point to the 1st line
516 dcbz 0,r11 ; Allocate the first savearea line
517
518 la r11,savefp4(r3) ; Point to the 2nd line
519 stfd f0,savefp0(r3)
520 dcbz 0,r11 ; Allocate it
521 stfd f1,savefp1(r3)
522 stfd f2,savefp2(r3)
523 la r11,savefp8(r3) ; Point to the 3rd line
524 stfd f3,savefp3(r3)
525 dcbz 0,r11 ; Allocate it
526 stfd f4,savefp4(r3)
527 stfd f5,savefp5(r3)
528 stfd f6,savefp6(r3)
529 la r11,savefp12(r3) ; Point to the 4th line
530 stfd f7,savefp7(r3)
531 dcbz 0,r11 ; Allocate it
532 stfd f8,savefp8(r3)
533 stfd f9,savefp9(r3)
534 stfd f10,savefp10(r3)
535 la r11,savefp16(r3) ; Point to the 5th line
536 stfd f11,savefp11(r3)
537 dcbz 0,r11 ; Allocate it
538 stfd f12,savefp12(r3)
539 stfd f13,savefp13(r3)
540 stfd f14,savefp14(r3)
541 la r11,savefp20(r3) ; Point to the 6th line
542 stfd f15,savefp15(r3)
543 stfd f16,savefp16(r3)
544 stfd f17,savefp17(r3)
545 stfd f18,savefp18(r3)
546 la r11,savefp24(r3) ; Point to the 7th line
547 stfd f19,savefp19(r3)
548 dcbz 0,r11 ; Allocate it
549 stfd f20,savefp20(r3)
550 stfd f21,savefp21(r3)
551 stfd f22,savefp22(r3)
552 la r11,savefp28(r3) ; Point to the 8th line
553 stfd f23,savefp23(r3)
554 dcbz 0,r11 ; Allocate it
555 stfd f24,savefp24(r3)
556 stfd f25,savefp25(r3)
557 stfd f26,savefp26(r3)
558 stfd f27,savefp27(r3)
559 stfd f28,savefp28(r3)
560
561 stfd f29,savefp29(r3)
562 stfd f30,savefp30(r3)
563 stfd f31,savefp31(r3)
564
565 fsret: mtmsr r0 ; Put interrupts on if they were and floating point off
566 isync
567
568 blr
569
570 fsbackout: mr r12,r0 ; Save the original MSR
571 b EXT(save_ret_join) ; Toss savearea and return from there...
572
573 /*
574 * fpu_switch()
575 *
576 * Entered to handle the floating-point unavailable exception and
577 * switch fpu context
578 *
579 * This code is run in virtual address mode on with interrupts off.
580 *
581 * Upon exit, the code returns to the users context with the floating
582 * point facility turned on.
583 *
584 * ENTRY: VM switched ON
585 * Interrupts OFF
586 * State is saved in savearea pointed to by R4.
587 * All other registers are free.
588 *
589 */
590
591 .align 5
592 .globl EXT(fpu_switch)
593
594 LEXT(fpu_switch)
595
596 #if DEBUG
597 lis r3,hi16(EXT(fpu_trap_count)) ; Get address of FP trap counter
598 ori r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
599 lwz r1,0(r3)
600 addi r1,r1,1
601 stw r1,0(r3)
602 #endif /* DEBUG */
603
604 mfsprg r26,0 ; Get the per_processor block
605 mfmsr r19 ; Get the current MSR
606
607 mr r25,r4 ; Save the entry savearea
608 lwz r22,FPUowner(r26) ; Get the thread that owns the FPU
609 lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread
610 ori r19,r19,lo16(MASK(MSR_FP)) ; Enable the floating point feature
611 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
612
613 mtmsr r19 ; Enable floating point instructions
614 isync
615
616 lwz r27,ACT_MACT_PCB(r17) ; Get the current level
617 lwz r29,curctx(r17) ; Grab the current context anchor of the current thread
618
619 ; R22 has the "old" context anchor
620 ; R29 has the "new" context anchor
621
622 #if FPVECDBG
623 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
624 li r2,0x7F01 ; (TEST/DEBUG)
625 mr r3,r22 ; (TEST/DEBUG)
626 mr r5,r29 ; (TEST/DEBUG)
627 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
628 sc ; (TEST/DEBUG)
629 #endif
630
631 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
632
633 fswretry: mr. r22,r22 ; See if there is any live FP status
634
635 beq- fsnosave ; No live context, so nothing to save...
636
637 isync ; Make sure we see this in the right order
638
639 lwz r30,FPUsave(r22) ; Get the top savearea
640 cmplw cr2,r22,r29 ; Are both old and new the same context?
641 lwz r18,FPUcpu(r22) ; Get the last CPU we ran on
642 cmplwi cr1,r30,0 ; Anything saved yet?
643 cmplw r18,r16 ; Make sure we are on the right processor
644 lwz r31,FPUlevel(r22) ; Get the context level
645
646 bne- fsnosave ; No, not on the same processor...
647
648 ;
649 ; Check to see if the live context has already been saved.
650 ; Also check to see if all we are here just to re-enable the MSR
651 ; and handle specially if so.
652 ;
653
654 cmplw r31,r27 ; See if the current and active levels are the same
655 crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same
656 li r3,0 ; Clear this
657
658 beq- fsthesame ; New and old are the same, just go enable...
659
660 beq- cr1,fsmstsave ; Not saved yet, go do it...
661
662 lwz r11,SAVlevel(r30) ; Get the level of top saved context
663
664 cmplw r31,r11 ; Are live and saved the same?
665
666 #if FPVECDBG
667 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
668 li r2,0x7F02 ; (TEST/DEBUG)
669 mr r3,r30 ; (TEST/DEBUG)
670 mr r5,r31 ; (TEST/DEBUG)
671 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
672 sc ; (TEST/DEBUG)
673 #endif
674
675 beq+ fsnosave ; Same level, so already saved...
676
677
678 fsmstsave: stw r3,FPUowner(r26) ; Kill the context now
679 eieio ; Make sure everyone sees it
680 bl EXT(save_get) ; Go get a savearea
681
682 la r11,savefp0(r3) ; Point to the 1st line in new savearea
683 lwz r12,facAct(r22) ; Get the activation associated with the context
684 dcbz 0,r11 ; Allocate cache
685 stw r3,FPUsave(r22) ; Set this as the latest context savearea for the thread
686
687 stw r30,SAVprev(r3) ; Point us to the old context
688 stw r31,SAVlevel(r3) ; Tag our level
689 li r7,SAVfloat ; Get the floating point ID
690 stw r12,SAVact(r3) ; Make sure we point to the right guy
691 stb r7,SAVflags+2(r3) ; Set that we have a floating point save area
692
693 #if FPVECDBG
694 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
695 li r2,0x7F03 ; (TEST/DEBUG)
696 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
697 sc ; (TEST/DEBUG)
698 #endif
699
700 ;
701 ; Now we will actually save the old context
702 ;
703
704 la r11,savefp4(r3) ; Point to the 2nd line
705 stfd f0,savefp0(r3)
706 dcbz 0,r11 ; Allocate cache
707 stfd f1,savefp1(r3)
708 stfd f2,savefp2(r3)
709 la r11,savefp8(r3) ; Point to the 3rd line
710 stfd f3,savefp3(r3)
711 dcbz 0,r11 ; Allocate cache
712 stfd f4,savefp4(r3)
713 stfd f5,savefp5(r3)
714 stfd f6,savefp6(r3)
715 la r11,savefp12(r3) ; Point to the 4th line
716 stfd f7,savefp7(r3)
717 dcbz 0,r11 ; Allocate cache
718 stfd f8,savefp8(r3)
719 stfd f9,savefp9(r3)
720 stfd f10,savefp10(r3)
721 la r11,savefp16(r3) ; Point to the 5th line
722 stfd f11,savefp11(r3)
723 dcbz 0,r11 ; Allocate cache
724 stfd f12,savefp12(r3)
725 stfd f13,savefp13(r3)
726 stfd f14,savefp14(r3)
727 la r11,savefp20(r3) ; Point to the 6th line
728 stfd f15,savefp15(r3)
729 dcbz 0,r11 ; Allocate cache
730 stfd f16,savefp16(r3)
731 stfd f17,savefp17(r3)
732 stfd f18,savefp18(r3)
733 la r11,savefp24(r3) ; Point to the 7th line
734 stfd f19,savefp19(r3)
735 dcbz 0,r11 ; Allocate cache
736 stfd f20,savefp20(r3)
737
738 stfd f21,savefp21(r3)
739 stfd f22,savefp22(r3)
740 la r11,savefp28(r3) ; Point to the 8th line
741 stfd f23,savefp23(r3)
742 dcbz 0,r11 ; allocate it
743 stfd f24,savefp24(r3)
744 stfd f25,savefp25(r3)
745 stfd f26,savefp26(r3)
746 stfd f27,savefp27(r3)
747 dcbz 0,r11 ; allocate it
748 stfd f28,savefp28(r3)
749 stfd f29,savefp29(r3)
750 stfd f30,savefp30(r3)
751 stfd f31,savefp31(r3)
752
753 ;
754 ; The context is all saved now and the facility is free.
755 ;
756 ; If we do not we need to fill the registers with junk, because this level has
757 ; never used them before and some thieving bastard could hack the old values
758 ; of some thread! Just imagine what would happen if they could! Why, nothing
759 ; would be safe! My God! It is terrifying!
760 ;
761
762
763 fsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
764 lwz r19,FPUcpu(r29) ; Get the last CPU we ran on
765 lwz r14,FPUsave(r29) ; Point to the top of the "new" context stack
766
767 stw r16,FPUcpu(r29) ; Claim context for us
768 eieio
769
770 #if FPVECDBG
771 lwz r13,FPUlevel(r29) ; (TEST/DEBUG)
772 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
773 li r2,0x7F04 ; (TEST/DEBUG)
774 mr r1,r15 ; (TEST/DEBUG)
775 mr r3,r14 ; (TEST/DEBUG)
776 mr r5,r13 ; (TEST/DEBUG)
777 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
778 sc ; (TEST/DEBUG)
779 #endif
780
781 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
782 mulli r19,r19,ppSize ; Find offset to the owner per_proc
783 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
784 li r16,FPUowner ; Displacement to float owner
785 add r19,r18,r19 ; Point to the owner per_proc
786 li r0,0
787
788 fsinvothr: lwarx r18,r16,r19 ; Get the owner
789 cmplw r18,r29 ; Does he still have this context?
790 bne fsinvoths ; Nope...
791 stwcx. r0,r16,r19 ; Try to invalidate it
792 bne- fsinvothr ; Try again if there was a collision...
793
794 fsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
795 la r11,savefp0(r14) ; Point to first line to bring in
796 stw r15,FPUlevel(r29) ; Set the "new" active level
797 eieio
798 stw r29,FPUowner(r26) ; Mark us as having the live context
799
800 beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load...
801
802 dcbt 0,r11 ; Touch line in
803
804 lwz r3,SAVprev(r14) ; Get the previous context
805 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
806 cmplw r0,r15 ; Top level correct to load?
807 bne- MakeSureThatNoTerroristsCanHurtUsByGod ; No, go initialize...
808
809 stw r3,FPUsave(r29) ; Pop the context (we will toss the savearea later)
810
811 #if FPVECDBG
812 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
813 li r2,0x7F05 ; (TEST/DEBUG)
814 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
815 sc ; (TEST/DEBUG)
816 #endif
817
818 la r11,savefp4(r14) ; Point to next line
819 dcbt 0,r11 ; Touch line in
820 lfd f0, savefp0(r14)
821 lfd f1,savefp1(r14)
822 lfd f2,savefp2(r14)
823 la r11,savefp8(r14) ; Point to next line
824 lfd f3,savefp3(r14)
825 dcbt 0,r11 ; Touch line in
826 lfd f4,savefp4(r14)
827 lfd f5,savefp5(r14)
828 lfd f6,savefp6(r14)
829 la r11,savefp12(r14) ; Point to next line
830 lfd f7,savefp7(r14)
831 dcbt 0,r11 ; Touch line in
832 lfd f8,savefp8(r14)
833 lfd f9,savefp9(r14)
834 lfd f10,savefp10(r14)
835 la r11,savefp16(r14) ; Point to next line
836 lfd f11,savefp11(r14)
837 dcbt 0,r11 ; Touch line in
838 lfd f12,savefp12(r14)
839 lfd f13,savefp13(r14)
840 lfd f14,savefp14(r14)
841 la r11,savefp20(r14) ; Point to next line
842 lfd f15,savefp15(r14)
843 dcbt 0,r11 ; Touch line in
844 lfd f16,savefp16(r14)
845 lfd f17,savefp17(r14)
846 lfd f18,savefp18(r14)
847 la r11,savefp24(r14) ; Point to next line
848 lfd f19,savefp19(r14)
849 dcbt 0,r11 ; Touch line in
850 lfd f20,savefp20(r14)
851 lfd f21,savefp21(r14)
852 la r11,savefp28(r14) ; Point to next line
853 lfd f22,savefp22(r14)
854 lfd f23,savefp23(r14)
855 dcbt 0,r11 ; Touch line in
856 lfd f24,savefp24(r14)
857 lfd f25,savefp25(r14)
858 lfd f26,savefp26(r14)
859 lfd f27,savefp27(r14)
860 lfd f28,savefp28(r14)
861 lfd f29,savefp29(r14)
862 lfd f30,savefp30(r14)
863 lfd f31,savefp31(r14)
864
865 mr r3,r14 ; Get the old savearea (we popped it before)
866 bl EXT(save_ret) ; Toss it
867
868 fsenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
869 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
870 ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature
871 lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags
872 lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act
873 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
874 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
875 oris r11,r11,hi16(floatUsed|floatCng) ; Set that we used floating point
876 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
877 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
878 xor r3,r25,r5 ; Get the real address of the savearea
879 beq- fsnuser ; We are not user state...
880 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
881 stw r11,spcFlags(r26) ; Set per_proc copy
882
883 fsnuser:
884 #if FPVECDBG
885 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
886 li r2,0x7F07 ; (TEST/DEBUG)
887 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
888 sc ; (TEST/DEBUG)
889 #endif
890
891 b EXT(exception_exit) ; Exit to the fray...
892
893 /*
894 * Initialize the registers to some bogus value
895 */
896
897 MakeSureThatNoTerroristsCanHurtUsByGod:
898
899 #if FPVECDBG
900 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
901 li r2,0x7F06 ; (TEST/DEBUG)
902 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
903 sc ; (TEST/DEBUG)
904 #endif
905 lis r5,hi16(EXT(FloatInit)) ; Get top secret floating point init value address
906 ori r5,r5,lo16(EXT(FloatInit)) ; Slam bottom
907 lfd f0,0(r5) ; Initialize FP0
908 fmr f1,f0 ; Do them all
909 fmr f2,f0
910 fmr f3,f0
911 fmr f4,f0
912 fmr f5,f0
913 fmr f6,f0
914 fmr f7,f0
915 fmr f8,f0
916 fmr f9,f0
917 fmr f10,f0
918 fmr f11,f0
919 fmr f12,f0
920 fmr f13,f0
921 fmr f14,f0
922 fmr f15,f0
923 fmr f16,f0
924 fmr f17,f0
925 fmr f18,f0
926 fmr f19,f0
927 fmr f20,f0
928 fmr f21,f0
929 fmr f22,f0
930 fmr f23,f0
931 fmr f24,f0
932 fmr f25,f0
933 fmr f26,f0
934 fmr f27,f0
935 fmr f28,f0
936 fmr f29,f0
937 fmr f30,f0
938 fmr f31,f0
939 b fsenable ; Finish setting it all up...
940
941
942 ;
943 ; We get here when we are switching to the same context at the same level and the context
944 ; is still live. Essentially, all we are doing is turning on the faility. It may have
945 ; gotten turned off due to doing a context save for the current level or a context switch
946 ; back to the live guy.
947 ;
948
949 .align 5
950
951 fsthesame:
952
953 #if FPVECDBG
954 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
955 li r2,0x7F0A ; (TEST/DEBUG)
956 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
957 sc ; (TEST/DEBUG)
958 #endif
959 beq- cr1,fsenable ; Not saved yet, nothing to pop, go enable and exit...
960
961 lwz r11,SAVlevel(r30) ; Get the level of top saved context
962 lwz r14,SAVprev(r30) ; Get the previous savearea
963
964 cmplw r11,r31 ; Are live and saved the same?
965
966 bne+ fsenable ; Level not the same, nothing to pop, go enable and exit...
967
968 mr r3,r30 ; Get the old savearea (we popped it before)
969 bl EXT(save_ret) ; Toss it
970 b fsenable ; Go enable and exit...
971
972
973 ;
974 ; This function invalidates any live floating point context for the passed in facility_context.
975 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
976 ;
977
978 .align 5
979 .globl EXT(toss_live_fpu)
980
981 LEXT(toss_live_fpu)
982
983
984 mfmsr r9 ; Get the MSR
985 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
986 rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now?
987 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off
988 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure floats are turned off
989 mtmsr r0 ; No interruptions
990 isync
991 beq+ tlfnotours ; Floats off, can not be live here...
992
993 mfsprg r8,0 ; Get the per proc
994
995 ;
996 ; Note that at this point, since floats are on, we are the owner
997 ; of live state on this processor
998 ;
999
1000 lwz r6,FPUowner(r8) ; Get the thread that owns the floats
1001 li r0,0 ; Clear this just in case we need it
1002 cmplw r6,r3 ; Are we tossing our own context?
1003 bne- tlfnotours ; Nope...
1004
1005 fsub f1,f1,f1 ; Make a 0
1006 mtfsf 0xFF,f1 ; Clear it
1007
1008 tlfnotours: lwz r11,FPUcpu(r3) ; Get the cpu on which we last loaded context
1009 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
1010 mulli r11,r11,ppSize ; Find offset to the owner per_proc
1011 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
1012 li r10,FPUowner ; Displacement to float owner
1013 add r11,r12,r11 ; Point to the owner per_proc
1014 li r0,0 ; Set a 0 to invalidate context
1015
1016 tlfinvothr: lwarx r12,r10,r11 ; Get the owner
1017 cmplw r12,r3 ; Does he still have this context?
1018 bne+ tlfexit ; Nope, leave...
1019 stwcx. r0,r10,r11 ; Try to invalidate it
1020 bne- tlfinvothr ; Try again if there was a collision...
1021
1022 tlfexit: mtmsr r9 ; Restore interruptions
1023 isync ; Could be turning off floats here
1024 blr ; Leave...
1025
1026
1027 /*
1028 * Altivec stuff is here. The techniques used are pretty identical to
1029 * the floating point. Except that we will honor the VRSAVE register
1030 * settings when loading and restoring registers.
1031 *
1032 * There are two indications of saved VRs: the VRSAVE register and the vrvalid
1033 * mask. VRSAVE is set by the vector user and represents the VRs that they
1034 * say that they are using. The vrvalid mask indicates which vector registers
1035 * are saved in the savearea. Whenever context is saved, it is saved according
1036 * to the VRSAVE register. It is loaded based on VRSAVE anded with
1037 * vrvalid (all other registers are splatted with 0s). This is done because we
1038 * don't want to load any registers we don't have a copy of, we want to set them
1039 * to zero instead.
1040 *
1041 * Note that there are some oddities here when we save a context we are using.
1042 * It is really not too cool to do this, but what the hey... Anyway,
1043 * we turn vectors and fpu off before we leave.
1044 * The oddity is that if you use vectors after this, the
1045 * savearea containing the context just saved will go away. So, bottom line is
1046 * that don't use vectors until after you are done with the saved context.
1047 *
1048 */
1049
1050 .align 5
1051 .globl EXT(vec_save)
1052
1053 LEXT(vec_save)
1054
1055 mfmsr r0 ; Get the MSR
1056 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off when we leave
1057 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
1058 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
1059 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp
1060 mtmsr r2 ; Set the MSR
1061 isync
1062
1063 mfsprg r6,0 ; Get the per_processor block
1064 lwz r12,VMXowner(r6) ; Get the context ID for owner
1065
1066 #if FPVECDBG
1067 mr r7,r0 ; (TEST/DEBUG)
1068 li r4,0 ; (TEST/DEBUG)
1069 mr r10,r3 ; (TEST/DEBUG)
1070 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1071 mr. r3,r12 ; (TEST/DEBUG)
1072 li r2,0x5F00 ; (TEST/DEBUG)
1073 li r5,0 ; (TEST/DEBUG)
1074 beq- noowneryeu ; (TEST/DEBUG)
1075 lwz r4,VMXlevel(r12) ; (TEST/DEBUG)
1076 lwz r5,VMXsave(r12) ; (TEST/DEBUG)
1077
1078 noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1079 sc ; (TEST/DEBUG)
1080 mr r0,r7 ; (TEST/DEBUG)
1081 mr r3,r10 ; (TEST/DEBUG)
1082 #endif
1083 mflr r2 ; Save the return address
1084
1085 vsretry: mr. r12,r12 ; Anyone own the vector?
1086 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
1087 beq- vsret ; Nobody owns the vector, no save required...
1088
1089 cmplw cr1,r3,r12 ; Is the specified context live?
1090
1091 isync ; Force owner check first
1092
1093 lwz r9,VMXcpu(r12) ; Get the cpu that context was last on
1094 bne- cr1,vsret ; Specified context is not live
1095
1096 cmplw cr1,r9,r11 ; Was the context for this processor?
1097 beq+ cr1,vsgoodcpu ; Facility last used on this processor...
1098
1099 b vsret ; Someone else claimed this...
1100
1101 .align 5
1102
1103 vsgoodcpu: lwz r3,VMXsave(r12) ; Get the current vector savearea for the thread
1104 lwz r10,liveVRS(r6) ; Get the right VRSave register
1105 lwz r9,VMXlevel(r12) ; Get our current level indicator
1106
1107
1108 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
1109 beq- cr1,vsneedone ; Never saved it, so we need an area...
1110
1111 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
1112 mr. r10,r10 ; Is VRsave set to 0?
1113 cmplw cr1,r9,r8 ; Correct level?
1114 bne- cr1,vsneedone ; Different level, so we need to save...
1115
1116 bne+ vsret ; VRsave is non-zero so we need to keep what is saved...
1117
1118 lwz r4,SAVprev(r3) ; Pick up the previous area
1119 lwz r5,SAVlevel(r4) ; Get the level associated with save
1120 stw r4,VMXsave(r12) ; Dequeue this savearea
1121 stw r5,VMXlevel(r12) ; Save the level
1122
1123 li r3,0 ; Clear
1124 stw r3,VMXowner(r12) ; Show no live context here
1125 eieio
1126
1127 vsbackout: mr r12,r0 ; Set the saved MSR
1128 b EXT(save_ret_join) ; Toss the savearea and return from there...
1129
1130 .align 5
1131
1132 vsneedone: mr. r10,r10 ; Is VRsave set to 0?
1133 beq- vsret ; Yeah, they do not care about any of them...
1134
1135 bl EXT(save_get) ; Get a savearea for the context
1136
1137 mfsprg r6,0 ; Get back per_processor block
1138 li r4,SAVvector ; Get vector tag
1139 lwz r12,VMXowner(r6) ; Get back our context ID
1140 stb r4,SAVflags+2(r3) ; Mark this savearea as a vector
1141 mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it...
1142 beq- vsbackout ; If disowned, just toss savearea...
1143 lwz r4,facAct(r12) ; Get the activation associated with live context
1144 mtlr r2 ; Restore return
1145 lwz r8,VMXsave(r12) ; Get the current top vector savearea
1146 stw r4,SAVact(r3) ; Indicate the right activation for this context
1147 lwz r9,VMXlevel(r12) ; Get our current level indicator again
1148 stw r3,VMXsave(r12) ; Set this as the most current floating point context
1149 stw r8,SAVprev(r3) ; And then chain this in front
1150
1151 stw r9,SAVlevel(r3) ; Set level in savearea
1152
1153 mfcr r2 ; Save non-volatile CRs
1154 lwz r10,liveVRS(r6) ; Get the right VRSave register
1155 lis r9,0x5555 ; Mask with odd bits set
1156 rlwinm r11,r10,1,0,31 ; Shift over 1
1157 ori r9,r9,0x5555 ; Finish mask
1158 or r4,r10,r11 ; After this, even bits show which lines to zap
1159
1160 andc r11,r4,r9 ; Clear out odd bits
1161
1162 la r6,savevr0(r3) ; Point to line 0
1163 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits
1164 or r4,r11,r4 ; Set the odd bits
1165 ; (bit 0 is line 0, bit 1 is line 8,
1166 ; bit 2 is line 1, bit 3 is line 9, etc.
1167 rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1168 la r7,savevr2(r3) ; Point to line 1
1169 mtcrf 255,r4 ; Load up the CRs
1170 stw r10,savevrvalid(r3) ; Save the validity information
1171 mr r8,r6 ; Start registers off
1172 ;
1173 ; Save the current vector state
1174 ;
1175
1176 bf 0,snol0 ; No line 0 to do...
1177 dcba br0,r6 ; Allocate cache line 0
1178
1179 snol0:
1180 la r6,savevr4(r3) ; Point to line 2
1181 bf 2,snol1 ; No line 1 to do...
1182 dcba br0,r7 ; Allocate cache line 1
1183
1184 snol1:
1185 la r7,savevr6(r3) ; Point to line 3
1186 bf 4,snol2 ; No line 2 to do...
1187 dcba br0,r6 ; Allocate cache line 2
1188
1189 snol2:
1190 li r11,16 ; Get offset for odd registers
1191 bf 16,snovr0 ; Do not save VR0...
1192 stvxl v0,br0,r8 ; Save VR0
1193
1194 snovr0:
1195 la r9,savevr2(r3) ; Point to V2/V3 pair
1196 bf 17,snovr1 ; Do not save VR1...
1197 stvxl v1,r11,r8 ; Save VR1
1198
1199 snovr1:
1200 la r6,savevr8(r3) ; Point to line 4
1201 bf 6,snol3 ; No line 3 to do...
1202 dcba br0,r7 ; Allocate cache line 3
1203
1204 snol3:
1205 la r8,savevr4(r3) ; Point to V4/V5 pair
1206 bf 18,snovr2 ; Do not save VR2...
1207 stvxl v2,br0,r9 ; Save VR2
1208
1209 snovr2:
1210 bf 19,snovr3 ; Do not save VR3...
1211 stvxl v3,r11,r9 ; Save VR3
1212
1213 snovr3:
1214 ;
1215 ; Note: CR4 is now free
1216 ;
1217 la r7,savevr10(r3) ; Point to line 5
1218 bf 8,snol4 ; No line 4 to do...
1219 dcba br0,r6 ; Allocate cache line 4
1220
1221 snol4:
1222 la r9,savevr6(r3) ; Point to R6/R7 pair
1223 bf 20,snovr4 ; Do not save VR4...
1224 stvxl v4,br0,r8 ; Save VR4
1225
1226 snovr4:
1227 bf 21,snovr5 ; Do not save VR5...
1228 stvxl v5,r11,r8 ; Save VR5
1229
1230 snovr5:
1231 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1232 la r6,savevr12(r3) ; Point to line 6
1233 bf 10,snol5 ; No line 5 to do...
1234 dcba br0,r7 ; Allocate cache line 5
1235
1236 snol5:
1237 la r8,savevr8(r3) ; Point to V8/V9 pair
1238 bf 22,snovr6 ; Do not save VR6...
1239 stvxl v6,br0,r9 ; Save VR6
1240
1241 snovr6:
1242 bf 23,snovr7 ; Do not save VR7...
1243 stvxl v7,r11,r9 ; Save VR7
1244
1245 snovr7:
1246 ;
1247 ; Note: CR5 is now free
1248 ;
1249 la r7,savevr14(r3) ; Point to line 7
1250 bf 12,snol6 ; No line 6 to do...
1251 dcba br0,r6 ; Allocate cache line 6
1252
1253 snol6:
1254 la r9,savevr10(r3) ; Point to V10/V11 pair
1255 bf 24,snovr8 ; Do not save VR8...
1256 stvxl v8,br0,r8 ; Save VR8
1257
1258 snovr8:
1259 bf 25,snovr9 ; Do not save VR9...
1260 stvxl v9,r11,r8 ; Save VR9
1261
1262 snovr9:
1263 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1264 la r6,savevr16(r3) ; Point to line 8
1265 bf 14,snol7 ; No line 7 to do...
1266 dcba br0,r7 ; Allocate cache line 7
1267
1268 snol7:
1269 la r8,savevr12(r3) ; Point to V12/V13 pair
1270 bf 26,snovr10 ; Do not save VR10...
1271 stvxl v10,br0,r9 ; Save VR10
1272
1273 snovr10:
1274 bf 27,snovr11 ; Do not save VR11...
1275 stvxl v11,r11,r9 ; Save VR11
1276
1277 snovr11:
1278
1279 ;
1280 ; Note: CR6 is now free
1281 ;
1282 la r7,savevr18(r3) ; Point to line 9
1283 bf 1,snol8 ; No line 8 to do...
1284 dcba br0,r6 ; Allocate cache line 8
1285
1286 snol8:
1287 la r9,savevr14(r3) ; Point to V14/V15 pair
1288 bf 28,snovr12 ; Do not save VR12...
1289 stvxl v12,br0,r8 ; Save VR12
1290
1291 snovr12:
1292 bf 29,snovr13 ; Do not save VR13...
1293 stvxl v13,r11,r8 ; Save VR13
1294
1295 snovr13:
1296 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1297 la r6,savevr20(r3) ; Point to line 10
1298 bf 3,snol9 ; No line 9 to do...
1299 dcba br0,r7 ; Allocate cache line 9
1300
1301 snol9:
1302 la r8,savevr16(r3) ; Point to V16/V17 pair
1303 bf 30,snovr14 ; Do not save VR14...
1304 stvxl v14,br0,r9 ; Save VR14
1305
1306 snovr14:
1307 bf 31,snovr15 ; Do not save VR15...
1308 stvxl v15,r11,r9 ; Save VR15
1309
1310 snovr15:
1311 ;
1312 ; Note: CR7 is now free
1313 ;
1314 la r7,savevr22(r3) ; Point to line 11
1315 bf 5,snol10 ; No line 10 to do...
1316 dcba br0,r6 ; Allocate cache line 10
1317
1318 snol10:
1319 la r9,savevr18(r3) ; Point to V18/V19 pair
1320 bf 16,snovr16 ; Do not save VR16...
1321 stvxl v16,br0,r8 ; Save VR16
1322
1323 snovr16:
1324 bf 17,snovr17 ; Do not save VR17...
1325 stvxl v17,r11,r8 ; Save VR17
1326
1327 snovr17:
1328 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1329 ;
1330 ; Note: All registers have been or are accounted for in CRs
1331 ;
1332 la r6,savevr24(r3) ; Point to line 12
1333 bf 7,snol11 ; No line 11 to do...
1334 dcba br0,r7 ; Allocate cache line 11
1335
1336 snol11:
1337 la r8,savevr20(r3) ; Point to V20/V21 pair
1338 bf 18,snovr18 ; Do not save VR18...
1339 stvxl v18,br0,r9 ; Save VR18
1340
1341 snovr18:
1342 bf 19,snovr19 ; Do not save VR19...
1343 stvxl v19,r11,r9 ; Save VR19
1344
1345 snovr19:
1346 la r7,savevr26(r3) ; Point to line 13
1347 bf 9,snol12 ; No line 12 to do...
1348 dcba br0,r6 ; Allocate cache line 12
1349
1350 snol12:
1351 la r9,savevr22(r3) ; Point to V22/V23 pair
1352 bf 20,snovr20 ; Do not save VR20...
1353 stvxl v20,br0,r8 ; Save VR20
1354
1355 snovr20:
1356 bf 21,snovr21 ; Do not save VR21...
1357 stvxl v21,r11,r8 ; Save VR21
1358
1359 snovr21:
1360 la r6,savevr28(r3) ; Point to line 14
1361 bf 11,snol13 ; No line 13 to do...
1362 dcba br0,r7 ; Allocate cache line 13
1363
1364 snol13:
1365 la r8,savevr24(r3) ; Point to V24/V25 pair
1366 bf 22,snovr22 ; Do not save VR22...
1367 stvxl v22,br0,r9 ; Save VR22
1368
1369 snovr22:
1370 bf 23,snovr23 ; Do not save VR23...
1371 stvxl v23,r11,r9 ; Save VR23
1372
1373 snovr23:
1374 la r7,savevr30(r3) ; Point to line 15
1375 bf 13,snol14 ; No line 14 to do...
1376 dcba br0,r6 ; Allocate cache line 14
1377
1378 snol14:
1379 la r9,savevr26(r3) ; Point to V26/V27 pair
1380 bf 24,snovr24 ; Do not save VR24...
1381 stvxl v24,br0,r8 ; Save VR24
1382
1383 snovr24:
1384 bf 25,snovr25 ; Do not save VR25...
1385 stvxl v25,r11,r8 ; Save VR25
1386
1387 snovr25:
1388 bf 15,snol15 ; No line 15 to do...
1389 dcba br0,r7 ; Allocate cache line 15
1390
1391 snol15:
1392 ;
1393 ; Note: All cache lines allocated now
1394 ;
1395 la r8,savevr28(r3) ; Point to V28/V29 pair
1396 bf 26,snovr26 ; Do not save VR26...
1397 stvxl v26,br0,r9 ; Save VR26
1398
1399 snovr26:
1400 bf 27,snovr27 ; Do not save VR27...
1401 stvxl v27,r11,r9 ; Save VR27
1402
1403 snovr27:
1404 la r7,savevr30(r3) ; Point to V30/V31 pair
1405 bf 28,snovr28 ; Do not save VR28...
1406 stvxl v28,br0,r8 ; Save VR28
1407
1408 snovr28:
1409 bf 29,snovr29 ; Do not save VR29...
1410 stvxl v29,r11,r8 ; Save VR29
1411
1412 snovr29:
1413 bf 30,snovr30 ; Do not save VR30...
1414 stvxl v30,br0,r7 ; Save VR30
1415
1416 snovr30:
1417 bf 31,snovr31 ; Do not save VR31...
1418 stvxl v31,r11,r7 ; Save VR31
1419
1420 snovr31:
1421 mtcrf 255,r2 ; Restore all cr
1422
1423 vsret: mtmsr r0 ; Put interrupts on if they were and vector off
1424 isync
1425
1426 blr
1427
1428 /*
1429 * vec_switch()
1430 *
1431 * Entered to handle the vector unavailable exception and
1432 * switch vector context
1433 *
1434 * This code is run with virtual address mode on and interrupts off.
1435 *
1436 * Upon exit, the code returns to the users context with the vector
1437 * facility turned on.
1438 *
1439 * ENTRY: VM switched ON
1440 * Interrupts OFF
1441 * State is saved in savearea pointed to by R4.
1442 * All other registers are free.
1443 *
1444 */
1445
1446 .align 5
1447 .globl EXT(vec_switch)
1448
1449 LEXT(vec_switch)
1450
1451 #if DEBUG
1452 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1453 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1454 lwz r1,0(r3)
1455 addi r1,r1,1
1456 stw r1,0(r3)
1457 #endif /* DEBUG */
1458
1459 mfsprg r26,0 ; Get the per_processor block
1460 mfmsr r19 ; Get the current MSR
1461
1462 mr r25,r4 ; Save the entry savearea
1463 lwz r22,VMXowner(r26) ; Get the thread that owns the vector
1464 lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread
1465 oris r19,r19,hi16(MASK(MSR_VEC)) ; Enable the vector feature
1466 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
1467
1468 mtmsr r19 ; Enable vector instructions
1469 isync
1470
1471 lwz r27,ACT_MACT_PCB(r17) ; Get the current level
1472 lwz r29,curctx(r17) ; Grab the current context anchor of the current thread
1473
1474 ; R22 has the "old" context anchor
1475 ; R29 has the "new" context anchor
1476
1477 #if FPVECDBG
1478 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1479 li r2,0x5F01 ; (TEST/DEBUG)
1480 mr r3,r22 ; (TEST/DEBUG)
1481 mr r5,r29 ; (TEST/DEBUG)
1482 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1483 sc ; (TEST/DEBUG)
1484 #endif
1485
1486 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
1487
1488 vsvretry: mr. r22,r22 ; See if there is any live vector status
1489
1490 beq- vsnosave ; No live context, so nothing to save...
1491
1492 isync ; Make sure we see this in the right order
1493
1494 lwz r30,VMXsave(r22) ; Get the top savearea
1495 cmplw cr2,r22,r29 ; Are both old and new the same context?
1496 lwz r18,VMXcpu(r22) ; Get the last CPU we ran on
1497 cmplwi cr1,r30,0 ; Anything saved yet?
1498 cmplw r18,r16 ; Make sure we are on the right processor
1499 lwz r31,VMXlevel(r22) ; Get the context level
1500
1501 lwz r10,liveVRS(r26) ; Get the right VRSave register
1502
1503 bne- vsnosave ; No, not on the same processor...
1504
1505 ;
1506 ; Check to see if the live context has already been saved.
1507 ; Also check to see if all we are here just to re-enable the MSR
1508 ; and handle specially if so.
1509 ;
1510
1511 cmplw r31,r27 ; See if the current and active levels are the same
1512 crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same
1513 li r8,0 ; Clear this
1514
1515 beq- vsthesame ; New and old are the same, just go enable...
1516
1517 cmplwi cr2,r10,0 ; Check VRSave to see if we really need to save anything...
1518 beq- cr1,vsmstsave ; Not saved yet, go do it...
1519
1520 lwz r11,SAVlevel(r30) ; Get the level of top saved context
1521
1522 cmplw r31,r11 ; Are live and saved the same?
1523
1524 #if FPVECDBG
1525 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1526 li r2,0x5F02 ; (TEST/DEBUG)
1527 mr r3,r30 ; (TEST/DEBUG)
1528 mr r5,r31 ; (TEST/DEBUG)
1529 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1530 sc ; (TEST/DEBUG)
1531 #endif
1532
1533 bne- vsmstsave ; Live context has not been saved yet...
1534
1535 bne- cr2,vsnosave ; Live context saved and VRSave not 0, no save and keep context...
1536
1537 lwz r4,SAVprev(r30) ; Pick up the previous area
1538 li r5,0 ; Assume this is the only one (which should be the ususal case)
1539 mr. r4,r4 ; Was this the only one?
1540 stw r4,VMXsave(r22) ; Dequeue this savearea
1541 beq+ vsonlyone ; This was the only one...
1542 lwz r5,SAVlevel(r4) ; Get the level associated with previous save
1543
1544 vsonlyone: stw r5,VMXlevel(r22) ; Save the level
1545 stw r8,VMXowner(r26) ; Clear owner
1546 eieio
1547 mr r3,r30 ; Copy the savearea we are tossing
1548 bl EXT(save_ret) ; Toss the savearea
1549 b vsnosave ; Go load up the context...
1550
1551 .align 5
1552
1553
1554 vsmstsave: stw r8,VMXowner(r26) ; Clear owner
1555 eieio
1556 beq- cr2,vsnosave ; The VRSave was 0, so there is nothing to save...
1557
1558 bl EXT(save_get) ; Go get a savearea
1559
1560 lwz r12,facAct(r22) ; Get the activation associated with the context
1561 stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread
1562
1563 stw r30,SAVprev(r3) ; Point us to the old context
1564 stw r31,SAVlevel(r3) ; Tag our level
1565 li r7,SAVvector ; Get the vector ID
1566 stw r12,SAVact(r3) ; Make sure we point to the right guy
1567 stb r7,SAVflags+2(r3) ; Set that we have a vector save area
1568
1569 #if FPVECDBG
1570 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1571 li r2,0x5F03 ; (TEST/DEBUG)
1572 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1573 sc ; (TEST/DEBUG)
1574 #endif
1575
1576 lwz r10,liveVRS(r26) ; Get the right VRSave register
1577 lis r9,0x5555 ; Mask with odd bits set
1578 rlwinm r11,r10,1,0,31 ; Shift over 1
1579 ori r9,r9,0x5555 ; Finish mask
1580 or r21,r10,r11 ; After this, even bits show which lines to zap
1581
1582 andc r13,r21,r9 ; Clear out odd bits
1583
1584 la r11,savevr0(r3) ; Point to line 0
1585 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1586 or r24,r13,r24 ; Set the odd bits
1587 ; (bit 0 is line 0, bit 1 is line 8,
1588 ; bit 2 is line 1, bit 3 is line 9, etc.
1589 rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1590 la r21,savevr2(r3) ; Point to line 1
1591 mtcrf 255,r24 ; Load up the CRs
1592 stw r10,savevrvalid(r3) ; Save the validity information
1593 mr r12,r11 ; Start registers off
1594 ;
1595 ; Save the current vector state
1596 ;
1597
1598 bf 0,nol0 ; No line 0 to do...
1599 dcba br0,r11 ; Allocate cache line 0
1600
1601 nol0:
1602 la r11,savevr4(r3) ; Point to line 2
1603 bf 2,nol1 ; No line 1 to do...
1604 dcba br0,r21 ; Allocate cache line 1
1605
1606 nol1:
1607 la r21,savevr6(r3) ; Point to line 3
1608 bf 4,nol2 ; No line 2 to do...
1609 dcba br0,r11 ; Allocate cache line 2
1610
1611 nol2:
1612 li r14,16 ; Get offset for odd registers
1613 bf 16,novr0 ; Do not save VR0...
1614 stvxl v0,br0,r12 ; Save VR0
1615
1616 novr0:
1617 la r13,savevr2(r3) ; Point to V2/V3 pair
1618 bf 17,novr1 ; Do not save VR1...
1619 stvxl v1,r14,r12 ; Save VR1
1620
1621 novr1:
1622 la r11,savevr8(r3) ; Point to line 4
1623 bf 6,nol3 ; No line 3 to do...
1624 dcba br0,r21 ; Allocate cache line 3
1625
1626 nol3:
1627 la r12,savevr4(r3) ; Point to V4/V5 pair
1628 bf 18,novr2 ; Do not save VR2...
1629 stvxl v2,br0,r13 ; Save VR2
1630
1631 novr2:
1632 bf 19,novr3 ; Do not save VR3...
1633 stvxl v3,r14,r13 ; Save VR3
1634
1635 novr3:
1636 ;
1637 ; Note: CR4 is now free
1638 ;
1639 la r21,savevr10(r3) ; Point to line 5
1640 bf 8,nol4 ; No line 4 to do...
1641 dcba br0,r11 ; Allocate cache line 4
1642
1643 nol4:
1644 la r13,savevr6(r3) ; Point to R6/R7 pair
1645 bf 20,novr4 ; Do not save VR4...
1646 stvxl v4,br0,r12 ; Save VR4
1647
1648 novr4:
1649 bf 21,novr5 ; Do not save VR5...
1650 stvxl v5,r14,r12 ; Save VR5
1651
1652 novr5:
1653 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1654 la r11,savevr12(r3) ; Point to line 6
1655 bf 10,nol5 ; No line 5 to do...
1656 dcba br0,r21 ; Allocate cache line 5
1657
1658 nol5:
1659 la r12,savevr8(r3) ; Point to V8/V9 pair
1660 bf 22,novr6 ; Do not save VR6...
1661 stvxl v6,br0,r13 ; Save VR6
1662
1663 novr6:
1664 bf 23,novr7 ; Do not save VR7...
1665 stvxl v7,r14,r13 ; Save VR7
1666
1667 novr7:
1668 ;
1669 ; Note: CR5 is now free
1670 ;
1671 la r21,savevr14(r3) ; Point to line 7
1672 bf 12,nol6 ; No line 6 to do...
1673 dcba br0,r11 ; Allocate cache line 6
1674
1675 nol6:
1676 la r13,savevr10(r3) ; Point to V10/V11 pair
1677 bf 24,novr8 ; Do not save VR8...
1678 stvxl v8,br0,r12 ; Save VR8
1679
1680 novr8:
1681 bf 25,novr9 ; Do not save VR9...
1682 stvxl v9,r14,r12 ; Save VR9
1683
1684 novr9:
1685 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1686 la r11,savevr16(r3) ; Point to line 8
1687 bf 14,nol7 ; No line 7 to do...
1688 dcba br0,r21 ; Allocate cache line 7
1689
1690 nol7:
1691 la r12,savevr12(r3) ; Point to V12/V13 pair
1692 bf 26,novr10 ; Do not save VR10...
1693 stvxl v10,br0,r13 ; Save VR10
1694
1695 novr10:
1696 bf 27,novr11 ; Do not save VR11...
1697 stvxl v11,r14,r13 ; Save VR11
1698
1699 novr11:
1700
1701 ;
1702 ; Note: CR6 is now free
1703 ;
1704 la r21,savevr18(r3) ; Point to line 9
1705 bf 1,nol8 ; No line 8 to do...
1706 dcba br0,r11 ; Allocate cache line 8
1707
1708 nol8:
1709 la r13,savevr14(r3) ; Point to V14/V15 pair
1710 bf 28,novr12 ; Do not save VR12...
1711 stvxl v12,br0,r12 ; Save VR12
1712
1713 novr12:
1714 bf 29,novr13 ; Do not save VR13...
1715 stvxl v13,r14,r12 ; Save VR13
1716
1717 novr13:
1718 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1719 la r11,savevr20(r3) ; Point to line 10
1720 bf 3,nol9 ; No line 9 to do...
1721 dcba br0,r21 ; Allocate cache line 9
1722
1723 nol9:
1724 la r12,savevr16(r3) ; Point to V16/V17 pair
1725 bf 30,novr14 ; Do not save VR14...
1726 stvxl v14,br0,r13 ; Save VR14
1727
1728 novr14:
1729 bf 31,novr15 ; Do not save VR15...
1730 stvxl v15,r14,r13 ; Save VR15
1731
1732 novr15:
1733 ;
1734 ; Note: CR7 is now free
1735 ;
1736 la r21,savevr22(r3) ; Point to line 11
1737 bf 5,nol10 ; No line 10 to do...
1738 dcba br0,r11 ; Allocate cache line 10
1739
1740 nol10:
1741 la r13,savevr18(r3) ; Point to V18/V19 pair
1742 bf 16,novr16 ; Do not save VR16...
1743 stvxl v16,br0,r12 ; Save VR16
1744
1745 novr16:
1746 bf 17,novr17 ; Do not save VR17...
1747 stvxl v17,r14,r12 ; Save VR17
1748
1749 novr17:
1750 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1751 ;
1752 ; Note: All registers have been or are accounted for in CRs
1753 ;
1754 la r11,savevr24(r3) ; Point to line 12
1755 bf 7,nol11 ; No line 11 to do...
1756 dcba br0,r21 ; Allocate cache line 11
1757
1758 nol11:
1759 la r12,savevr20(r3) ; Point to V20/V21 pair
1760 bf 18,novr18 ; Do not save VR18...
1761 stvxl v18,br0,r13 ; Save VR18
1762
1763 novr18:
1764 bf 19,novr19 ; Do not save VR19...
1765 stvxl v19,r14,r13 ; Save VR19
1766
1767 novr19:
1768 la r21,savevr26(r3) ; Point to line 13
1769 bf 9,nol12 ; No line 12 to do...
1770 dcba br0,r11 ; Allocate cache line 12
1771
1772 nol12:
1773 la r13,savevr22(r3) ; Point to V22/V23 pair
1774 bf 20,novr20 ; Do not save VR20...
1775 stvxl v20,br0,r12 ; Save VR20
1776
1777 novr20:
1778 bf 21,novr21 ; Do not save VR21...
1779 stvxl v21,r14,r12 ; Save VR21
1780
1781 novr21:
1782 la r11,savevr28(r3) ; Point to line 14
1783 bf 11,nol13 ; No line 13 to do...
1784 dcba br0,r21 ; Allocate cache line 13
1785
1786 nol13:
1787 la r12,savevr24(r3) ; Point to V24/V25 pair
1788 bf 22,novr22 ; Do not save VR22...
1789 stvxl v22,br0,r13 ; Save VR22
1790
1791 novr22:
1792 bf 23,novr23 ; Do not save VR23...
1793 stvxl v23,r14,r13 ; Save VR23
1794
1795 novr23:
1796 la r21,savevr30(r3) ; Point to line 15
1797 bf 13,nol14 ; No line 14 to do...
1798 dcba br0,r11 ; Allocate cache line 14
1799
1800 nol14:
1801 la r13,savevr26(r3) ; Point to V26/V27 pair
1802 bf 24,novr24 ; Do not save VR24...
1803 stvxl v24,br0,r12 ; Save VR24
1804
1805 novr24:
1806 bf 25,novr25 ; Do not save VR25...
1807 stvxl v25,r14,r12 ; Save VR25
1808
1809 novr25:
1810 bf 15,nol15 ; No line 15 to do...
1811 dcba br0,r21 ; Allocate cache line 15
1812
1813 nol15:
1814 ;
1815 ; Note: All cache lines allocated now
1816 ;
1817 la r12,savevr28(r3) ; Point to V28/V29 pair
1818 bf 26,novr26 ; Do not save VR26...
1819 stvxl v26,br0,r13 ; Save VR26
1820
1821 novr26:
1822 bf 27,novr27 ; Do not save VR27...
1823 stvxl v27,r14,r13 ; Save VR27
1824
1825 novr27:
1826 la r13,savevr30(r3) ; Point to V30/V31 pair
1827 bf 28,novr28 ; Do not save VR28...
1828 stvxl v28,br0,r12 ; Save VR28
1829
1830 novr28:
1831 bf 29,novr29 ; Do not save VR29...
1832 stvxl v29,r14,r12 ; Save VR29
1833
1834 novr29:
1835 bf 30,novr30 ; Do not save VR30...
1836 stvxl v30,br0,r13 ; Save VR30
1837
1838 novr30:
1839 bf 31,novr31 ; Do not save VR31...
1840 stvxl v31,r14,r13 ; Save VR31
1841
1842 novr31:
1843
1844
1845
1846 ;
1847 ; The context is all saved now and the facility is free.
1848 ;
1849 ; If we do not we need to fill the registers with junk, because this level has
1850 ; never used them before and some thieving bastard could hack the old values
1851 ; of some thread! Just imagine what would happen if they could! Why, nothing
1852 ; would be safe! My God! It is terrifying!
1853 ;
1854 ; Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian)
1855 ; constant that we may need to fill unused vector registers.
1856 ;
1857
1858
1859
1860
1861 vsnosave: vspltisb v31,-10 ; Get 0xF6F6F6F6
1862 lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
1863 vspltisb v30,5 ; Get 0x05050505
1864 lwz r19,VMXcpu(r29) ; Get the last CPU we ran on
1865 vspltish v29,4 ; Get 0x00040004
1866 lwz r14,VMXsave(r29) ; Point to the top of the "new" context stack
1867 vrlb v31,v31,v30 ; Get 0xDEDEDEDE
1868
1869 stw r16,VMXcpu(r29) ; Claim context for us
1870 eieio
1871
1872 #if FPVECDBG
1873 lwz r13,VMXlevel(r29) ; (TEST/DEBUG)
1874 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1875 li r2,0x5F04 ; (TEST/DEBUG)
1876 mr r1,r15 ; (TEST/DEBUG)
1877 mr r3,r14 ; (TEST/DEBUG)
1878 mr r5,r13 ; (TEST/DEBUG)
1879 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1880 sc ; (TEST/DEBUG)
1881 #endif
1882
1883 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
1884 vspltisb v28,-2 ; Get 0xFEFEFEFE
1885 mulli r19,r19,ppSize ; Find offset to the owner per_proc
1886 vsubuhm v31,v31,v29 ; Get 0xDEDADEDA
1887 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
1888 vpkpx v30,v28,v3 ; Get 0x7FFF7FFF
1889 li r16,VMXowner ; Displacement to vector owner
1890 add r19,r18,r19 ; Point to the owner per_proc
1891 vrlb v31,v31,v29 ; Get 0xDEADDEAD
1892 li r0,0
1893
1894 vsinvothr: lwarx r18,r16,r19 ; Get the owner
1895 cmplw r18,r29 ; Does he still have this context?
1896 bne vsinvoths ; Nope...
1897 stwcx. r0,r16,r19 ; Try to invalidate it
1898 bne- vsinvothr ; Try again if there was a collision...
1899
1900
1901 vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
1902 vmrghh v31,v30,v31 ; Get 0x7FFFDEAD. V31 keeps this value until the bitter end
1903 stw r15,VMXlevel(r29) ; Set the "new" active level
1904 eieio
1905 stw r29,VMXowner(r26) ; Mark us as having the live context
1906
1907 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
1908
1909 lwz r3,SAVprev(r14) ; Get the previous context
1910 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
1911 cmplw r0,r15 ; Top level correct to load?
1912 bne- ProtectTheAmericanWay ; No, go initialize...
1913
1914 stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later)
1915
1916 #if FPVECDBG
1917 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1918 li r2,0x5F05 ; (TEST/DEBUG)
1919 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1920 sc ; (TEST/DEBUG)
1921 #endif
1922
1923 lwz r22,savevrsave(r25) ; Get the most current VRSAVE
1924 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
1925 lis r9,0x5555 ; Mask with odd bits set
1926 and r10,r10,r22 ; Figure out just what registers need to be loaded
1927 ori r9,r9,0x5555 ; Finish mask
1928 rlwinm r11,r10,1,0,31 ; Shift over 1
1929 or r12,r10,r11 ; After this, even bits show which lines to touch
1930 andc r13,r12,r9 ; Clear out odd bits
1931
1932 la r20,savevr0(r14) ; Point to line 0
1933 rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1934 la r21,savevr2(r3) ; Point to line 1
1935 or r3,r13,r3 ; Set the odd bits
1936 ; (bit 0 is line 0, bit 1 is line 8,
1937 ; bit 2 is line 1, bit 3 is line 9, etc.
1938 rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1939 mtcrf 255,r3 ; Load up the CRs
1940 mr r22,r20 ; Start registers off
1941 ;
1942 ; Load the new vector state
1943 ;
1944
1945 bf 0,lnol0 ; No line 0 to do...
1946 dcbt br0,r20 ; Touch cache line 0
1947
1948 lnol0:
1949 la r20,savevr4(r14) ; Point to line 2
1950 bf 2,lnol1 ; No line 1 to do...
1951 dcbt br0,r21 ; Touch cache line 1
1952
1953 lnol1:
1954 la r21,savevr6(r14) ; Point to line 3
1955 bf 4,lnol2 ; No line 2 to do...
1956 dcbt br0,r20 ; Touch cache line 2
1957
1958 lnol2:
1959 li r30,16 ; Get offset for odd registers
1960 bf 16,lnovr0 ; Do not restore VR0...
1961 lvxl v0,br0,r22 ; Restore VR0
1962
1963 lnovr0:
1964 la r23,savevr2(r14) ; Point to V2/V3 pair
1965 bf 17,lnovr1 ; Do not restore VR1...
1966 lvxl v1,r30,r22 ; Restore VR1
1967
1968 lnovr1:
1969 la r20,savevr8(r14) ; Point to line 4
1970 bf 6,lnol3 ; No line 3 to do...
1971 dcbt br0,r21 ; Touch cache line 3
1972
1973 lnol3:
1974 la r22,savevr4(r14) ; Point to V4/V5 pair
1975 bf 18,lnovr2 ; Do not restore VR2...
1976 lvxl v2,br0,r23 ; Restore VR2
1977
1978 lnovr2:
1979 bf 19,lnovr3 ; Do not restore VR3...
1980 lvxl v3,r30,r23 ; Restore VR3
1981
1982 lnovr3:
1983 ;
1984 ; Note: CR4 is now free
1985 ;
1986 la r21,savevr10(r14) ; Point to line 5
1987 bf 8,lnol4 ; No line 4 to do...
1988 dcbt br0,r20 ; Touch cache line 4
1989
1990 lnol4:
1991 la r23,savevr6(r14) ; Point to R6/R7 pair
1992 bf 20,lnovr4 ; Do not restore VR4...
1993 lvxl v4,br0,r22 ; Restore VR4
1994
1995 lnovr4:
1996 bf 21,lnovr5 ; Do not restore VR5...
1997 lvxl v5,r30,r22 ; Restore VR5
1998
1999 lnovr5:
2000 mtcrf 0x08,r10 ; Set CRs for registers 16-19
2001 la r20,savevr12(r14) ; Point to line 6
2002 bf 10,lnol5 ; No line 5 to do...
2003 dcbt br0,r21 ; Touch cache line 5
2004
2005 lnol5:
2006 la r22,savevr8(r14) ; Point to V8/V9 pair
2007 bf 22,lnovr6 ; Do not restore VR6...
2008 lvxl v6,br0,r23 ; Restore VR6
2009
2010 lnovr6:
2011 bf 23,lnovr7 ; Do not restore VR7...
2012 lvxl v7,r30,r23 ; Restore VR7
2013
2014 lnovr7:
2015 ;
2016 ; Note: CR5 is now free
2017 ;
2018 la r21,savevr14(r14) ; Point to line 7
2019 bf 12,lnol6 ; No line 6 to do...
2020 dcbt br0,r20 ; Touch cache line 6
2021
2022 lnol6:
2023 la r23,savevr10(r14) ; Point to V10/V11 pair
2024 bf 24,lnovr8 ; Do not restore VR8...
2025 lvxl v8,br0,r22 ; Restore VR8
2026
2027 lnovr8:
2028 bf 25,lnovr9 ; Do not save VR9...
2029 lvxl v9,r30,r22 ; Restore VR9
2030
2031 lnovr9:
2032 mtcrf 0x04,r10 ; Set CRs for registers 20-23
2033 la r20,savevr16(r14) ; Point to line 8
2034 bf 14,lnol7 ; No line 7 to do...
2035 dcbt br0,r21 ; Touch cache line 7
2036
2037 lnol7:
2038 la r22,savevr12(r14) ; Point to V12/V13 pair
2039 bf 26,lnovr10 ; Do not restore VR10...
2040 lvxl v10,br0,r23 ; Restore VR10
2041
2042 lnovr10:
2043 bf 27,lnovr11 ; Do not restore VR11...
2044 lvxl v11,r30,r23 ; Restore VR11
2045
2046 lnovr11:
2047
2048 ;
2049 ; Note: CR6 is now free
2050 ;
2051 la r21,savevr18(r14) ; Point to line 9
2052 bf 1,lnol8 ; No line 8 to do...
2053 dcbt br0,r20 ; Touch cache line 8
2054
2055 lnol8:
2056 la r23,savevr14(r14) ; Point to V14/V15 pair
2057 bf 28,lnovr12 ; Do not restore VR12...
2058 lvxl v12,br0,r22 ; Restore VR12
2059
2060 lnovr12:
2061 bf 29,lnovr13 ; Do not restore VR13...
2062 lvxl v13,r30,r22 ; Restore VR13
2063
2064 lnovr13:
2065 mtcrf 0x02,r10 ; Set CRs for registers 24-27
2066 la r20,savevr20(r14) ; Point to line 10
2067 bf 3,lnol9 ; No line 9 to do...
2068 dcbt br0,r21 ; Touch cache line 9
2069
2070 lnol9:
2071 la r22,savevr16(r14) ; Point to V16/V17 pair
2072 bf 30,lnovr14 ; Do not restore VR14...
2073 lvxl v14,br0,r23 ; Restore VR14
2074
2075 lnovr14:
2076 bf 31,lnovr15 ; Do not restore VR15...
2077 lvxl v15,r30,r23 ; Restore VR15
2078
2079 lnovr15:
2080 ;
2081 ; Note: CR7 is now free
2082 ;
2083 la r21,savevr22(r14) ; Point to line 11
2084 bf 5,lnol10 ; No line 10 to do...
2085 dcbt br0,r20 ; Touch cache line 10
2086
2087 lnol10:
2088 la r23,savevr18(r14) ; Point to V18/V19 pair
2089 bf 16,lnovr16 ; Do not restore VR16...
2090 lvxl v16,br0,r22 ; Restore VR16
2091
2092 lnovr16:
2093 bf 17,lnovr17 ; Do not restore VR17...
2094 lvxl v17,r30,r22 ; Restore VR17
2095
2096 lnovr17:
2097 mtcrf 0x01,r10 ; Set CRs for registers 28-31
2098 ;
2099 ; Note: All registers have been or are accounted for in CRs
2100 ;
2101 la r20,savevr24(r14) ; Point to line 12
2102 bf 7,lnol11 ; No line 11 to do...
2103 dcbt br0,r21 ; Touch cache line 11
2104
2105 lnol11:
2106 la r22,savevr20(r14) ; Point to V20/V21 pair
2107 bf 18,lnovr18 ; Do not restore VR18...
2108 lvxl v18,br0,r23 ; Restore VR18
2109
2110 lnovr18:
2111 bf 19,lnovr19 ; Do not restore VR19...
2112 lvxl v19,r30,r23 ; Restore VR19
2113
2114 lnovr19:
2115 la r21,savevr26(r14) ; Point to line 13
2116 bf 9,lnol12 ; No line 12 to do...
2117 dcbt br0,r20 ; Touch cache line 12
2118
2119 lnol12:
2120 la r23,savevr22(r14) ; Point to V22/V23 pair
2121 bf 20,lnovr20 ; Do not restore VR20...
2122 lvxl v20,br0,r22 ; Restore VR20
2123
2124 lnovr20:
2125 bf 21,lnovr21 ; Do not restore VR21...
2126 lvxl v21,r30,r22 ; Restore VR21
2127
2128 lnovr21:
2129 la r20,savevr28(r14) ; Point to line 14
2130 bf 11,lnol13 ; No line 13 to do...
2131 dcbt br0,r21 ; Touch cache line 13
2132
2133 lnol13:
2134 la r22,savevr24(r14) ; Point to V24/V25 pair
2135 bf 22,lnovr22 ; Do not restore VR22...
2136 lvxl v22,br0,r23 ; Restore VR22
2137
2138 lnovr22:
2139 bf 23,lnovr23 ; Do not restore VR23...
2140 lvxl v23,r30,r23 ; Restore VR23
2141
2142 lnovr23:
2143 la r21,savevr30(r14) ; Point to line 15
2144 bf 13,lnol14 ; No line 14 to do...
2145 dcbt br0,r20 ; Touch cache line 14
2146
2147 lnol14:
2148 la r23,savevr26(r14) ; Point to V26/V27 pair
2149 bf 24,lnovr24 ; Do not restore VR24...
2150 lvxl v24,br0,r22 ; Restore VR24
2151
2152 lnovr24:
2153 bf 25,lnovr25 ; Do not restore VR25...
2154 lvxl v25,r30,r22 ; Restore VR25
2155
2156 lnovr25:
2157 bf 15,lnol15 ; No line 15 to do...
2158 dcbt br0,r21 ; Touch cache line 15
2159
2160 lnol15:
2161 ;
2162 ; Note: All needed cache lines have been touched now
2163 ;
2164 la r22,savevr28(r14) ; Point to V28/V29 pair
2165 bf 26,lnovr26 ; Do not restore VR26...
2166 lvxl v26,br0,r23 ; Restore VR26
2167
2168 lnovr26:
2169 bf 27,lnovr27 ; Do not restore VR27...
2170 lvxl v27,r30,r23 ; Restore VR27
2171
2172 lnovr27:
2173 la r23,savevr30(r14) ; Point to V30/V31 pair
2174 bf 28,lnovr28 ; Do not restore VR28...
2175 lvxl v28,br0,r22 ; Restore VR28
2176
2177 lnovr28:
2178 bf 29,lnovr29 ; Do not restore VR29...
2179 lvxl v29,r30,r22 ; Restore VR29
2180
2181 lnovr29:
2182 bf 30,lnovr30 ; Do not restore VR30...
2183 lvxl v30,br0,r23 ; Restore VR30
2184
2185 lnovr30:
2186 ;
2187 ; Everything is restored now except for VR31. We need it to get
2188 ; the QNaNBarbarian value to put into idle vector registers.
2189 ; Note: V31 was set above to QNaNbarbarian
2190 ;
2191
2192 cmpwi r10,-1 ; Handle the quick case of all registers in use
2193 beq- mstlvr31 ; Not likely, but all are in use...
2194 mtcrf 255,r10 ; Get mask of valid registers
2195
2196 bt 0,ni0 ; Register is ok already...
2197 vor v0,v31,v31 ; Copy into the next register
2198 ni0:
2199 bt 1,ni1 ; Register is ok already...
2200 vor v1,v31,v31 ; Copy into the next register
2201 ni1:
2202 bt 2,ni2 ; Register is ok already...
2203 vor v2,v31,v31 ; Copy into the next register
2204 ni2:
2205 bt 3,ni3 ; Register is ok already...
2206 vor v3,v31,v31 ; Copy into the next register
2207 ni3:
2208 bt 4,ni4 ; Register is ok already...
2209 vor v4,v31,v31 ; Copy into the next register
2210 ni4:
2211 bt 5,ni5 ; Register is ok already...
2212 vor v5,v31,v31 ; Copy into the next register
2213 ni5:
2214 bt 6,ni6 ; Register is ok already...
2215 vor v6,v31,v31 ; Copy into the next register
2216 ni6:
2217 bt 7,ni7 ; Register is ok already...
2218 vor v7,v31,v31 ; Copy into the next register
2219 ni7:
2220 bt 8,ni8 ; Register is ok already...
2221 vor v8,v31,v31 ; Copy into the next register
2222 ni8:
2223 bt 9,ni9 ; Register is ok already...
2224 vor v9,v31,v31 ; Copy into the next register
2225 ni9:
2226 bt 10,ni10 ; Register is ok already...
2227 vor v10,v31,v31 ; Copy into the next register
2228 ni10:
2229 bt 11,ni11 ; Register is ok already...
2230 vor v11,v31,v31 ; Copy into the next register
2231 ni11:
2232 bt 12,ni12 ; Register is ok already...
2233 vor v12,v31,v31 ; Copy into the next register
2234 ni12:
2235 bt 13,ni13 ; Register is ok already...
2236 vor v13,v31,v31 ; Copy into the next register
2237 ni13:
2238 bt 14,ni14 ; Register is ok already...
2239 vor v14,v31,v31 ; Copy into the next register
2240 ni14:
2241 bt 15,ni15 ; Register is ok already...
2242 vor v15,v31,v31 ; Copy into the next register
2243 ni15:
2244 bt 16,ni16 ; Register is ok already...
2245 vor v16,v31,v31 ; Copy into the next register
2246 ni16:
2247 bt 17,ni17 ; Register is ok already...
2248 vor v17,v31,v31 ; Copy into the next register
2249 ni17:
2250 bt 18,ni18 ; Register is ok already...
2251 vor v18,v31,v31 ; Copy into the next register
2252 ni18:
2253 bt 19,ni19 ; Register is ok already...
2254 vor v19,v31,v31 ; Copy into the next register
2255 ni19:
2256 bt 20,ni20 ; Register is ok already...
2257 vor v20,v31,v31 ; Copy into the next register
2258 ni20:
2259 bt 21,ni21 ; Register is ok already...
2260 vor v21,v31,v31 ; Copy into the next register
2261 ni21:
2262 bt 22,ni22 ; Register is ok already...
2263 vor v22,v31,v31 ; Copy into the next register
2264 ni22:
2265 bt 23,ni23 ; Register is ok already...
2266 vor v23,v31,v31 ; Copy into the next register
2267 ni23:
2268 bt 24,ni24 ; Register is ok already...
2269 vor v24,v31,v31 ; Copy into the next register
2270 ni24:
2271 bt 25,ni25 ; Register is ok already...
2272 vor v25,v31,v31 ; Copy into the next register
2273 ni25:
2274 bt 26,ni26 ; Register is ok already...
2275 vor v26,v31,v31 ; Copy into the next register
2276 ni26:
2277 bt 27,ni27 ; Register is ok already...
2278 vor v27,v31,v31 ; Copy into the next register
2279 ni27:
2280 bt 28,ni28 ; Register is ok already...
2281 vor v28,v31,v31 ; Copy into the next register
2282 ni28:
2283 bt 29,ni29 ; Register is ok already...
2284 vor v29,v31,v31 ; Copy into the next register
2285 ni29:
2286 bt 30,ni30 ; Register is ok already...
2287 vor v30,v31,v31 ; Copy into the next register
2288 ni30:
2289 bf 31,lnovr31 ; V31 is empty, no need to restore...
2290
2291 mstlvr31: lvxl v31,r30,r23 ; Restore VR31
2292
2293 lnovr31: mr r3,r14 ; Get the old savearea (we popped it before)
2294 bl EXT(save_ret) ; Toss it
2295
2296 vrenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
2297 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
2298 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
2299 lwz r10,ACT_MACT_SPF(r17) ; Get the act special flags
2300 lwz r11,spcFlags(r26) ; Get per_proc spec flags cause not in sync with act
2301 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
2302 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2303 oris r11,r11,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2304 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
2305 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
2306 xor r3,r25,r5 ; Get the real address of the savearea
2307 beq- vrnuser ; We are not user state...
2308 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
2309 stw r11,spcFlags(r26) ; Set per_proc copy
2310
2311 vrnuser:
2312 #if FPVECDBG
2313 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2314 li r2,0x5F07 ; (TEST/DEBUG)
2315 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2316 sc ; (TEST/DEBUG)
2317 #endif
2318 b EXT(exception_exit) ; Exit to the fray...
2319
2320 /*
2321 * Initialize the registers to some bogus value
2322 */
2323
2324 ProtectTheAmericanWay:
2325
2326 #if FPVECDBG
2327 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2328 li r2,0x5F06 ; (TEST/DEBUG)
2329 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2330 sc ; (TEST/DEBUG)
2331 #endif
2332
2333 vor v0,v31,v31 ; Copy into the next register
2334 vor v1,v31,v31 ; Copy into the next register
2335 vor v2,v31,v31 ; Copy into the next register
2336 vor v3,v31,v31 ; Copy into the next register
2337 vor v4,v31,v31 ; Copy into the next register
2338 vor v5,v31,v31 ; Copy into the next register
2339 vor v6,v31,v31 ; Copy into the next register
2340 vor v7,v31,v31 ; Copy into the next register
2341 vor v8,v31,v31 ; Copy into the next register
2342 vor v9,v31,v31 ; Copy into the next register
2343 vor v10,v31,v31 ; Copy into the next register
2344 vor v11,v31,v31 ; Copy into the next register
2345 vor v12,v31,v31 ; Copy into the next register
2346 vor v13,v31,v31 ; Copy into the next register
2347 vor v14,v31,v31 ; Copy into the next register
2348 vor v15,v31,v31 ; Copy into the next register
2349 vor v16,v31,v31 ; Copy into the next register
2350 vor v17,v31,v31 ; Copy into the next register
2351 vor v18,v31,v31 ; Copy into the next register
2352 vor v19,v31,v31 ; Copy into the next register
2353 vor v20,v31,v31 ; Copy into the next register
2354 vor v21,v31,v31 ; Copy into the next register
2355 vor v22,v31,v31 ; Copy into the next register
2356 vor v23,v31,v31 ; Copy into the next register
2357 vor v24,v31,v31 ; Copy into the next register
2358 vor v25,v31,v31 ; Copy into the next register
2359 vor v26,v31,v31 ; Copy into the next register
2360 vor v27,v31,v31 ; Copy into the next register
2361 vor v28,v31,v31 ; Copy into the next register
2362 vor v29,v31,v31 ; Copy into the next register
2363 vor v30,v31,v31 ; Copy into the next register
2364 b vrenable ; Finish setting it all up...
2365
2366
2367
2368 ;
2369 ; We get here when we are switching to the same context at the same level and the context
2370 ; is still live. Essentially, all we are doing is turning on the faility. It may have
2371 ; gotten turned off due to doing a context save for the current level or a context switch
2372 ; back to the live guy.
2373 ;
2374
2375 .align 5
2376
2377 vsthesame:
2378
2379 #if FPVECDBG
2380 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2381 li r2,0x5F0A ; (TEST/DEBUG)
2382 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2383 sc ; (TEST/DEBUG)
2384 #endif
2385 beq- cr1,vrenable ; Not saved yet, nothing to pop, go enable and exit...
2386
2387 lwz r11,SAVlevel(r30) ; Get the level of top saved context
2388 lwz r14,SAVprev(r30) ; Get the previous savearea
2389
2390 cmplw r11,r31 ; Are live and saved the same?
2391
2392 bne+ vrenable ; Level not the same, nothing to pop, go enable and exit...
2393
2394 mr r3,r30 ; Get the old savearea (we popped it before)
2395 bl EXT(save_ret) ; Toss it
2396 b vrenable ; Go enable and exit...
2397
2398
2399 ;
2400 ; This function invalidates any live vector context for the passed in facility_context.
2401 ; This is intended to be called just before act_machine_sv_free tosses saveareas.
2402 ;
2403
2404 .align 5
2405 .globl EXT(toss_live_vec)
2406
2407 LEXT(toss_live_vec)
2408
2409 mfmsr r9 ; Get the MSR
2410 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
2411 rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now?
2412 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vector is turned off
2413 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure fpu is turned off
2414 mtmsr r0 ; No interruptions
2415 isync
2416 beq+ tlvnotours ; Vector off, can not be live here...
2417
2418 mfsprg r8,0 ; Get the per proc
2419
2420 ;
2421 ; Note that at this point, since vecs are on, we are the owner
2422 ; of live state on this processor
2423 ;
2424
2425 lwz r6,VMXowner(r8) ; Get the thread that owns the vector
2426 li r0,0 ; Clear this just in case we need it
2427 cmplw r6,r3 ; Are we tossing our own context?
2428 bne- tlvnotours ; Nope...
2429
2430 vspltish v1,1 ; Turn on the non-Java bit and saturate
2431 vspltisw v0,1 ; Turn on the saturate bit
2432 vxor v1,v1,v0 ; Turn off saturate
2433 mtspr vrsave,r0 ; Clear VRSAVE
2434 mtvscr v1 ; Set the non-java, no saturate status
2435
2436 tlvnotours: lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2437 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2438 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2439 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2440 li r10,VMXowner ; Displacement to vector owner
2441 add r11,r12,r11 ; Point to the owner per_proc
2442 li r0,0 ; Set a 0 to invalidate context
2443
2444 tlvinvothr: lwarx r12,r10,r11 ; Get the owner
2445 cmplw r12,r3 ; Does he still have this context?
2446 bne+ tlvexit ; Nope, leave...
2447 stwcx. r0,r10,r11 ; Try to invalidate it
2448 bne- tlvinvothr ; Try again if there was a collision...
2449
2450 tlvexit: mtmsr r9 ; Restore interruptions
2451 isync ; Could be turning off vectors here
2452 blr ; Leave....
2453
2454 #if 0
2455 ;
2456 ; This function invalidates any live vector context for the passed in facility_context
2457 ; if the level is current. It also tosses the corresponding savearea if there is one.
2458 ; This function is primarily used whenever we detect a VRSave that is all zeros.
2459 ;
2460
2461 .align 5
2462 .globl EXT(vec_trash)
2463
2464 LEXT(vec_trash)
2465
2466 lwz r12,facAct(r3) ; Get the activation
2467 lwz r11,VMXlevel(r3) ; Get the context level
2468 lwz r10,ACT_MACT_PCB(r12) ; Grab the current level for the thread
2469 lwz r9,VMXsave(r3) ; Get the savearea, if any
2470 cmplw r10,r11 ; Are we at the right level?
2471 cmplwi cr1,r9,0 ; Remember if there is a savearea
2472 bnelr+ ; No, we do nothing...
2473
2474 lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2475 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2476 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2477 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2478 li r10,VMXowner ; Displacement to vector owner
2479 add r11,r12,r11 ; Point to the owner per_proc
2480 li r0,0 ; Set a 0 to invalidate context
2481
2482 vtinvothr: lwarx r12,r10,r11 ; Get the owner
2483 cmplw r12,r3 ; Does he still have this context?
2484 bne vtnotlive ; Nope, not live anywhere...
2485 stwcx. r0,r10,r11 ; Try to invalidate it
2486 bne- vtinvothr ; Try again if there was a collision...
2487
2488 vtnotlive: beqlr+ cr1 ; Leave if there is no savearea
2489 lwz r8,SAVlevel(r9) ; Get the level of the savearea
2490 cmplw r8,r11 ; Savearea for the current level?
2491 bnelr+ ; No, nothing to release...
2492
2493 lwz r8,SAVprev(r9) ; Pick up the previous area
2494 mr. r8,r8 ; Is there a previous?
2495 beq- vtnoprev ; Nope...
2496 lwz r7,SAVlevel(r8) ; Get the level associated with save
2497
2498 vtnoprev: stw r8,VMXsave(r3) ; Dequeue this savearea
2499 stw r7,VMXlevel(r3) ; Pop the level
2500
2501 mr r3,r9 ; Get the savearea to release
2502 b EXT(save_ret) ; Go and toss the save area (note, we will return from there)...
2503 #endif
2504
2505 ;
2506 ; Just some test code to force vector and/or floating point in the kernel
2507 ;
2508
2509 .align 5
2510 .globl EXT(fctx_test)
2511
2512 LEXT(fctx_test)
2513
2514 mfsprg r3,0 ; Get the per_proc block
2515 lwz r3,PP_ACTIVE_THREAD(r3) ; Get the thread pointer
2516 mr. r3,r3 ; Are we actually up and running?
2517 beqlr- ; No...
2518
2519 fmr f0,f0 ; Use floating point
2520 mftb r4 ; Get time base for a random number
2521 li r5,1 ; Get a potential vrsave to use
2522 andi. r4,r4,0x3F ; Get a number from 0 - 63
2523 slw r5,r5,r4 ; Choose a register to save (should be 0 half the time)
2524 mtspr vrsave,r5 ; Set VRSave
2525 vor v0,v0,v0 ; Use vectors
2526 blr