]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/cswtch.s
xnu-344.23.tar.gz
[apple/xnu.git] / osfmk / ppc / cswtch.s
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
de355530
A
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.
1c79356b 11 *
de355530
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
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.
1c79356b
A
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>
9bccf70c 33#include <ppc/savearea.h>
1c79356b
A
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
9bccf70c
A
50 .align 5
51 .globl EXT(load_context)
52
53LEXT(load_context)
54
55 .globl EXT(Load_context)
56
57LEXT(Load_context)
1c79356b
A
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
de355530 62 e worry about saving its frame, hence we can reset the istackptr
1c79356b
A
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)
1c79356b 74 stw r0,PP_ISTACKPTR(r6)
9bccf70c 75 stw r3,PP_ACTIVE_THREAD(r6)
1c79356b
A
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 */
de355530 82 mtsprg 1,r9
1c79356b
A
83 stw r1,0(r12)
84 li r0,0 /* Clear a register */
de355530
A
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 */
1c79356b 88 mfmsr r5 /* Since we are passing control, get our MSR values */
de355530
A
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 */
1c79356b 92 stw r0,FM_BACKPTR(r1) /* zero backptr */
de355530
A
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 */
1c79356b
A
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
9bccf70c
A
110 .align 5
111 .globl EXT(Call_continuation)
112
113LEXT(Call_continuation)
114
115 mtlr r3
116 mr r1, r4 /* Load new stack pointer */
117 blr /* Jump to the continuation */
1c79356b
A
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.
de355530
A
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.
1c79356b
A
126 */
127
128/* Context switches are double jumps. We pass the following to the
129 * context switch firmware call:
130 *
de355530 131 * R3 = switchee's savearea
1c79356b
A
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
9bccf70c
A
141 .align 5
142 .globl EXT(Switch_context)
1c79356b 143
9bccf70c
A
144LEXT(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
1c79356b 148#if DEBUG
de355530
A
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
1c79356b
A
152 BREAKPOINT_TRAP
153notonintstack:
154#endif
de355530
A
155 stw r4,THREAD_CONTINUATION(r3) ; Set continuation into the thread
156 cmpwi cr1,r4,0 ; used waaaay down below
9bccf70c 157 lwz r7,0(r10) ; Get the current stack
de355530
A
158/*
159 * Make the new thread the current thread.
160 */
161
9bccf70c 162 stw r7,THREAD_KERNEL_STACK(r3) ; Remember the current stack in the thread (do not need???)
de355530
A
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
1c79356b 169 lwz r7,CTHREAD_SELF(r5) ; Pick up the user assist word
de355530
A
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)
178nnnn: ; (TEST/DEBUG)
179#endif
9bccf70c 180
de355530 181 stw r11,0(r10) ; Save the new kernel stack address
9bccf70c 182 stw r7,UAW(r12) ; Save the assist word for the "ultra fast path"
de355530
A
183
184 lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment
185
1c79356b
A
186 lwz r7,ACT_MACT_SPF(r5) ; Get the special flags
187
de355530 188 lwz r10,ACT_KLOADED(r5)
9bccf70c 189 stw r11,ppbbTaskEnv(r12) ; Save the bb task env
de355530
A
190 li r0,0
191 cmpwi cr0,r10,0
192 lwz r10,PP_ACTIVE_KLOADED(r12)
9bccf70c 193 stw r7,spcFlags(r12) ; Set per_proc copy of the special flags
de355530 194 beq cr0,.L_sw_ctx_not_kld
1c79356b 195
de355530
A
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
1c79356b 208 lis r0,hi16(CutTrace) ; Trace FW call
de355530 209 mr. r10,r10 ; Any tracing going on?
1c79356b 210 ori r0,r0,lo16(CutTrace) ; Trace FW call
de355530 211 beq+ cswNoTrc ; No trace today, dude...
1c79356b
A
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
de355530
A
218cswNoTrc: 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
9bccf70c
A
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?
de355530 233 bne+ cswnofloat ; Float is not ours...
9bccf70c
A
234
235 cmplw r10,r11 ; Is the level the same?
236 lwz r5,FPUcpu(r2) ; Get the owning cpu
de355530 237 bne+ cswnofloat ; Level not the same, this is not live...
9bccf70c
A
238
239 cmplw r5,r0 ; Still owned by this cpu?
240 lwz r10,FPUsave(r2) ; Get the level
de355530 241 bne+ cswnofloat ; CPU claimed by someone else...
9bccf70c
A
242
243 mr. r10,r10 ; Is there a savearea here?
244 ori r6,r6,lo16(MASK(MSR_FP)) ; Enable floating point
245
de355530 246 beq- cswnofloat ; No savearea to check...
9bccf70c
A
247
248 lwz r3,SAVlevel(r10) ; Get the level
de355530 249 lwz r5,SAVprev(r10) ; Get the previous of this savearea
9bccf70c
A
250 cmplw r3,r11 ; Is it for the current level?
251
de355530 252 bne+ cswnofloat ; Nope...
9bccf70c
A
253
254 stw r5,FPUsave(r2) ; Pop off this savearea
de355530
A
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
9bccf70c
A
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
de355530
A
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
276cswfpudq: 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
281cswnofloat: bne+ cr5,cswnovect ; Vector is not ours...
9bccf70c
A
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
de355530 287 bne+ cswnovect ; Level not the same, this is not live...
9bccf70c
A
288
289 cmplw r5,r0 ; Still owned by this cpu?
290 lwz r10,VMXsave(r2) ; Get the level
de355530 291 bne+ cswnovect ; CPU claimed by someone else...
9bccf70c
A
292
293 mr. r10,r10 ; Is there a savearea here?
294 oris r6,r6,hi16(MASK(MSR_VEC)) ; Enable vector
295
de355530 296 beq- cswnovect ; No savearea to check...
9bccf70c
A
297
298 lwz r3,SAVlevel(r10) ; Get the level
de355530 299 lwz r5,SAVprev(r10) ; Get the previous of this savearea
9bccf70c
A
300 cmplw r3,r11 ; Is it for the current level?
301
de355530 302 bne+ cswnovect ; Nope...
9bccf70c
A
303
304 stw r5,VMXsave(r2) ; Pop off this savearea
de355530
A
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
9bccf70c
A
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
de355530
A
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;
9bccf70c 324
de355530
A
325cswvecdq: 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
330cswnovect: 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 */
9bccf70c 333 lis r0,hi16(SwitchContextCall) /* Top part of switch context */
de355530
A
334 stw r9,savesrr0(r8) /* Make us jump to the switch in routine */
335
1c79356b 336 li r10,MSR_SUPERVISOR_INT_OFF /* Get the switcher's MSR */
de355530
A
337 lwz r9,SAVflags(r8) /* Get the flags */
338 stw r10,savesrr1(r8) /* Set up for switch in */
d7e50217 339 rlwinm r9,r9,0,15,13 /* Reset the syscall flag */
de355530
A
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 */
1c79356b 342 stw r9,SAVflags(r8) /* Set the flags */
9bccf70c
A
343
344 bne cr1,swtchtocont ; Switch to the continuation
1c79356b
A
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 */
9bccf70c
A
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
1c79356b 361
9bccf70c 362swtchtocont:
de355530
A
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
9bccf70c
A
366
367 b EXT(exception_exit) ; Blocking on continuation, toss old context...
1c79356b
A
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 *
de355530 378 * R3 = switcher's savearea
1c79356b
A
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
9bccf70c
A
386
387 .align 5
388 .globl EXT(switch_in)
389
390LEXT(switch_in)
d7e50217 391
de355530
A
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 */
1c79356b 397
de355530
A
398 stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */
399 stw r10,SAVprev(r3) /* Chain on the old one */
1c79356b 400
de355530
A
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
1c79356b
A
414
415
416
417/*
9bccf70c 418 * void fpu_save(facility_context ctx)
1c79356b 419 *
9bccf70c
A
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.
1c79356b 425 */
9bccf70c
A
426 .align 5
427 .globl EXT(fpu_save)
1c79356b 428
9bccf70c
A
429LEXT(fpu_save)
430
431
432 mfmsr r0 ; Get the MSR
de355530
A
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
9bccf70c 435 ori r2,r2,MASK(MSR_FP) ; Enable the floating point feature for now also
de355530 436 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
9bccf70c 437 mtmsr r2 ; Set the MSR
1c79356b 438 isync
9bccf70c
A
439
440 mfsprg r6,0 ; Get the per_processor block
441 lwz r12,FPUowner(r6) ; Get the context ID for owner
442
1c79356b 443#if FPVECDBG
9bccf70c
A
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)
de355530 451 beq- noowneryet ; (TEST/DEBUG)
9bccf70c
A
452 lwz r4,FPUlevel(r12) ; (TEST/DEBUG)
453 lwz r5,FPUsave(r12) ; (TEST/DEBUG)
454
455noowneryet: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
456 sc ; (TEST/DEBUG)
457 mr r0,r7 ; (TEST/DEBUG)
458 mr r3,r10 ; (TEST/DEBUG)
1c79356b 459#endif
9bccf70c
A
460 mflr r2 ; Save the return address
461
462fsretry: mr. r12,r12 ; Anyone own the FPU?
463 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
de355530 464 beq- fsret ; Nobody owns the FPU, no save required...
1c79356b 465
9bccf70c 466 cmplw cr1,r3,r12 ; Is the specified context live?
1c79356b 467
9bccf70c 468 isync ; Force owner check first
1c79356b 469
9bccf70c 470 lwz r9,FPUcpu(r12) ; Get the cpu that context was last on
de355530 471 bne- cr1,fsret ; No, it is not...
1c79356b 472
9bccf70c 473 cmplw cr1,r9,r11 ; Was the context for this processor?
de355530 474 beq- cr1,fsgoodcpu ; Facility last used on this processor...
0b4e3aa0 475
9bccf70c 476 b fsret ; Someone else claimed it...
1c79356b 477
9bccf70c 478 .align 5
1c79356b 479
9bccf70c
A
480fsgoodcpu: lwz r3,FPUsave(r12) ; Get the current FPU savearea for the thread
481 lwz r9,FPUlevel(r12) ; Get our current level indicator
1c79356b 482
9bccf70c
A
483 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
484 beq- cr1,fsneedone ; Never saved it, so go do it...
1c79356b 485
9bccf70c
A
486 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
487 cmplw cr1,r9,r8 ; Correct level?
de355530 488 beq- cr1,fsret ; The current level is already saved, bail out...
1c79356b 489
9bccf70c
A
490fsneedone: 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...
de355530 497 beq- fsbackout ; If disowned, just toss savearea...
9bccf70c 498 lwz r4,facAct(r12) ; Get the activation associated with live context
de355530 499 mtlr r2 ; Restore return
9bccf70c
A
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
de355530 504 stw r8,SAVprev(r3) ; And then chain this in front
1c79356b 505
9bccf70c 506 stw r9,SAVlevel(r3) ; Show level in savearea
1c79356b 507
de355530
A
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
9bccf70c 562fsret: mtmsr r0 ; Put interrupts on if they were and floating point off
1c79356b
A
563 isync
564
565 blr
566
de355530
A
567fsbackout: mr r12,r0 ; Save the original MSR
568 b EXT(save_ret_join) ; Toss savearea and return from there...
9bccf70c 569
1c79356b
A
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
9bccf70c
A
588 .align 5
589 .globl EXT(fpu_switch)
590
591LEXT(fpu_switch)
592
1c79356b 593#if DEBUG
1c79356b
A
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)
1c79356b
A
599#endif /* DEBUG */
600
9bccf70c
A
601 mfsprg r26,0 ; Get the per_processor block
602 mfmsr r19 ; Get the current MSR
1c79356b 603
9bccf70c
A
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
1c79356b 609
9bccf70c 610 mtmsr r19 ; Enable floating point instructions
1c79356b 611 isync
1c79356b 612
9bccf70c
A
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
0b4e3aa0 615
9bccf70c
A
616; R22 has the "old" context anchor
617; R29 has the "new" context anchor
0b4e3aa0 618
1c79356b 619#if FPVECDBG
9bccf70c
A
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)
1c79356b 626#endif
9bccf70c
A
627
628 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
1c79356b 629
9bccf70c 630fswretry: mr. r22,r22 ; See if there is any live FP status
1c79356b 631
9bccf70c 632 beq- fsnosave ; No live context, so nothing to save...
1c79356b 633
9bccf70c 634 isync ; Make sure we see this in the right order
1c79356b 635
9bccf70c
A
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
1c79356b 642
9bccf70c
A
643 bne- fsnosave ; No, not on the same processor...
644
1c79356b 645;
9bccf70c
A
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.
1c79356b 649;
9bccf70c
A
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
1c79356b 654
9bccf70c
A
655 beq- fsthesame ; New and old are the same, just go enable...
656
657 beq- cr1,fsmstsave ; Not saved yet, go do it...
1c79356b 658
9bccf70c 659 lwz r11,SAVlevel(r30) ; Get the level of top saved context
1c79356b 660
9bccf70c
A
661 cmplw r31,r11 ; Are live and saved the same?
662
1c79356b 663#if FPVECDBG
9bccf70c
A
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)
1c79356b 670#endif
9bccf70c
A
671
672 beq+ fsnosave ; Same level, so already saved...
673
1c79356b 674
9bccf70c
A
675fsmstsave: 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
de355530
A
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
d7e50217 682 stw r3,FPUsave(r22) ; Set this as the latest context savearea for the thread
de355530
A
683
684 stw r30,SAVprev(r3) ; Point us to the old context
9bccf70c
A
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
1c79356b 689
1c79356b 690#if FPVECDBG
9bccf70c
A
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)
1c79356b
A
695#endif
696
de355530
A
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)
1c79356b 749
1c79356b
A
750;
751; The context is all saved now and the facility is free.
752;
9bccf70c 753; If we do not we need to fill the registers with junk, because this level has
1c79356b
A
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
0b4e3aa0 759
9bccf70c
A
760fsnosave: 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
0b4e3aa0 763
9bccf70c
A
764 stw r16,FPUcpu(r29) ; Claim context for us
765 eieio
0b4e3aa0 766
1c79356b 767#if FPVECDBG
9bccf70c
A
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)
1c79356b 776#endif
9bccf70c
A
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
de355530 783 li r0,0
9bccf70c
A
784
785fsinvothr: lwarx r18,r16,r19 ; Get the owner
de355530
A
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...
9bccf70c 790
de355530 791fsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
9bccf70c
A
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
1c79356b 796
de355530 797 beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load...
9bccf70c
A
798
799 dcbt 0,r11 ; Touch line in
800
de355530 801 lwz r3,SAVprev(r14) ; Get the previous context
9bccf70c
A
802 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
803 cmplw r0,r15 ; Top level correct to load?
de355530 804 bne- MakeSureThatNoTerroristsCanHurtUsByGod ; No, go initialize...
9bccf70c
A
805
806 stw r3,FPUsave(r29) ; Pop the context (we will toss the savearea later)
1c79356b
A
807
808#if FPVECDBG
9bccf70c
A
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)
1c79356b
A
813#endif
814
9bccf70c
A
815 la r11,savefp4(r14) ; Point to next line
816 dcbt 0,r11 ; Touch line in
1c79356b
A
817 lfd f0, savefp0(r14)
818 lfd f1,savefp1(r14)
1c79356b 819 lfd f2,savefp2(r14)
9bccf70c 820 la r11,savefp8(r14) ; Point to next line
1c79356b 821 lfd f3,savefp3(r14)
9bccf70c 822 dcbt 0,r11 ; Touch line in
1c79356b
A
823 lfd f4,savefp4(r14)
824 lfd f5,savefp5(r14)
825 lfd f6,savefp6(r14)
9bccf70c 826 la r11,savefp12(r14) ; Point to next line
1c79356b 827 lfd f7,savefp7(r14)
9bccf70c 828 dcbt 0,r11 ; Touch line in
1c79356b
A
829 lfd f8,savefp8(r14)
830 lfd f9,savefp9(r14)
831 lfd f10,savefp10(r14)
9bccf70c 832 la r11,savefp16(r14) ; Point to next line
1c79356b 833 lfd f11,savefp11(r14)
9bccf70c 834 dcbt 0,r11 ; Touch line in
1c79356b
A
835 lfd f12,savefp12(r14)
836 lfd f13,savefp13(r14)
837 lfd f14,savefp14(r14)
9bccf70c 838 la r11,savefp20(r14) ; Point to next line
1c79356b 839 lfd f15,savefp15(r14)
9bccf70c 840 dcbt 0,r11 ; Touch line in
1c79356b
A
841 lfd f16,savefp16(r14)
842 lfd f17,savefp17(r14)
843 lfd f18,savefp18(r14)
9bccf70c 844 la r11,savefp24(r14) ; Point to next line
1c79356b 845 lfd f19,savefp19(r14)
9bccf70c 846 dcbt 0,r11 ; Touch line in
1c79356b
A
847 lfd f20,savefp20(r14)
848 lfd f21,savefp21(r14)
9bccf70c 849 la r11,savefp28(r14) ; Point to next line
1c79356b
A
850 lfd f22,savefp22(r14)
851 lfd f23,savefp23(r14)
9bccf70c 852 dcbt 0,r11 ; Touch line in
1c79356b
A
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
9bccf70c
A
862 mr r3,r14 ; Get the old savearea (we popped it before)
863 bl EXT(save_ret) ; Toss it
864
de355530
A
865fsenable: 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
9bccf70c 867 ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature
d7e50217
A
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
de355530 870 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
1c79356b 871 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
d7e50217 872 oris r11,r11,hi16(floatUsed|floatCng) ; Set that we used floating point
9bccf70c 873 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
de355530
A
874 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
875 xor r3,r25,r5 ; Get the real address of the savearea
b4c24cb9 876 beq- fsnuser ; We are not user state...
9bccf70c 877 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
d7e50217 878 stw r11,spcFlags(r26) ; Set per_proc copy
1c79356b
A
879
880fsnuser:
881#if FPVECDBG
9bccf70c
A
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)
1c79356b 886#endif
1c79356b 887
9bccf70c 888 b EXT(exception_exit) ; Exit to the fray...
1c79356b
A
889
890/*
891 * Initialize the registers to some bogus value
892 */
893
894MakeSureThatNoTerroristsCanHurtUsByGod:
0b4e3aa0 895
1c79356b 896#if FPVECDBG
9bccf70c
A
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)
1c79356b 901#endif
9bccf70c
A
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
1c79356b
A
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
1c79356b
A
922 fmr f18,f0
923 fmr f19,f0
924 fmr f20,f0
1c79356b
A
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
9bccf70c
A
936 b fsenable ; Finish setting it all up...
937
1c79356b
A
938
939;
9bccf70c
A
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.
1c79356b 944;
9bccf70c
A
945
946 .align 5
1c79356b 947
9bccf70c 948fsthesame:
1c79356b 949
9bccf70c
A
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...
1c79356b 957
9bccf70c 958 lwz r11,SAVlevel(r30) ; Get the level of top saved context
de355530 959 lwz r14,SAVprev(r30) ; Get the previous savearea
1c79356b 960
9bccf70c 961 cmplw r11,r31 ; Are live and saved the same?
1c79356b 962
9bccf70c 963 bne+ fsenable ; Level not the same, nothing to pop, go enable and exit...
1c79356b 964
9bccf70c
A
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
978LEXT(toss_live_fpu)
979
de355530 980
9bccf70c 981 mfmsr r9 ; Get the MSR
de355530 982 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
9bccf70c 983 rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now?
de355530
A
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
9bccf70c
A
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
1c79356b 995;
9bccf70c
A
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?
de355530 1000 bne- tlfnotours ; Nope...
9bccf70c 1001
de355530 1002 fsub f1,f1,f1 ; Make a 0
9bccf70c
A
1003 mtfsf 0xFF,f1 ; Clear it
1004
1005tlfnotours: 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
de355530 1011 li r0,0 ; Set a 0 to invalidate context
9bccf70c
A
1012
1013tlfinvothr: lwarx r12,r10,r11 ; Get the owner
de355530
A
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...
9bccf70c 1018
de355530 1019tlfexit: mtmsr r9 ; Restore interruptions
9bccf70c
A
1020 isync ; Could be turning off floats here
1021 blr ; Leave...
1022
1c79356b
A
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 *
9bccf70c
A
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 *
1c79356b
A
1045 */
1046
9bccf70c
A
1047 .align 5
1048 .globl EXT(vec_save)
1049
1050LEXT(vec_save)
1c79356b 1051
9bccf70c 1052 mfmsr r0 ; Get the MSR
de355530
A
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
9bccf70c 1055 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
de355530 1056 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp
9bccf70c 1057 mtmsr r2 ; Set the MSR
1c79356b
A
1058 isync
1059
9bccf70c
A
1060 mfsprg r6,0 ; Get the per_processor block
1061 lwz r12,VMXowner(r6) ; Get the context ID for owner
1062
1c79356b 1063#if FPVECDBG
9bccf70c
A
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
1075noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1076 sc ; (TEST/DEBUG)
1077 mr r0,r7 ; (TEST/DEBUG)
1078 mr r3,r10 ; (TEST/DEBUG)
1c79356b 1079#endif
9bccf70c
A
1080 mflr r2 ; Save the return address
1081
1082vsretry: 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
1100vsgoodcpu: 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...
1c79356b 1112
9bccf70c 1113 bne+ vsret ; VRsave is non-zero so we need to keep what is saved...
0b4e3aa0 1114
de355530 1115 lwz r4,SAVprev(r3) ; Pick up the previous area
9bccf70c
A
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
de355530
A
1120 li r3,0 ; Clear
1121 stw r3,VMXowner(r12) ; Show no live context here
9bccf70c
A
1122 eieio
1123
de355530
A
1124vsbackout: mr r12,r0 ; Set the saved MSR
1125 b EXT(save_ret_join) ; Toss the savearea and return from there...
9bccf70c
A
1126
1127 .align 5
1128
1129vsneedone: 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
de355530 1141 mtlr r2 ; Restore return
9bccf70c
A
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
de355530 1146 stw r8,SAVprev(r3) ; And then chain this in front
9bccf70c
A
1147
1148 stw r9,SAVlevel(r3) ; Set level in savearea
1149
de355530
A
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
1176snol0:
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
1181snol1:
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
1186snol2:
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
1191snovr0:
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
1196snovr1:
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
1201snol3:
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
1206snovr2:
1207 bf 19,snovr3 ; Do not save VR3...
1208 stvxl v3,r11,r9 ; Save VR3
1209
1210snovr3:
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
1218snol4:
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
1223snovr4:
1224 bf 21,snovr5 ; Do not save VR5...
1225 stvxl v5,r11,r8 ; Save VR5
1226
1227snovr5:
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
1233snol5:
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
1238snovr6:
1239 bf 23,snovr7 ; Do not save VR7...
1240 stvxl v7,r11,r9 ; Save VR7
1241
1242snovr7:
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
1250snol6:
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
1255snovr8:
1256 bf 25,snovr9 ; Do not save VR9...
1257 stvxl v9,r11,r8 ; Save VR9
1258
1259snovr9:
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
1265snol7:
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
1270snovr10:
1271 bf 27,snovr11 ; Do not save VR11...
1272 stvxl v11,r11,r9 ; Save VR11
1273
1274snovr11:
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
1283snol8:
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
1288snovr12:
1289 bf 29,snovr13 ; Do not save VR13...
1290 stvxl v13,r11,r8 ; Save VR13
1291
1292snovr13:
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
1298snol9:
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
1303snovr14:
1304 bf 31,snovr15 ; Do not save VR15...
1305 stvxl v15,r11,r9 ; Save VR15
1306
1307snovr15:
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
1315snol10:
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
1320snovr16:
1321 bf 17,snovr17 ; Do not save VR17...
1322 stvxl v17,r11,r8 ; Save VR17
1323
1324snovr17:
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
1333snol11:
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
1338snovr18:
1339 bf 19,snovr19 ; Do not save VR19...
1340 stvxl v19,r11,r9 ; Save VR19
1341
1342snovr19:
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
1347snol12:
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
1352snovr20:
1353 bf 21,snovr21 ; Do not save VR21...
1354 stvxl v21,r11,r8 ; Save VR21
1355
1356snovr21:
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
1361snol13:
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
1366snovr22:
1367 bf 23,snovr23 ; Do not save VR23...
1368 stvxl v23,r11,r9 ; Save VR23
1369
1370snovr23:
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
1375snol14:
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
1380snovr24:
1381 bf 25,snovr25 ; Do not save VR25...
1382 stvxl v25,r11,r8 ; Save VR25
1383
1384snovr25:
1385 bf 15,snol15 ; No line 15 to do...
1386 dcba br0,r7 ; Allocate cache line 15
1387
1388snol15:
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
1396snovr26:
1397 bf 27,snovr27 ; Do not save VR27...
1398 stvxl v27,r11,r9 ; Save VR27
1399
1400snovr27:
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
1405snovr28:
1406 bf 29,snovr29 ; Do not save VR29...
1407 stvxl v29,r11,r8 ; Save VR29
1408
1409snovr29:
1410 bf 30,snovr30 ; Do not save VR30...
1411 stvxl v30,br0,r7 ; Save VR30
1412
1413snovr30:
1414 bf 31,snovr31 ; Do not save VR31...
1415 stvxl v31,r11,r7 ; Save VR31
1416
1417snovr31:
1418 mtcrf 255,r2 ; Restore all cr
1419
1420vsret: mtmsr r0 ; Put interrupts on if they were and vector off
1c79356b
A
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
9bccf70c
A
1443 .align 5
1444 .globl EXT(vec_switch)
1445
1446LEXT(vec_switch)
1c79356b
A
1447
1448#if DEBUG
1c79356b
A
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)
1c79356b
A
1454#endif /* DEBUG */
1455
9bccf70c
A
1456 mfsprg r26,0 ; Get the per_processor block
1457 mfmsr r19 ; Get the current MSR
1c79356b 1458
9bccf70c
A
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
1c79356b
A
1466 isync
1467
9bccf70c
A
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
0b4e3aa0 1470
9bccf70c
A
1471; R22 has the "old" context anchor
1472; R29 has the "new" context anchor
0b4e3aa0 1473
1c79356b 1474#if FPVECDBG
9bccf70c
A
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)
1c79356b
A
1481#endif
1482
9bccf70c 1483 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
1c79356b 1484
9bccf70c 1485vsvretry: mr. r22,r22 ; See if there is any live vector status
1c79356b 1486
9bccf70c 1487 beq- vsnosave ; No live context, so nothing to save...
1c79356b 1488
9bccf70c 1489 isync ; Make sure we see this in the right order
1c79356b 1490
9bccf70c
A
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
1c79356b 1497
9bccf70c
A
1498 lwz r10,liveVRS(r26) ; Get the right VRSave register
1499
1500 bne- vsnosave ; No, not on the same processor...
1501
1c79356b 1502;
9bccf70c
A
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.
1c79356b 1506;
9bccf70c
A
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
1c79356b 1511
9bccf70c
A
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...
1c79356b 1516
9bccf70c 1517 lwz r11,SAVlevel(r30) ; Get the level of top saved context
1c79356b 1518
9bccf70c
A
1519 cmplw r31,r11 ; Are live and saved the same?
1520
1c79356b 1521#if FPVECDBG
9bccf70c
A
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)
1c79356b 1528#endif
9bccf70c
A
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...
1c79356b 1533
de355530 1534 lwz r4,SAVprev(r30) ; Pick up the previous area
9bccf70c
A
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
1541vsonlyone: 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
1c79356b 1549
9bccf70c
A
1550
1551vsmstsave: 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
de355530 1557 lwz r12,facAct(r22) ; Get the activation associated with the context
d7e50217 1558 stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread
de355530
A
1559
1560 stw r30,SAVprev(r3) ; Point us to the old context
9bccf70c
A
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
1c79356b 1565
1c79356b 1566#if FPVECDBG
9bccf70c
A
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)
1c79356b
A
1571#endif
1572
9bccf70c 1573 lwz r10,liveVRS(r26) ; Get the right VRSave register
de355530
A
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
1598nol0:
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
1603nol1:
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
1608nol2:
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
1613novr0:
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
1618novr1:
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
1623nol3:
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
1628novr2:
1629 bf 19,novr3 ; Do not save VR3...
1630 stvxl v3,r14,r13 ; Save VR3
1631
1632novr3:
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
1640nol4:
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
1645novr4:
1646 bf 21,novr5 ; Do not save VR5...
1647 stvxl v5,r14,r12 ; Save VR5
1648
1649novr5:
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
1655nol5:
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
1660novr6:
1661 bf 23,novr7 ; Do not save VR7...
1662 stvxl v7,r14,r13 ; Save VR7
1663
1664novr7:
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
1672nol6:
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
1677novr8:
1678 bf 25,novr9 ; Do not save VR9...
1679 stvxl v9,r14,r12 ; Save VR9
1680
1681novr9:
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
1687nol7:
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
1692novr10:
1693 bf 27,novr11 ; Do not save VR11...
1694 stvxl v11,r14,r13 ; Save VR11
1695
1696novr11:
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
1705nol8:
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
1710novr12:
1711 bf 29,novr13 ; Do not save VR13...
1712 stvxl v13,r14,r12 ; Save VR13
1713
1714novr13:
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
1720nol9:
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
1725novr14:
1726 bf 31,novr15 ; Do not save VR15...
1727 stvxl v15,r14,r13 ; Save VR15
1728
1729novr15:
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
1737nol10:
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
1742novr16:
1743 bf 17,novr17 ; Do not save VR17...
1744 stvxl v17,r14,r12 ; Save VR17
1745
1746novr17:
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
1755nol11:
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
1760novr18:
1761 bf 19,novr19 ; Do not save VR19...
1762 stvxl v19,r14,r13 ; Save VR19
1763
1764novr19:
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
1769nol12:
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
1774novr20:
1775 bf 21,novr21 ; Do not save VR21...
1776 stvxl v21,r14,r12 ; Save VR21
1777
1778novr21:
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
1783nol13:
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
1788novr22:
1789 bf 23,novr23 ; Do not save VR23...
1790 stvxl v23,r14,r13 ; Save VR23
1791
1792novr23:
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
1797nol14:
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
1802novr24:
1803 bf 25,novr25 ; Do not save VR25...
1804 stvxl v25,r14,r12 ; Save VR25
1805
1806novr25:
1807 bf 15,nol15 ; No line 15 to do...
1808 dcba br0,r21 ; Allocate cache line 15
1809
1810nol15:
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
1818novr26:
1819 bf 27,novr27 ; Do not save VR27...
1820 stvxl v27,r14,r13 ; Save VR27
1821
1822novr27:
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
1827novr28:
1828 bf 29,novr29 ; Do not save VR29...
1829 stvxl v29,r14,r12 ; Save VR29
1830
1831novr29:
1832 bf 30,novr30 ; Do not save VR30...
1833 stvxl v30,br0,r13 ; Save VR30
1834
1835novr30:
1836 bf 31,novr31 ; Do not save VR31...
1837 stvxl v31,r14,r13 ; Save VR31
1838
1839novr31:
1840
1c79356b
A
1841
1842
9bccf70c
A
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;
1c79356b 1854
0b4e3aa0
A
1855
1856
0b4e3aa0 1857
9bccf70c
A
1858vsnosave: 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
1c79356b
A
1868
1869#if FPVECDBG
9bccf70c
A
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)
1c79356b 1878#endif
9bccf70c
A
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
de355530 1889 li r0,0
9bccf70c
A
1890
1891vsinvothr: lwarx r18,r16,r19 ; Get the owner
de355530
A
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
9bccf70c 1897
de355530 1898vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
9bccf70c
A
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
1c79356b 1903
de355530 1904 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
9bccf70c 1905
de355530 1906 lwz r3,SAVprev(r14) ; Get the previous context
9bccf70c
A
1907 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
1908 cmplw r0,r15 ; Top level correct to load?
de355530 1909 bne- ProtectTheAmericanWay ; No, go initialize...
1c79356b 1910
9bccf70c
A
1911 stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later)
1912
1c79356b 1913#if FPVECDBG
9bccf70c
A
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)
1c79356b
A
1918#endif
1919
d7e50217 1920 lwz r22,savevrsave(r25) ; Get the most current VRSAVE
de355530
A
1921 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
1922 lis r9,0x5555 ; Mask with odd bits set
9bccf70c 1923 and r10,r10,r22 ; Figure out just what registers need to be loaded
de355530
A
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
1945lnol0:
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
1950lnol1:
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
1955lnol2:
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
1960lnovr0:
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
1965lnovr1:
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
1970lnol3:
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
1975lnovr2:
1976 bf 19,lnovr3 ; Do not restore VR3...
1977 lvxl v3,r30,r23 ; Restore VR3
1978
1979lnovr3:
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
1987lnol4:
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
1992lnovr4:
1993 bf 21,lnovr5 ; Do not restore VR5...
1994 lvxl v5,r30,r22 ; Restore VR5
1995
1996lnovr5:
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
2002lnol5:
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
2007lnovr6:
2008 bf 23,lnovr7 ; Do not restore VR7...
2009 lvxl v7,r30,r23 ; Restore VR7
2010
2011lnovr7:
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
2019lnol6:
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
2024lnovr8:
2025 bf 25,lnovr9 ; Do not save VR9...
2026 lvxl v9,r30,r22 ; Restore VR9
2027
2028lnovr9:
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
2034lnol7:
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
2039lnovr10:
2040 bf 27,lnovr11 ; Do not restore VR11...
2041 lvxl v11,r30,r23 ; Restore VR11
2042
2043lnovr11:
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
2052lnol8:
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
2057lnovr12:
2058 bf 29,lnovr13 ; Do not restore VR13...
2059 lvxl v13,r30,r22 ; Restore VR13
2060
2061lnovr13:
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
2067lnol9:
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
2072lnovr14:
2073 bf 31,lnovr15 ; Do not restore VR15...
2074 lvxl v15,r30,r23 ; Restore VR15
2075
2076lnovr15:
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
2084lnol10:
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
2089lnovr16:
2090 bf 17,lnovr17 ; Do not restore VR17...
2091 lvxl v17,r30,r22 ; Restore VR17
2092
2093lnovr17:
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
2102lnol11:
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
2107lnovr18:
2108 bf 19,lnovr19 ; Do not restore VR19...
2109 lvxl v19,r30,r23 ; Restore VR19
2110
2111lnovr19:
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
2116lnol12:
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
2121lnovr20:
2122 bf 21,lnovr21 ; Do not restore VR21...
2123 lvxl v21,r30,r22 ; Restore VR21
2124
2125lnovr21:
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
2130lnol13:
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
2135lnovr22:
2136 bf 23,lnovr23 ; Do not restore VR23...
2137 lvxl v23,r30,r23 ; Restore VR23
2138
2139lnovr23:
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
2144lnol14:
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
2149lnovr24:
2150 bf 25,lnovr25 ; Do not restore VR25...
2151 lvxl v25,r30,r22 ; Restore VR25
2152
2153lnovr25:
2154 bf 15,lnol15 ; No line 15 to do...
2155 dcbt br0,r21 ; Touch cache line 15
2156
2157lnol15:
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
2165lnovr26:
2166 bf 27,lnovr27 ; Do not restore VR27...
2167 lvxl v27,r30,r23 ; Restore VR27
2168
2169lnovr27:
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
2174lnovr28:
2175 bf 29,lnovr29 ; Do not restore VR29...
2176 lvxl v29,r30,r22 ; Restore VR29
2177
2178lnovr29:
2179 bf 30,lnovr30 ; Do not restore VR30...
2180 lvxl v30,br0,r23 ; Restore VR30
2181
2182lnovr30:
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
2195ni0:
2196 bt 1,ni1 ; Register is ok already...
2197 vor v1,v31,v31 ; Copy into the next register
2198ni1:
2199 bt 2,ni2 ; Register is ok already...
2200 vor v2,v31,v31 ; Copy into the next register
2201ni2:
2202 bt 3,ni3 ; Register is ok already...
2203 vor v3,v31,v31 ; Copy into the next register
2204ni3:
2205 bt 4,ni4 ; Register is ok already...
2206 vor v4,v31,v31 ; Copy into the next register
2207ni4:
2208 bt 5,ni5 ; Register is ok already...
2209 vor v5,v31,v31 ; Copy into the next register
2210ni5:
2211 bt 6,ni6 ; Register is ok already...
2212 vor v6,v31,v31 ; Copy into the next register
2213ni6:
2214 bt 7,ni7 ; Register is ok already...
2215 vor v7,v31,v31 ; Copy into the next register
2216ni7:
2217 bt 8,ni8 ; Register is ok already...
2218 vor v8,v31,v31 ; Copy into the next register
2219ni8:
2220 bt 9,ni9 ; Register is ok already...
2221 vor v9,v31,v31 ; Copy into the next register
2222ni9:
2223 bt 10,ni10 ; Register is ok already...
2224 vor v10,v31,v31 ; Copy into the next register
2225ni10:
2226 bt 11,ni11 ; Register is ok already...
2227 vor v11,v31,v31 ; Copy into the next register
2228ni11:
2229 bt 12,ni12 ; Register is ok already...
2230 vor v12,v31,v31 ; Copy into the next register
2231ni12:
2232 bt 13,ni13 ; Register is ok already...
2233 vor v13,v31,v31 ; Copy into the next register
2234ni13:
2235 bt 14,ni14 ; Register is ok already...
2236 vor v14,v31,v31 ; Copy into the next register
2237ni14:
2238 bt 15,ni15 ; Register is ok already...
2239 vor v15,v31,v31 ; Copy into the next register
2240ni15:
2241 bt 16,ni16 ; Register is ok already...
2242 vor v16,v31,v31 ; Copy into the next register
2243ni16:
2244 bt 17,ni17 ; Register is ok already...
2245 vor v17,v31,v31 ; Copy into the next register
2246ni17:
2247 bt 18,ni18 ; Register is ok already...
2248 vor v18,v31,v31 ; Copy into the next register
2249ni18:
2250 bt 19,ni19 ; Register is ok already...
2251 vor v19,v31,v31 ; Copy into the next register
2252ni19:
2253 bt 20,ni20 ; Register is ok already...
2254 vor v20,v31,v31 ; Copy into the next register
2255ni20:
2256 bt 21,ni21 ; Register is ok already...
2257 vor v21,v31,v31 ; Copy into the next register
2258ni21:
2259 bt 22,ni22 ; Register is ok already...
2260 vor v22,v31,v31 ; Copy into the next register
2261ni22:
2262 bt 23,ni23 ; Register is ok already...
2263 vor v23,v31,v31 ; Copy into the next register
2264ni23:
2265 bt 24,ni24 ; Register is ok already...
2266 vor v24,v31,v31 ; Copy into the next register
2267ni24:
2268 bt 25,ni25 ; Register is ok already...
2269 vor v25,v31,v31 ; Copy into the next register
2270ni25:
2271 bt 26,ni26 ; Register is ok already...
2272 vor v26,v31,v31 ; Copy into the next register
2273ni26:
2274 bt 27,ni27 ; Register is ok already...
2275 vor v27,v31,v31 ; Copy into the next register
2276ni27:
2277 bt 28,ni28 ; Register is ok already...
2278 vor v28,v31,v31 ; Copy into the next register
2279ni28:
2280 bt 29,ni29 ; Register is ok already...
2281 vor v29,v31,v31 ; Copy into the next register
2282ni29:
2283 bt 30,ni30 ; Register is ok already...
2284 vor v30,v31,v31 ; Copy into the next register
2285ni30:
2286 bf 31,lnovr31 ; V31 is empty, no need to restore...
2287
2288mstlvr31: lvxl v31,r30,r23 ; Restore VR31
1c79356b 2289
de355530
A
2290lnovr31: mr r3,r14 ; Get the old savearea (we popped it before)
2291 bl EXT(save_ret) ; Toss it
2292
2293vrenable: 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
9bccf70c 2295 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
d7e50217
A
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
de355530 2298 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
1c79356b 2299 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
d7e50217 2300 oris r11,r11,hi16(vectorUsed|vectorCng) ; Set that we used vectors
9bccf70c 2301 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
de355530
A
2302 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
2303 xor r3,r25,r5 ; Get the real address of the savearea
b4c24cb9 2304 beq- vrnuser ; We are not user state...
9bccf70c 2305 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
d7e50217 2306 stw r11,spcFlags(r26) ; Set per_proc copy
1c79356b
A
2307
2308vrnuser:
2309#if FPVECDBG
9bccf70c
A
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)
1c79356b 2314#endif
9bccf70c 2315 b EXT(exception_exit) ; Exit to the fray...
1c79356b
A
2316
2317/*
2318 * Initialize the registers to some bogus value
1c79356b
A
2319 */
2320
2321ProtectTheAmericanWay:
2322
2323#if FPVECDBG
9bccf70c
A
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)
1c79356b 2328#endif
9bccf70c
A
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
2374vsthesame:
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
de355530 2385 lwz r14,SAVprev(r30) ; Get the previous savearea
9bccf70c
A
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.
1c79356b 2399;
1c79356b 2400
9bccf70c
A
2401 .align 5
2402 .globl EXT(toss_live_vec)
1c79356b 2403
9bccf70c
A
2404LEXT(toss_live_vec)
2405
2406 mfmsr r9 ; Get the MSR
de355530
A
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
9bccf70c
A
2411 mtmsr r0 ; No interruptions
2412 isync
2413 beq+ tlvnotours ; Vector off, can not be live here...
1c79356b 2414
9bccf70c
A
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
2433tlvnotours: 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
2441tlvinvothr: lwarx r12,r10,r11 ; Get the owner
de355530
A
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...
9bccf70c 2446
de355530 2447tlvexit: mtmsr r9 ; Restore interruptions
9bccf70c
A
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
2461LEXT(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
de355530 2477 li r0,0 ; Set a 0 to invalidate context
9bccf70c
A
2478
2479vtinvothr: lwarx r12,r10,r11 ; Get the owner
de355530
A
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...
9bccf70c 2484
de355530 2485vtnotlive: beqlr+ cr1 ; Leave if there is no savearea
9bccf70c
A
2486 lwz r8,SAVlevel(r9) ; Get the level of the savearea
2487 cmplw r8,r11 ; Savearea for the current level?
de355530 2488 bnelr+ ; No, nothing to release...
9bccf70c 2489
de355530 2490 lwz r8,SAVprev(r9) ; Pick up the previous area
9bccf70c 2491 mr. r8,r8 ; Is there a previous?
de355530 2492 beq- vtnoprev ; Nope...
9bccf70c
A
2493 lwz r7,SAVlevel(r8) ; Get the level associated with save
2494
2495vtnoprev: 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)
1c79356b 2508
9bccf70c
A
2509LEXT(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