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