]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/cswtch.s
xnu-344.12.2.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 *
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>
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
9bccf70c 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 */
9bccf70c 82 mtsprg 1,r9
1c79356b
A
83 stw r1,0(r12)
84 li r0,0 /* Clear a register */
85 lwz r8,ACT_MACT_PCB(r9) /* Get the savearea used */
1c79356b
A
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 */
1c79356b
A
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 */
1c79356b
A
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
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.
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
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
9bccf70c 149 lwz r11,PP_ISTACKPTR(r12) ; (DEBUG/TRACE) make sure we are not
1c79356b
A
150 mr. r11,r11 ; (DEBUG/TRACE) on the interrupt
151 bne+ notonintstack ; (DEBUG/TRACE) stack
152 BREAKPOINT_TRAP
153notonintstack:
154#endif
9bccf70c
A
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
1c79356b
A
158/*
159 * Make the new thread the current thread.
160 */
161
9bccf70c
A
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
1c79356b 164
9bccf70c 165 lwz r11,THREAD_KERNEL_STACK(r5) ; Get the new stack pointer
1c79356b 166
9bccf70c
A
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
0b4e3aa0 170 lwz r8,ACT_MACT_PCB(r5) ; Get the PCB for the new guy
9bccf70c
A
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
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"
0b4e3aa0
A
183
184 lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment
1c79356b
A
185
186 lwz r7,ACT_MACT_SPF(r5) ; Get the special flags
187
188 lwz r10,ACT_KLOADED(r5)
9bccf70c 189 stw r11,ppbbTaskEnv(r12) ; Save the bb task env
1c79356b
A
190 li r0,0
191 cmpwi cr0,r10,0
9bccf70c
A
192 lwz r10,PP_ACTIVE_KLOADED(r12)
193 stw r7,spcFlags(r12) ; Set per_proc copy of the special flags
1c79356b
A
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
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 */
1c79356b
A
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 */
9bccf70c 223 lwz r2,curctx(r5) ; Grab our current context pointer
1c79356b
A
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 */
9bccf70c
A
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
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...
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
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 */
333 lis r0,hi16(SwitchContextCall) /* Top part of switch context */
1c79356b 334 stw r9,savesrr0(r8) /* Make us jump to the switch in routine */
9bccf70c 335
1c79356b
A
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 */
1c79356b
A
341 xor r3,r7,r8 /* Get the physical address of the new context save area */
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
A
362swtchtocont:
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...
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 *
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
9bccf70c
A
386
387 .align 5
388 .globl EXT(switch_in)
389
390LEXT(switch_in)
1c79356b
A
391
392 lwz r4,saver4(r3) /* Get the old thread */
1c79356b
A
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/*
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
433 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
1c79356b 434 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
9bccf70c
A
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
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)
451 beq- noowneryet ; (TEST/DEBUG)
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
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
A
470 lwz r9,FPUcpu(r12) ; Get the cpu that context was last on
471 bne- cr1,fsret ; No, it is not...
1c79356b 472
9bccf70c
A
473 cmplw cr1,r9,r11 ; Was the context for this processor?
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?
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...
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
1c79356b 505
9bccf70c 506 stw r9,SAVlevel(r3) ; Show level in savearea
1c79356b
A
507
508;
509; Save the current FPU state into the PCB of the thread that owns it.
510;
511
9bccf70c
A
512 la r11,savefp0(r3) ; Point to the 1st line
513 dcbz 0,r11 ; Allocate the first savearea line
1c79356b 514
9bccf70c 515 la r11,savefp4(r3) ; Point to the 2nd line
1c79356b 516 stfd f0,savefp0(r3)
9bccf70c 517 dcbz 0,r11 ; Allocate it
1c79356b
A
518 stfd f1,savefp1(r3)
519 stfd f2,savefp2(r3)
9bccf70c 520 la r11,savefp8(r3) ; Point to the 3rd line
1c79356b 521 stfd f3,savefp3(r3)
9bccf70c 522 dcbz 0,r11 ; Allocate it
1c79356b
A
523 stfd f4,savefp4(r3)
524 stfd f5,savefp5(r3)
525 stfd f6,savefp6(r3)
9bccf70c 526 la r11,savefp12(r3) ; Point to the 4th line
1c79356b 527 stfd f7,savefp7(r3)
9bccf70c 528 dcbz 0,r11 ; Allocate it
1c79356b
A
529 stfd f8,savefp8(r3)
530 stfd f9,savefp9(r3)
531 stfd f10,savefp10(r3)
9bccf70c 532 la r11,savefp16(r3) ; Point to the 5th line
1c79356b 533 stfd f11,savefp11(r3)
9bccf70c 534 dcbz 0,r11 ; Allocate it
1c79356b
A
535 stfd f12,savefp12(r3)
536 stfd f13,savefp13(r3)
537 stfd f14,savefp14(r3)
9bccf70c 538 la r11,savefp20(r3) ; Point to the 6th line
1c79356b
A
539 stfd f15,savefp15(r3)
540 stfd f16,savefp16(r3)
541 stfd f17,savefp17(r3)
542 stfd f18,savefp18(r3)
9bccf70c 543 la r11,savefp24(r3) ; Point to the 7th line
1c79356b 544 stfd f19,savefp19(r3)
9bccf70c 545 dcbz 0,r11 ; Allocate it
1c79356b 546 stfd f20,savefp20(r3)
1c79356b
A
547 stfd f21,savefp21(r3)
548 stfd f22,savefp22(r3)
9bccf70c 549 la r11,savefp28(r3) ; Point to the 8th line
1c79356b 550 stfd f23,savefp23(r3)
9bccf70c 551 dcbz 0,r11 ; Allocate it
1c79356b
A
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
1c79356b
A
558 stfd f29,savefp29(r3)
559 stfd f30,savefp30(r3)
560 stfd f31,savefp31(r3)
9bccf70c
A
561
562fsret: mtmsr r0 ; Put interrupts on if they were and floating point off
1c79356b
A
563 isync
564
565 blr
566
9bccf70c
A
567fsbackout: mr r12,r0 ; Save the original MSR
568 b EXT(save_ret_join) ; Toss savearea and return from there...
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
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
1c79356b 683
9bccf70c
A
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
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
697;
698; Now we will actually save the old context
699;
700
9bccf70c 701 la r11,savefp4(r3) ; Point to the 2nd line
1c79356b 702 stfd f0,savefp0(r3)
9bccf70c 703 dcbz 0,r11 ; Allocate cache
1c79356b
A
704 stfd f1,savefp1(r3)
705 stfd f2,savefp2(r3)
9bccf70c 706 la r11,savefp8(r3) ; Point to the 3rd line
1c79356b 707 stfd f3,savefp3(r3)
9bccf70c 708 dcbz 0,r11 ; Allocate cache
1c79356b
A
709 stfd f4,savefp4(r3)
710 stfd f5,savefp5(r3)
711 stfd f6,savefp6(r3)
9bccf70c 712 la r11,savefp12(r3) ; Point to the 4th line
1c79356b 713 stfd f7,savefp7(r3)
9bccf70c 714 dcbz 0,r11 ; Allocate cache
1c79356b
A
715 stfd f8,savefp8(r3)
716 stfd f9,savefp9(r3)
717 stfd f10,savefp10(r3)
9bccf70c 718 la r11,savefp16(r3) ; Point to the 5th line
1c79356b 719 stfd f11,savefp11(r3)
9bccf70c 720 dcbz 0,r11 ; Allocate cache
1c79356b
A
721 stfd f12,savefp12(r3)
722 stfd f13,savefp13(r3)
723 stfd f14,savefp14(r3)
9bccf70c 724 la r11,savefp20(r3) ; Point to the 6th line
1c79356b 725 stfd f15,savefp15(r3)
9bccf70c 726 dcbz 0,r11 ; Allocate cache
1c79356b
A
727 stfd f16,savefp16(r3)
728 stfd f17,savefp17(r3)
729 stfd f18,savefp18(r3)
9bccf70c 730 la r11,savefp24(r3) ; Point to the 7th line
1c79356b 731 stfd f19,savefp19(r3)
9bccf70c 732 dcbz 0,r11 ; Allocate cache
1c79356b
A
733 stfd f20,savefp20(r3)
734
1c79356b
A
735 stfd f21,savefp21(r3)
736 stfd f22,savefp22(r3)
9bccf70c 737 la r11,savefp28(r3) ; Point to the 8th line
1c79356b 738 stfd f23,savefp23(r3)
9bccf70c 739 dcbz 0,r11 ; allocate it
1c79356b
A
740 stfd f24,savefp24(r3)
741 stfd f25,savefp25(r3)
742 stfd f26,savefp26(r3)
1c79356b 743 stfd f27,savefp27(r3)
9bccf70c 744 dcbz 0,r11 ; allocate it
1c79356b
A
745 stfd f28,savefp28(r3)
746 stfd f29,savefp29(r3)
747 stfd f30,savefp30(r3)
748 stfd f31,savefp31(r3)
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
783 li r0,0
784
785fsinvothr: 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
791fsinvoths: 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
1c79356b
A
796
797 beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load...
9bccf70c
A
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?
1c79356b 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
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
867 ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature
868 lwz r10,ACT_MACT_SPF(r17) ; Get the special flags
869 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
1c79356b 870 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
9bccf70c
A
871 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
872 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
873 xor r3,r25,r5 ; Get the real address of the savearea
b4c24cb9 874 beq- fsnuser ; We are not user state...
9bccf70c
A
875 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
876 stw r10,spcFlags(r26) ; Set per_proc copy
1c79356b
A
877
878fsnuser:
879#if FPVECDBG
9bccf70c
A
880 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
881 li r2,0x7F07 ; (TEST/DEBUG)
882 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
883 sc ; (TEST/DEBUG)
1c79356b 884#endif
1c79356b 885
9bccf70c 886 b EXT(exception_exit) ; Exit to the fray...
1c79356b
A
887
888/*
889 * Initialize the registers to some bogus value
890 */
891
892MakeSureThatNoTerroristsCanHurtUsByGod:
0b4e3aa0 893
1c79356b 894#if FPVECDBG
9bccf70c
A
895 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
896 li r2,0x7F06 ; (TEST/DEBUG)
897 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
898 sc ; (TEST/DEBUG)
1c79356b 899#endif
9bccf70c
A
900 lis r5,hi16(EXT(FloatInit)) ; Get top secret floating point init value address
901 ori r5,r5,lo16(EXT(FloatInit)) ; Slam bottom
902 lfd f0,0(r5) ; Initialize FP0
903 fmr f1,f0 ; Do them all
1c79356b
A
904 fmr f2,f0
905 fmr f3,f0
906 fmr f4,f0
907 fmr f5,f0
908 fmr f6,f0
909 fmr f7,f0
910 fmr f8,f0
911 fmr f9,f0
912 fmr f10,f0
913 fmr f11,f0
914 fmr f12,f0
915 fmr f13,f0
916 fmr f14,f0
917 fmr f15,f0
918 fmr f16,f0
919 fmr f17,f0
1c79356b
A
920 fmr f18,f0
921 fmr f19,f0
922 fmr f20,f0
1c79356b
A
923 fmr f21,f0
924 fmr f22,f0
925 fmr f23,f0
926 fmr f24,f0
927 fmr f25,f0
928 fmr f26,f0
929 fmr f27,f0
930 fmr f28,f0
931 fmr f29,f0
932 fmr f30,f0
933 fmr f31,f0
9bccf70c
A
934 b fsenable ; Finish setting it all up...
935
1c79356b
A
936
937;
9bccf70c
A
938; We get here when we are switching to the same context at the same level and the context
939; is still live. Essentially, all we are doing is turning on the faility. It may have
940; gotten turned off due to doing a context save for the current level or a context switch
941; back to the live guy.
1c79356b 942;
9bccf70c
A
943
944 .align 5
1c79356b 945
9bccf70c 946fsthesame:
1c79356b 947
9bccf70c
A
948#if FPVECDBG
949 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
950 li r2,0x7F0A ; (TEST/DEBUG)
951 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
952 sc ; (TEST/DEBUG)
953#endif
954 beq- cr1,fsenable ; Not saved yet, nothing to pop, go enable and exit...
1c79356b 955
9bccf70c
A
956 lwz r11,SAVlevel(r30) ; Get the level of top saved context
957 lwz r14,SAVprev(r30) ; Get the previous savearea
1c79356b 958
9bccf70c 959 cmplw r11,r31 ; Are live and saved the same?
1c79356b 960
9bccf70c 961 bne+ fsenable ; Level not the same, nothing to pop, go enable and exit...
1c79356b 962
9bccf70c
A
963 mr r3,r30 ; Get the old savearea (we popped it before)
964 bl EXT(save_ret) ; Toss it
965 b fsenable ; Go enable and exit...
966
967
968;
969; This function invalidates any live floating point context for the passed in facility_context.
970; This is intended to be called just before act_machine_sv_free tosses saveareas.
971;
972
973 .align 5
974 .globl EXT(toss_live_fpu)
975
976LEXT(toss_live_fpu)
977
978
979 mfmsr r9 ; Get the MSR
980 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
981 rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT ; Are floats on right now?
982 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off
983 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure floats are turned off
984 mtmsr r0 ; No interruptions
985 isync
986 beq+ tlfnotours ; Floats off, can not be live here...
987
988 mfsprg r8,0 ; Get the per proc
989
990;
991; Note that at this point, since floats are on, we are the owner
992; of live state on this processor
1c79356b 993;
9bccf70c
A
994
995 lwz r6,FPUowner(r8) ; Get the thread that owns the floats
996 li r0,0 ; Clear this just in case we need it
997 cmplw r6,r3 ; Are we tossing our own context?
998 bne- tlfnotours ; Nope...
999
1000 fsub f1,f1,f1 ; Make a 0
1001 mtfsf 0xFF,f1 ; Clear it
1002
1003tlfnotours: lwz r11,FPUcpu(r3) ; Get the cpu on which we last loaded context
1004 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
1005 mulli r11,r11,ppSize ; Find offset to the owner per_proc
1006 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
1007 li r10,FPUowner ; Displacement to float owner
1008 add r11,r12,r11 ; Point to the owner per_proc
1009 li r0,0 ; Set a 0 to invalidate context
1010
1011tlfinvothr: lwarx r12,r10,r11 ; Get the owner
1012 cmplw r12,r3 ; Does he still have this context?
1013 bne+ tlfexit ; Nope, leave...
1014 stwcx. r0,r10,r11 ; Try to invalidate it
1015 bne- tlfinvothr ; Try again if there was a collision...
1016
1017tlfexit: mtmsr r9 ; Restore interruptions
1018 isync ; Could be turning off floats here
1019 blr ; Leave...
1020
1c79356b
A
1021
1022/*
1023 * Altivec stuff is here. The techniques used are pretty identical to
1024 * the floating point. Except that we will honor the VRSAVE register
1025 * settings when loading and restoring registers.
1026 *
1027 * There are two indications of saved VRs: the VRSAVE register and the vrvalid
1028 * mask. VRSAVE is set by the vector user and represents the VRs that they
1029 * say that they are using. The vrvalid mask indicates which vector registers
1030 * are saved in the savearea. Whenever context is saved, it is saved according
1031 * to the VRSAVE register. It is loaded based on VRSAVE anded with
1032 * vrvalid (all other registers are splatted with 0s). This is done because we
1033 * don't want to load any registers we don't have a copy of, we want to set them
1034 * to zero instead.
1035 *
9bccf70c
A
1036 * Note that there are some oddities here when we save a context we are using.
1037 * It is really not too cool to do this, but what the hey... Anyway,
1038 * we turn vectors and fpu off before we leave.
1039 * The oddity is that if you use vectors after this, the
1040 * savearea containing the context just saved will go away. So, bottom line is
1041 * that don't use vectors until after you are done with the saved context.
1042 *
1c79356b
A
1043 */
1044
9bccf70c
A
1045 .align 5
1046 .globl EXT(vec_save)
1047
1048LEXT(vec_save)
1c79356b 1049
9bccf70c
A
1050 mfmsr r0 ; Get the MSR
1051 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vectors are turned off when we leave
1c79356b 1052 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
9bccf70c
A
1053 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
1054 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force off fp
1055 mtmsr r2 ; Set the MSR
1c79356b
A
1056 isync
1057
9bccf70c
A
1058 mfsprg r6,0 ; Get the per_processor block
1059 lwz r12,VMXowner(r6) ; Get the context ID for owner
1060
1c79356b 1061#if FPVECDBG
9bccf70c
A
1062 mr r7,r0 ; (TEST/DEBUG)
1063 li r4,0 ; (TEST/DEBUG)
1064 mr r10,r3 ; (TEST/DEBUG)
1065 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1066 mr. r3,r12 ; (TEST/DEBUG)
1067 li r2,0x5F00 ; (TEST/DEBUG)
1068 li r5,0 ; (TEST/DEBUG)
1069 beq- noowneryeu ; (TEST/DEBUG)
1070 lwz r4,VMXlevel(r12) ; (TEST/DEBUG)
1071 lwz r5,VMXsave(r12) ; (TEST/DEBUG)
1072
1073noowneryeu: oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1074 sc ; (TEST/DEBUG)
1075 mr r0,r7 ; (TEST/DEBUG)
1076 mr r3,r10 ; (TEST/DEBUG)
1c79356b 1077#endif
9bccf70c
A
1078 mflr r2 ; Save the return address
1079
1080vsretry: mr. r12,r12 ; Anyone own the vector?
1081 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
1082 beq- vsret ; Nobody owns the vector, no save required...
1083
1084 cmplw cr1,r3,r12 ; Is the specified context live?
1085
1086 isync ; Force owner check first
1087
1088 lwz r9,VMXcpu(r12) ; Get the cpu that context was last on
1089 bne- cr1,vsret ; Specified context is not live
1090
1091 cmplw cr1,r9,r11 ; Was the context for this processor?
1092 beq+ cr1,vsgoodcpu ; Facility last used on this processor...
1093
1094 b vsret ; Someone else claimed this...
1095
1096 .align 5
1097
1098vsgoodcpu: lwz r3,VMXsave(r12) ; Get the current vector savearea for the thread
1099 lwz r10,liveVRS(r6) ; Get the right VRSave register
1100 lwz r9,VMXlevel(r12) ; Get our current level indicator
1101
1102
1103 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
1104 beq- cr1,vsneedone ; Never saved it, so we need an area...
1105
1106 lwz r8,SAVlevel(r3) ; Get the level this savearea is for
1107 mr. r10,r10 ; Is VRsave set to 0?
1108 cmplw cr1,r9,r8 ; Correct level?
1109 bne- cr1,vsneedone ; Different level, so we need to save...
1c79356b 1110
9bccf70c 1111 bne+ vsret ; VRsave is non-zero so we need to keep what is saved...
0b4e3aa0 1112
9bccf70c
A
1113 lwz r4,SAVprev(r3) ; Pick up the previous area
1114 lwz r5,SAVlevel(r4) ; Get the level associated with save
1115 stw r4,VMXsave(r12) ; Dequeue this savearea
1116 stw r5,VMXlevel(r12) ; Save the level
1117
1118 li r3,0 ; Clear
1119 stw r3,VMXowner(r12) ; Show no live context here
1120 eieio
1121
1122vsbackout: mr r12,r0 ; Set the saved MSR
1123 b EXT(save_ret_join) ; Toss the savearea and return from there...
1124
1125 .align 5
1126
1127vsneedone: mr. r10,r10 ; Is VRsave set to 0?
1128 beq- vsret ; Yeah, they do not care about any of them...
1129
1130 bl EXT(save_get) ; Get a savearea for the context
1131
1132 mfsprg r6,0 ; Get back per_processor block
1133 li r4,SAVvector ; Get vector tag
1134 lwz r12,VMXowner(r6) ; Get back our context ID
1135 stb r4,SAVflags+2(r3) ; Mark this savearea as a vector
1136 mr. r12,r12 ; See if we were disowned while away. Very, very small chance of it...
1137 beq- vsbackout ; If disowned, just toss savearea...
1138 lwz r4,facAct(r12) ; Get the activation associated with live context
1139 mtlr r2 ; Restore return
1140 lwz r8,VMXsave(r12) ; Get the current top vector savearea
1141 stw r4,SAVact(r3) ; Indicate the right activation for this context
1142 lwz r9,VMXlevel(r12) ; Get our current level indicator again
1143 stw r3,VMXsave(r12) ; Set this as the most current floating point context
1144 stw r8,SAVprev(r3) ; And then chain this in front
1145
1146 stw r9,SAVlevel(r3) ; Set level in savearea
1147
1c79356b
A
1148 mfcr r2 ; Save non-volatile CRs
1149 lwz r10,liveVRS(r6) ; Get the right VRSave register
1150 lis r9,0x5555 ; Mask with odd bits set
1151 rlwinm r11,r10,1,0,31 ; Shift over 1
1152 ori r9,r9,0x5555 ; Finish mask
0b4e3aa0 1153 or r4,r10,r11 ; After this, even bits show which lines to zap
1c79356b 1154
0b4e3aa0 1155 andc r11,r4,r9 ; Clear out odd bits
1c79356b
A
1156
1157 la r6,savevr0(r3) ; Point to line 0
1158 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits
1c79356b
A
1159 or r4,r11,r4 ; Set the odd bits
1160 ; (bit 0 is line 0, bit 1 is line 8,
1161 ; bit 2 is line 1, bit 3 is line 9, etc.
1c79356b
A
1162 rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1163 la r7,savevr2(r3) ; Point to line 1
1164 mtcrf 255,r4 ; Load up the CRs
1165 stw r10,savevrvalid(r3) ; Save the validity information
1166 mr r8,r6 ; Start registers off
1167;
1168; Save the current vector state
1169;
1170
1171 bf 0,snol0 ; No line 0 to do...
1172 dcba br0,r6 ; Allocate cache line 0
1173
1174snol0:
1175 la r6,savevr4(r3) ; Point to line 2
1176 bf 2,snol1 ; No line 1 to do...
1177 dcba br0,r7 ; Allocate cache line 1
1178
1179snol1:
1180 la r7,savevr6(r3) ; Point to line 3
1181 bf 4,snol2 ; No line 2 to do...
1182 dcba br0,r6 ; Allocate cache line 2
1183
1184snol2:
1185 li r11,16 ; Get offset for odd registers
1186 bf 16,snovr0 ; Do not save VR0...
1187 stvxl v0,br0,r8 ; Save VR0
1188
1189snovr0:
1190 la r9,savevr2(r3) ; Point to V2/V3 pair
1191 bf 17,snovr1 ; Do not save VR1...
1192 stvxl v1,r11,r8 ; Save VR1
1193
1194snovr1:
1195 la r6,savevr8(r3) ; Point to line 4
1196 bf 6,snol3 ; No line 3 to do...
1197 dcba br0,r7 ; Allocate cache line 3
1198
1199snol3:
1200 la r8,savevr4(r3) ; Point to V4/V5 pair
1201 bf 18,snovr2 ; Do not save VR2...
1202 stvxl v2,br0,r9 ; Save VR2
1203
1204snovr2:
1205 bf 19,snovr3 ; Do not save VR3...
1206 stvxl v3,r11,r9 ; Save VR3
1207
1208snovr3:
1209;
1210; Note: CR4 is now free
1211;
1212 la r7,savevr10(r3) ; Point to line 5
1213 bf 8,snol4 ; No line 4 to do...
1214 dcba br0,r6 ; Allocate cache line 4
1215
1216snol4:
1217 la r9,savevr6(r3) ; Point to R6/R7 pair
1218 bf 20,snovr4 ; Do not save VR4...
1219 stvxl v4,br0,r8 ; Save VR4
1220
1221snovr4:
1222 bf 21,snovr5 ; Do not save VR5...
1223 stvxl v5,r11,r8 ; Save VR5
1224
1225snovr5:
1226 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1227 la r6,savevr12(r3) ; Point to line 6
1228 bf 10,snol5 ; No line 5 to do...
1229 dcba br0,r7 ; Allocate cache line 5
1230
1231snol5:
1232 la r8,savevr8(r3) ; Point to V8/V9 pair
1233 bf 22,snovr6 ; Do not save VR6...
1234 stvxl v6,br0,r9 ; Save VR6
1235
1236snovr6:
1237 bf 23,snovr7 ; Do not save VR7...
1238 stvxl v7,r11,r9 ; Save VR7
1239
1240snovr7:
1241;
1242; Note: CR5 is now free
1243;
1244 la r7,savevr14(r3) ; Point to line 7
1245 bf 12,snol6 ; No line 6 to do...
1246 dcba br0,r6 ; Allocate cache line 6
1247
1248snol6:
1249 la r9,savevr10(r3) ; Point to V10/V11 pair
1250 bf 24,snovr8 ; Do not save VR8...
1251 stvxl v8,br0,r8 ; Save VR8
1252
1253snovr8:
1254 bf 25,snovr9 ; Do not save VR9...
1255 stvxl v9,r11,r8 ; Save VR9
1256
1257snovr9:
1258 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1259 la r6,savevr16(r3) ; Point to line 8
1260 bf 14,snol7 ; No line 7 to do...
1261 dcba br0,r7 ; Allocate cache line 7
1262
1263snol7:
1264 la r8,savevr12(r3) ; Point to V12/V13 pair
1265 bf 26,snovr10 ; Do not save VR10...
1266 stvxl v10,br0,r9 ; Save VR10
1267
1268snovr10:
1269 bf 27,snovr11 ; Do not save VR11...
1270 stvxl v11,r11,r9 ; Save VR11
1271
1272snovr11:
1273
1274;
1275; Note: CR6 is now free
1276;
1277 la r7,savevr18(r3) ; Point to line 9
1278 bf 1,snol8 ; No line 8 to do...
1279 dcba br0,r6 ; Allocate cache line 8
1280
1281snol8:
1282 la r9,savevr14(r3) ; Point to V14/V15 pair
1283 bf 28,snovr12 ; Do not save VR12...
1284 stvxl v12,br0,r8 ; Save VR12
1285
1286snovr12:
1287 bf 29,snovr13 ; Do not save VR13...
1288 stvxl v13,r11,r8 ; Save VR13
1289
1290snovr13:
1291 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1292 la r6,savevr20(r3) ; Point to line 10
1293 bf 3,snol9 ; No line 9 to do...
1294 dcba br0,r7 ; Allocate cache line 9
1295
1296snol9:
1297 la r8,savevr16(r3) ; Point to V16/V17 pair
1298 bf 30,snovr14 ; Do not save VR14...
1299 stvxl v14,br0,r9 ; Save VR14
1300
1301snovr14:
1302 bf 31,snovr15 ; Do not save VR15...
1303 stvxl v15,r11,r9 ; Save VR15
1304
1305snovr15:
1306;
1307; Note: CR7 is now free
1308;
1309 la r7,savevr22(r3) ; Point to line 11
1310 bf 5,snol10 ; No line 10 to do...
1311 dcba br0,r6 ; Allocate cache line 10
1312
1313snol10:
1314 la r9,savevr18(r3) ; Point to V18/V19 pair
1315 bf 16,snovr16 ; Do not save VR16...
1316 stvxl v16,br0,r8 ; Save VR16
1317
1318snovr16:
1319 bf 17,snovr17 ; Do not save VR17...
1320 stvxl v17,r11,r8 ; Save VR17
1321
1322snovr17:
1323 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1324;
1325; Note: All registers have been or are accounted for in CRs
1326;
1327 la r6,savevr24(r3) ; Point to line 12
1328 bf 7,snol11 ; No line 11 to do...
1329 dcba br0,r7 ; Allocate cache line 11
1330
1331snol11:
1332 la r8,savevr20(r3) ; Point to V20/V21 pair
1333 bf 18,snovr18 ; Do not save VR18...
1334 stvxl v18,br0,r9 ; Save VR18
1335
1336snovr18:
1337 bf 19,snovr19 ; Do not save VR19...
1338 stvxl v19,r11,r9 ; Save VR19
1339
1340snovr19:
1341 la r7,savevr26(r3) ; Point to line 13
1342 bf 9,snol12 ; No line 12 to do...
1343 dcba br0,r6 ; Allocate cache line 12
1344
1345snol12:
1346 la r9,savevr22(r3) ; Point to V22/V23 pair
1347 bf 20,snovr20 ; Do not save VR20...
1348 stvxl v20,br0,r8 ; Save VR20
1349
1350snovr20:
1351 bf 21,snovr21 ; Do not save VR21...
1352 stvxl v21,r11,r8 ; Save VR21
1353
1354snovr21:
1355 la r6,savevr28(r3) ; Point to line 14
1356 bf 11,snol13 ; No line 13 to do...
1357 dcba br0,r7 ; Allocate cache line 13
1358
1359snol13:
1360 la r8,savevr24(r3) ; Point to V24/V25 pair
1361 bf 22,snovr22 ; Do not save VR22...
1362 stvxl v22,br0,r9 ; Save VR22
1363
1364snovr22:
1365 bf 23,snovr23 ; Do not save VR23...
1366 stvxl v23,r11,r9 ; Save VR23
1367
1368snovr23:
1369 la r7,savevr30(r3) ; Point to line 15
1370 bf 13,snol14 ; No line 14 to do...
1371 dcba br0,r6 ; Allocate cache line 14
1372
1373snol14:
1374 la r9,savevr26(r3) ; Point to V26/V27 pair
1375 bf 24,snovr24 ; Do not save VR24...
1376 stvxl v24,br0,r8 ; Save VR24
1377
1378snovr24:
1379 bf 25,snovr25 ; Do not save VR25...
1380 stvxl v25,r11,r8 ; Save VR25
1381
1382snovr25:
1383 bf 15,snol15 ; No line 15 to do...
1384 dcba br0,r7 ; Allocate cache line 15
1385
1386snol15:
1387;
1388; Note: All cache lines allocated now
1389;
1390 la r8,savevr28(r3) ; Point to V28/V29 pair
1391 bf 26,snovr26 ; Do not save VR26...
1392 stvxl v26,br0,r9 ; Save VR26
1393
1394snovr26:
1395 bf 27,snovr27 ; Do not save VR27...
1396 stvxl v27,r11,r9 ; Save VR27
1397
1398snovr27:
1399 la r7,savevr30(r3) ; Point to V30/V31 pair
1400 bf 28,snovr28 ; Do not save VR28...
1401 stvxl v28,br0,r8 ; Save VR28
1402
1403snovr28:
1404 bf 29,snovr29 ; Do not save VR29...
1405 stvxl v29,r11,r8 ; Save VR29
1406
1407snovr29:
1c79356b
A
1408 bf 30,snovr30 ; Do not save VR30...
1409 stvxl v30,br0,r7 ; Save VR30
1410
1411snovr30:
1c79356b
A
1412 bf 31,snovr31 ; Do not save VR31...
1413 stvxl v31,r11,r7 ; Save VR31
1414
1415snovr31:
9bccf70c 1416 mtcrf 255,r2 ; Restore all cr
1c79356b 1417
9bccf70c 1418vsret: mtmsr r0 ; Put interrupts on if they were and vector off
1c79356b
A
1419 isync
1420
1421 blr
1422
1423/*
1424 * vec_switch()
1425 *
1426 * Entered to handle the vector unavailable exception and
1427 * switch vector context
1428 *
1429 * This code is run with virtual address mode on and interrupts off.
1430 *
1431 * Upon exit, the code returns to the users context with the vector
1432 * facility turned on.
1433 *
1434 * ENTRY: VM switched ON
1435 * Interrupts OFF
1436 * State is saved in savearea pointed to by R4.
1437 * All other registers are free.
1438 *
1439 */
1440
9bccf70c
A
1441 .align 5
1442 .globl EXT(vec_switch)
1443
1444LEXT(vec_switch)
1c79356b
A
1445
1446#if DEBUG
1c79356b
A
1447 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1448 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1449 lwz r1,0(r3)
1450 addi r1,r1,1
1451 stw r1,0(r3)
1c79356b
A
1452#endif /* DEBUG */
1453
9bccf70c
A
1454 mfsprg r26,0 ; Get the per_processor block
1455 mfmsr r19 ; Get the current MSR
1c79356b 1456
9bccf70c
A
1457 mr r25,r4 ; Save the entry savearea
1458 lwz r22,VMXowner(r26) ; Get the thread that owns the vector
1459 lwz r10,PP_ACTIVE_THREAD(r26) ; Get the pointer to the active thread
1460 oris r19,r19,hi16(MASK(MSR_VEC)) ; Enable the vector feature
1461 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
1462
1463 mtmsr r19 ; Enable vector instructions
1c79356b
A
1464 isync
1465
9bccf70c
A
1466 lwz r27,ACT_MACT_PCB(r17) ; Get the current level
1467 lwz r29,curctx(r17) ; Grab the current context anchor of the current thread
0b4e3aa0 1468
9bccf70c
A
1469; R22 has the "old" context anchor
1470; R29 has the "new" context anchor
0b4e3aa0 1471
1c79356b 1472#if FPVECDBG
9bccf70c
A
1473 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1474 li r2,0x5F01 ; (TEST/DEBUG)
1475 mr r3,r22 ; (TEST/DEBUG)
1476 mr r5,r29 ; (TEST/DEBUG)
1477 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1478 sc ; (TEST/DEBUG)
1c79356b
A
1479#endif
1480
9bccf70c 1481 lhz r16,PP_CPU_NUMBER(r26) ; Get the current CPU number
1c79356b 1482
9bccf70c 1483vsvretry: mr. r22,r22 ; See if there is any live vector status
1c79356b 1484
9bccf70c 1485 beq- vsnosave ; No live context, so nothing to save...
1c79356b 1486
9bccf70c 1487 isync ; Make sure we see this in the right order
1c79356b 1488
9bccf70c
A
1489 lwz r30,VMXsave(r22) ; Get the top savearea
1490 cmplw cr2,r22,r29 ; Are both old and new the same context?
1491 lwz r18,VMXcpu(r22) ; Get the last CPU we ran on
1492 cmplwi cr1,r30,0 ; Anything saved yet?
1493 cmplw r18,r16 ; Make sure we are on the right processor
1494 lwz r31,VMXlevel(r22) ; Get the context level
1c79356b 1495
9bccf70c
A
1496 lwz r10,liveVRS(r26) ; Get the right VRSave register
1497
1498 bne- vsnosave ; No, not on the same processor...
1499
1c79356b 1500;
9bccf70c
A
1501; Check to see if the live context has already been saved.
1502; Also check to see if all we are here just to re-enable the MSR
1503; and handle specially if so.
1c79356b 1504;
9bccf70c
A
1505
1506 cmplw r31,r27 ; See if the current and active levels are the same
1507 crand cr0_eq,cr2_eq,cr0_eq ; Remember if both the levels and contexts are the same
1508 li r8,0 ; Clear this
1c79356b 1509
9bccf70c
A
1510 beq- vsthesame ; New and old are the same, just go enable...
1511
1512 cmplwi cr2,r10,0 ; Check VRSave to see if we really need to save anything...
1513 beq- cr1,vsmstsave ; Not saved yet, go do it...
1c79356b 1514
9bccf70c 1515 lwz r11,SAVlevel(r30) ; Get the level of top saved context
1c79356b 1516
9bccf70c
A
1517 cmplw r31,r11 ; Are live and saved the same?
1518
1c79356b 1519#if FPVECDBG
9bccf70c
A
1520 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1521 li r2,0x5F02 ; (TEST/DEBUG)
1522 mr r3,r30 ; (TEST/DEBUG)
1523 mr r5,r31 ; (TEST/DEBUG)
1524 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1525 sc ; (TEST/DEBUG)
1c79356b 1526#endif
9bccf70c
A
1527
1528 bne- vsmstsave ; Live context has not been saved yet...
1529
1530 bne- cr2,vsnosave ; Live context saved and VRSave not 0, no save and keep context...
1c79356b 1531
9bccf70c
A
1532 lwz r4,SAVprev(r30) ; Pick up the previous area
1533 li r5,0 ; Assume this is the only one (which should be the ususal case)
1534 mr. r4,r4 ; Was this the only one?
1535 stw r4,VMXsave(r22) ; Dequeue this savearea
1536 beq+ vsonlyone ; This was the only one...
1537 lwz r5,SAVlevel(r4) ; Get the level associated with previous save
1538
1539vsonlyone: stw r5,VMXlevel(r22) ; Save the level
1540 stw r8,VMXowner(r26) ; Clear owner
1541 eieio
1542 mr r3,r30 ; Copy the savearea we are tossing
1543 bl EXT(save_ret) ; Toss the savearea
1544 b vsnosave ; Go load up the context...
1545
1546 .align 5
1c79356b 1547
9bccf70c
A
1548
1549vsmstsave: stw r8,VMXowner(r26) ; Clear owner
1550 eieio
1551 beq- cr2,vsnosave ; The VRSave was 0, so there is nothing to save...
1552
1553 bl EXT(save_get) ; Go get a savearea
1554
1555 lwz r12,facAct(r22) ; Get the activation associated with the context
1556 stw r3,VMXsave(r22) ; Set this as the latest context savearea for the thread
1557
1558 stw r30,SAVprev(r3) ; Point us to the old context
1559 stw r31,SAVlevel(r3) ; Tag our level
1560 li r7,SAVvector ; Get the vector ID
1561 stw r12,SAVact(r3) ; Make sure we point to the right guy
1562 stb r7,SAVflags+2(r3) ; Set that we have a vector save area
1c79356b 1563
1c79356b 1564#if FPVECDBG
9bccf70c
A
1565 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1566 li r2,0x5F03 ; (TEST/DEBUG)
1567 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1568 sc ; (TEST/DEBUG)
1c79356b
A
1569#endif
1570
9bccf70c
A
1571 lwz r10,liveVRS(r26) ; Get the right VRSave register
1572 lis r9,0x5555 ; Mask with odd bits set
1573 rlwinm r11,r10,1,0,31 ; Shift over 1
1574 ori r9,r9,0x5555 ; Finish mask
1575 or r21,r10,r11 ; After this, even bits show which lines to zap
1576
1577 andc r13,r21,r9 ; Clear out odd bits
1578
1579 la r11,savevr0(r3) ; Point to line 0
1580 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1581 or r24,r13,r24 ; Set the odd bits
1582 ; (bit 0 is line 0, bit 1 is line 8,
1583 ; bit 2 is line 1, bit 3 is line 9, etc.
1584 rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1585 la r21,savevr2(r3) ; Point to line 1
1586 mtcrf 255,r24 ; Load up the CRs
1587 stw r10,savevrvalid(r3) ; Save the validity information
1588 mr r12,r11 ; Start registers off
1c79356b
A
1589;
1590; Save the current vector state
1591;
1592
9bccf70c
A
1593 bf 0,nol0 ; No line 0 to do...
1594 dcba br0,r11 ; Allocate cache line 0
1c79356b
A
1595
1596nol0:
9bccf70c
A
1597 la r11,savevr4(r3) ; Point to line 2
1598 bf 2,nol1 ; No line 1 to do...
1599 dcba br0,r21 ; Allocate cache line 1
1c79356b
A
1600
1601nol1:
9bccf70c
A
1602 la r21,savevr6(r3) ; Point to line 3
1603 bf 4,nol2 ; No line 2 to do...
1604 dcba br0,r11 ; Allocate cache line 2
1c79356b
A
1605
1606nol2:
9bccf70c
A
1607 li r14,16 ; Get offset for odd registers
1608 bf 16,novr0 ; Do not save VR0...
1609 stvxl v0,br0,r12 ; Save VR0
1c79356b
A
1610
1611novr0:
9bccf70c
A
1612 la r13,savevr2(r3) ; Point to V2/V3 pair
1613 bf 17,novr1 ; Do not save VR1...
1614 stvxl v1,r14,r12 ; Save VR1
1c79356b
A
1615
1616novr1:
9bccf70c
A
1617 la r11,savevr8(r3) ; Point to line 4
1618 bf 6,nol3 ; No line 3 to do...
1619 dcba br0,r21 ; Allocate cache line 3
1c79356b
A
1620
1621nol3:
9bccf70c
A
1622 la r12,savevr4(r3) ; Point to V4/V5 pair
1623 bf 18,novr2 ; Do not save VR2...
1624 stvxl v2,br0,r13 ; Save VR2
1c79356b
A
1625
1626novr2:
9bccf70c
A
1627 bf 19,novr3 ; Do not save VR3...
1628 stvxl v3,r14,r13 ; Save VR3
1c79356b
A
1629
1630novr3:
1631;
1632; Note: CR4 is now free
1633;
9bccf70c
A
1634 la r21,savevr10(r3) ; Point to line 5
1635 bf 8,nol4 ; No line 4 to do...
1636 dcba br0,r11 ; Allocate cache line 4
1c79356b
A
1637
1638nol4:
9bccf70c
A
1639 la r13,savevr6(r3) ; Point to R6/R7 pair
1640 bf 20,novr4 ; Do not save VR4...
1641 stvxl v4,br0,r12 ; Save VR4
1c79356b
A
1642
1643novr4:
9bccf70c
A
1644 bf 21,novr5 ; Do not save VR5...
1645 stvxl v5,r14,r12 ; Save VR5
1c79356b
A
1646
1647novr5:
9bccf70c
A
1648 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1649 la r11,savevr12(r3) ; Point to line 6
1650 bf 10,nol5 ; No line 5 to do...
1651 dcba br0,r21 ; Allocate cache line 5
1c79356b
A
1652
1653nol5:
9bccf70c
A
1654 la r12,savevr8(r3) ; Point to V8/V9 pair
1655 bf 22,novr6 ; Do not save VR6...
1656 stvxl v6,br0,r13 ; Save VR6
1c79356b
A
1657
1658novr6:
9bccf70c
A
1659 bf 23,novr7 ; Do not save VR7...
1660 stvxl v7,r14,r13 ; Save VR7
1c79356b
A
1661
1662novr7:
1663;
1664; Note: CR5 is now free
1665;
9bccf70c
A
1666 la r21,savevr14(r3) ; Point to line 7
1667 bf 12,nol6 ; No line 6 to do...
1668 dcba br0,r11 ; Allocate cache line 6
1c79356b
A
1669
1670nol6:
9bccf70c
A
1671 la r13,savevr10(r3) ; Point to V10/V11 pair
1672 bf 24,novr8 ; Do not save VR8...
1673 stvxl v8,br0,r12 ; Save VR8
1c79356b
A
1674
1675novr8:
9bccf70c
A
1676 bf 25,novr9 ; Do not save VR9...
1677 stvxl v9,r14,r12 ; Save VR9
1c79356b
A
1678
1679novr9:
9bccf70c
A
1680 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1681 la r11,savevr16(r3) ; Point to line 8
1682 bf 14,nol7 ; No line 7 to do...
1683 dcba br0,r21 ; Allocate cache line 7
1c79356b
A
1684
1685nol7:
9bccf70c
A
1686 la r12,savevr12(r3) ; Point to V12/V13 pair
1687 bf 26,novr10 ; Do not save VR10...
1688 stvxl v10,br0,r13 ; Save VR10
1c79356b
A
1689
1690novr10:
9bccf70c
A
1691 bf 27,novr11 ; Do not save VR11...
1692 stvxl v11,r14,r13 ; Save VR11
1c79356b
A
1693
1694novr11:
1695
1696;
1697; Note: CR6 is now free
1698;
9bccf70c
A
1699 la r21,savevr18(r3) ; Point to line 9
1700 bf 1,nol8 ; No line 8 to do...
1701 dcba br0,r11 ; Allocate cache line 8
1c79356b
A
1702
1703nol8:
9bccf70c
A
1704 la r13,savevr14(r3) ; Point to V14/V15 pair
1705 bf 28,novr12 ; Do not save VR12...
1706 stvxl v12,br0,r12 ; Save VR12
1c79356b
A
1707
1708novr12:
9bccf70c
A
1709 bf 29,novr13 ; Do not save VR13...
1710 stvxl v13,r14,r12 ; Save VR13
1c79356b
A
1711
1712novr13:
9bccf70c
A
1713 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1714 la r11,savevr20(r3) ; Point to line 10
1715 bf 3,nol9 ; No line 9 to do...
1716 dcba br0,r21 ; Allocate cache line 9
1c79356b
A
1717
1718nol9:
9bccf70c
A
1719 la r12,savevr16(r3) ; Point to V16/V17 pair
1720 bf 30,novr14 ; Do not save VR14...
1721 stvxl v14,br0,r13 ; Save VR14
1c79356b
A
1722
1723novr14:
9bccf70c
A
1724 bf 31,novr15 ; Do not save VR15...
1725 stvxl v15,r14,r13 ; Save VR15
1c79356b
A
1726
1727novr15:
1728;
1729; Note: CR7 is now free
1730;
9bccf70c
A
1731 la r21,savevr22(r3) ; Point to line 11
1732 bf 5,nol10 ; No line 10 to do...
1733 dcba br0,r11 ; Allocate cache line 10
1c79356b
A
1734
1735nol10:
9bccf70c
A
1736 la r13,savevr18(r3) ; Point to V18/V19 pair
1737 bf 16,novr16 ; Do not save VR16...
1738 stvxl v16,br0,r12 ; Save VR16
1c79356b
A
1739
1740novr16:
9bccf70c
A
1741 bf 17,novr17 ; Do not save VR17...
1742 stvxl v17,r14,r12 ; Save VR17
1c79356b
A
1743
1744novr17:
9bccf70c 1745 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1c79356b
A
1746;
1747; Note: All registers have been or are accounted for in CRs
1748;
9bccf70c
A
1749 la r11,savevr24(r3) ; Point to line 12
1750 bf 7,nol11 ; No line 11 to do...
1751 dcba br0,r21 ; Allocate cache line 11
1c79356b
A
1752
1753nol11:
9bccf70c
A
1754 la r12,savevr20(r3) ; Point to V20/V21 pair
1755 bf 18,novr18 ; Do not save VR18...
1756 stvxl v18,br0,r13 ; Save VR18
1c79356b
A
1757
1758novr18:
9bccf70c
A
1759 bf 19,novr19 ; Do not save VR19...
1760 stvxl v19,r14,r13 ; Save VR19
1c79356b
A
1761
1762novr19:
9bccf70c
A
1763 la r21,savevr26(r3) ; Point to line 13
1764 bf 9,nol12 ; No line 12 to do...
1765 dcba br0,r11 ; Allocate cache line 12
1c79356b
A
1766
1767nol12:
9bccf70c
A
1768 la r13,savevr22(r3) ; Point to V22/V23 pair
1769 bf 20,novr20 ; Do not save VR20...
1770 stvxl v20,br0,r12 ; Save VR20
1c79356b
A
1771
1772novr20:
9bccf70c
A
1773 bf 21,novr21 ; Do not save VR21...
1774 stvxl v21,r14,r12 ; Save VR21
1c79356b
A
1775
1776novr21:
9bccf70c
A
1777 la r11,savevr28(r3) ; Point to line 14
1778 bf 11,nol13 ; No line 13 to do...
1779 dcba br0,r21 ; Allocate cache line 13
1c79356b
A
1780
1781nol13:
9bccf70c
A
1782 la r12,savevr24(r3) ; Point to V24/V25 pair
1783 bf 22,novr22 ; Do not save VR22...
1784 stvxl v22,br0,r13 ; Save VR22
1c79356b
A
1785
1786novr22:
9bccf70c
A
1787 bf 23,novr23 ; Do not save VR23...
1788 stvxl v23,r14,r13 ; Save VR23
1c79356b
A
1789
1790novr23:
9bccf70c
A
1791 la r21,savevr30(r3) ; Point to line 15
1792 bf 13,nol14 ; No line 14 to do...
1793 dcba br0,r11 ; Allocate cache line 14
1c79356b
A
1794
1795nol14:
9bccf70c
A
1796 la r13,savevr26(r3) ; Point to V26/V27 pair
1797 bf 24,novr24 ; Do not save VR24...
1798 stvxl v24,br0,r12 ; Save VR24
1c79356b
A
1799
1800novr24:
9bccf70c
A
1801 bf 25,novr25 ; Do not save VR25...
1802 stvxl v25,r14,r12 ; Save VR25
1c79356b
A
1803
1804novr25:
9bccf70c
A
1805 bf 15,nol15 ; No line 15 to do...
1806 dcba br0,r21 ; Allocate cache line 15
1c79356b
A
1807
1808nol15:
1809;
1810; Note: All cache lines allocated now
1811;
9bccf70c
A
1812 la r12,savevr28(r3) ; Point to V28/V29 pair
1813 bf 26,novr26 ; Do not save VR26...
1814 stvxl v26,br0,r13 ; Save VR26
1c79356b
A
1815
1816novr26:
9bccf70c
A
1817 bf 27,novr27 ; Do not save VR27...
1818 stvxl v27,r14,r13 ; Save VR27
1c79356b
A
1819
1820novr27:
9bccf70c
A
1821 la r13,savevr30(r3) ; Point to V30/V31 pair
1822 bf 28,novr28 ; Do not save VR28...
1823 stvxl v28,br0,r12 ; Save VR28
1c79356b
A
1824
1825novr28:
9bccf70c
A
1826 bf 29,novr29 ; Do not save VR29...
1827 stvxl v29,r14,r12 ; Save VR29
1c79356b
A
1828
1829novr29:
9bccf70c
A
1830 bf 30,novr30 ; Do not save VR30...
1831 stvxl v30,br0,r13 ; Save VR30
1c79356b
A
1832
1833novr30:
9bccf70c
A
1834 bf 31,novr31 ; Do not save VR31...
1835 stvxl v31,r14,r13 ; Save VR31
1c79356b
A
1836
1837novr31:
1c79356b
A
1838
1839
1840
9bccf70c
A
1841;
1842; The context is all saved now and the facility is free.
1843;
1844; If we do not we need to fill the registers with junk, because this level has
1845; never used them before and some thieving bastard could hack the old values
1846; of some thread! Just imagine what would happen if they could! Why, nothing
1847; would be safe! My God! It is terrifying!
1848;
1849; Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian)
1850; constant that we may need to fill unused vector registers.
1851;
1c79356b 1852
0b4e3aa0
A
1853
1854
0b4e3aa0 1855
9bccf70c
A
1856vsnosave: vspltisb v31,-10 ; Get 0xF6F6F6F6
1857 lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
1858 vspltisb v30,5 ; Get 0x05050505
1859 lwz r19,VMXcpu(r29) ; Get the last CPU we ran on
1860 vspltish v29,4 ; Get 0x00040004
1861 lwz r14,VMXsave(r29) ; Point to the top of the "new" context stack
1862 vrlb v31,v31,v30 ; Get 0xDEDEDEDE
1863
1864 stw r16,VMXcpu(r29) ; Claim context for us
1865 eieio
1c79356b
A
1866
1867#if FPVECDBG
9bccf70c
A
1868 lwz r13,VMXlevel(r29) ; (TEST/DEBUG)
1869 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1870 li r2,0x5F04 ; (TEST/DEBUG)
1871 mr r1,r15 ; (TEST/DEBUG)
1872 mr r3,r14 ; (TEST/DEBUG)
1873 mr r5,r13 ; (TEST/DEBUG)
1874 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1875 sc ; (TEST/DEBUG)
1c79356b 1876#endif
9bccf70c
A
1877
1878 lis r18,hi16(EXT(per_proc_info)) ; Set base per_proc
1879 vspltisb v28,-2 ; Get 0xFEFEFEFE
1880 mulli r19,r19,ppSize ; Find offset to the owner per_proc
1881 vsubuhm v31,v31,v29 ; Get 0xDEDADEDA
1882 ori r18,r18,lo16(EXT(per_proc_info)) ; Set base per_proc
1883 vpkpx v30,v28,v3 ; Get 0x7FFF7FFF
1884 li r16,VMXowner ; Displacement to vector owner
1885 add r19,r18,r19 ; Point to the owner per_proc
1886 vrlb v31,v31,v29 ; Get 0xDEADDEAD
1887 li r0,0
1888
1889vsinvothr: lwarx r18,r16,r19 ; Get the owner
1890 cmplw r18,r29 ; Does he still have this context?
1891 bne vsinvoths ; Nope...
1892 stwcx. r0,r16,r19 ; Try to invalidate it
1893 bne- vsinvothr ; Try again if there was a collision...
1894
1895
1896vsinvoths: cmplwi cr1,r14,0 ; Do we possibly have some context to load?
1897 vmrghh v31,v30,v31 ; Get 0x7FFFDEAD. V31 keeps this value until the bitter end
1898 stw r15,VMXlevel(r29) ; Set the "new" active level
1899 eieio
1900 stw r29,VMXowner(r26) ; Mark us as having the live context
1c79356b 1901
9bccf70c
A
1902 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
1903
1904 lwz r3,SAVprev(r14) ; Get the previous context
1905 lwz r0,SAVlevel(r14) ; Get the level of first facility savearea
1906 cmplw r0,r15 ; Top level correct to load?
1907 bne- ProtectTheAmericanWay ; No, go initialize...
1c79356b 1908
9bccf70c
A
1909 stw r3,VMXsave(r29) ; Pop the context (we will toss the savearea later)
1910
1c79356b 1911#if FPVECDBG
9bccf70c
A
1912 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
1913 li r2,0x5F05 ; (TEST/DEBUG)
1914 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
1915 sc ; (TEST/DEBUG)
1c79356b
A
1916#endif
1917
9bccf70c
A
1918 lwz r22,savevrsave(r25) ; Get the most current VRSAVE
1919 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
1920 lis r9,0x5555 ; Mask with odd bits set
1921 and r10,r10,r22 ; Figure out just what registers need to be loaded
1922 ori r9,r9,0x5555 ; Finish mask
1923 rlwinm r11,r10,1,0,31 ; Shift over 1
1924 or r12,r10,r11 ; After this, even bits show which lines to touch
1925 andc r13,r12,r9 ; Clear out odd bits
1926
1927 la r20,savevr0(r14) ; Point to line 0
1928 rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1929 la r21,savevr2(r3) ; Point to line 1
1930 or r3,r13,r3 ; Set the odd bits
1931 ; (bit 0 is line 0, bit 1 is line 8,
1932 ; bit 2 is line 1, bit 3 is line 9, etc.
1933 rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1934 mtcrf 255,r3 ; Load up the CRs
1935 mr r22,r20 ; Start registers off
1c79356b
A
1936;
1937; Load the new vector state
1938;
1939
9bccf70c
A
1940 bf 0,lnol0 ; No line 0 to do...
1941 dcbt br0,r20 ; Touch cache line 0
1c79356b
A
1942
1943lnol0:
9bccf70c
A
1944 la r20,savevr4(r14) ; Point to line 2
1945 bf 2,lnol1 ; No line 1 to do...
1946 dcbt br0,r21 ; Touch cache line 1
1c79356b
A
1947
1948lnol1:
9bccf70c
A
1949 la r21,savevr6(r14) ; Point to line 3
1950 bf 4,lnol2 ; No line 2 to do...
1951 dcbt br0,r20 ; Touch cache line 2
1c79356b
A
1952
1953lnol2:
9bccf70c
A
1954 li r30,16 ; Get offset for odd registers
1955 bf 16,lnovr0 ; Do not restore VR0...
1956 lvxl v0,br0,r22 ; Restore VR0
1c79356b
A
1957
1958lnovr0:
9bccf70c
A
1959 la r23,savevr2(r14) ; Point to V2/V3 pair
1960 bf 17,lnovr1 ; Do not restore VR1...
1961 lvxl v1,r30,r22 ; Restore VR1
1c79356b
A
1962
1963lnovr1:
9bccf70c
A
1964 la r20,savevr8(r14) ; Point to line 4
1965 bf 6,lnol3 ; No line 3 to do...
1966 dcbt br0,r21 ; Touch cache line 3
1c79356b
A
1967
1968lnol3:
9bccf70c
A
1969 la r22,savevr4(r14) ; Point to V4/V5 pair
1970 bf 18,lnovr2 ; Do not restore VR2...
1971 lvxl v2,br0,r23 ; Restore VR2
1c79356b
A
1972
1973lnovr2:
9bccf70c
A
1974 bf 19,lnovr3 ; Do not restore VR3...
1975 lvxl v3,r30,r23 ; Restore VR3
1c79356b
A
1976
1977lnovr3:
1978;
1979; Note: CR4 is now free
1980;
9bccf70c
A
1981 la r21,savevr10(r14) ; Point to line 5
1982 bf 8,lnol4 ; No line 4 to do...
1983 dcbt br0,r20 ; Touch cache line 4
1c79356b
A
1984
1985lnol4:
9bccf70c
A
1986 la r23,savevr6(r14) ; Point to R6/R7 pair
1987 bf 20,lnovr4 ; Do not restore VR4...
1988 lvxl v4,br0,r22 ; Restore VR4
1c79356b
A
1989
1990lnovr4:
9bccf70c
A
1991 bf 21,lnovr5 ; Do not restore VR5...
1992 lvxl v5,r30,r22 ; Restore VR5
1c79356b
A
1993
1994lnovr5:
9bccf70c
A
1995 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1996 la r20,savevr12(r14) ; Point to line 6
1997 bf 10,lnol5 ; No line 5 to do...
1998 dcbt br0,r21 ; Touch cache line 5
1c79356b
A
1999
2000lnol5:
9bccf70c
A
2001 la r22,savevr8(r14) ; Point to V8/V9 pair
2002 bf 22,lnovr6 ; Do not restore VR6...
2003 lvxl v6,br0,r23 ; Restore VR6
1c79356b
A
2004
2005lnovr6:
9bccf70c
A
2006 bf 23,lnovr7 ; Do not restore VR7...
2007 lvxl v7,r30,r23 ; Restore VR7
1c79356b
A
2008
2009lnovr7:
2010;
2011; Note: CR5 is now free
2012;
9bccf70c
A
2013 la r21,savevr14(r14) ; Point to line 7
2014 bf 12,lnol6 ; No line 6 to do...
2015 dcbt br0,r20 ; Touch cache line 6
1c79356b
A
2016
2017lnol6:
9bccf70c
A
2018 la r23,savevr10(r14) ; Point to V10/V11 pair
2019 bf 24,lnovr8 ; Do not restore VR8...
2020 lvxl v8,br0,r22 ; Restore VR8
1c79356b
A
2021
2022lnovr8:
9bccf70c
A
2023 bf 25,lnovr9 ; Do not save VR9...
2024 lvxl v9,r30,r22 ; Restore VR9
1c79356b
A
2025
2026lnovr9:
9bccf70c
A
2027 mtcrf 0x04,r10 ; Set CRs for registers 20-23
2028 la r20,savevr16(r14) ; Point to line 8
2029 bf 14,lnol7 ; No line 7 to do...
2030 dcbt br0,r21 ; Touch cache line 7
1c79356b
A
2031
2032lnol7:
9bccf70c
A
2033 la r22,savevr12(r14) ; Point to V12/V13 pair
2034 bf 26,lnovr10 ; Do not restore VR10...
2035 lvxl v10,br0,r23 ; Restore VR10
1c79356b
A
2036
2037lnovr10:
9bccf70c
A
2038 bf 27,lnovr11 ; Do not restore VR11...
2039 lvxl v11,r30,r23 ; Restore VR11
1c79356b
A
2040
2041lnovr11:
2042
2043;
2044; Note: CR6 is now free
2045;
9bccf70c
A
2046 la r21,savevr18(r14) ; Point to line 9
2047 bf 1,lnol8 ; No line 8 to do...
2048 dcbt br0,r20 ; Touch cache line 8
1c79356b
A
2049
2050lnol8:
9bccf70c
A
2051 la r23,savevr14(r14) ; Point to V14/V15 pair
2052 bf 28,lnovr12 ; Do not restore VR12...
2053 lvxl v12,br0,r22 ; Restore VR12
1c79356b
A
2054
2055lnovr12:
9bccf70c
A
2056 bf 29,lnovr13 ; Do not restore VR13...
2057 lvxl v13,r30,r22 ; Restore VR13
1c79356b
A
2058
2059lnovr13:
9bccf70c
A
2060 mtcrf 0x02,r10 ; Set CRs for registers 24-27
2061 la r20,savevr20(r14) ; Point to line 10
2062 bf 3,lnol9 ; No line 9 to do...
2063 dcbt br0,r21 ; Touch cache line 9
1c79356b
A
2064
2065lnol9:
9bccf70c
A
2066 la r22,savevr16(r14) ; Point to V16/V17 pair
2067 bf 30,lnovr14 ; Do not restore VR14...
2068 lvxl v14,br0,r23 ; Restore VR14
1c79356b
A
2069
2070lnovr14:
9bccf70c
A
2071 bf 31,lnovr15 ; Do not restore VR15...
2072 lvxl v15,r30,r23 ; Restore VR15
1c79356b
A
2073
2074lnovr15:
2075;
2076; Note: CR7 is now free
2077;
9bccf70c
A
2078 la r21,savevr22(r14) ; Point to line 11
2079 bf 5,lnol10 ; No line 10 to do...
2080 dcbt br0,r20 ; Touch cache line 10
1c79356b
A
2081
2082lnol10:
9bccf70c
A
2083 la r23,savevr18(r14) ; Point to V18/V19 pair
2084 bf 16,lnovr16 ; Do not restore VR16...
2085 lvxl v16,br0,r22 ; Restore VR16
1c79356b
A
2086
2087lnovr16:
9bccf70c
A
2088 bf 17,lnovr17 ; Do not restore VR17...
2089 lvxl v17,r30,r22 ; Restore VR17
1c79356b
A
2090
2091lnovr17:
9bccf70c 2092 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1c79356b
A
2093;
2094; Note: All registers have been or are accounted for in CRs
2095;
9bccf70c
A
2096 la r20,savevr24(r14) ; Point to line 12
2097 bf 7,lnol11 ; No line 11 to do...
2098 dcbt br0,r21 ; Touch cache line 11
1c79356b
A
2099
2100lnol11:
9bccf70c
A
2101 la r22,savevr20(r14) ; Point to V20/V21 pair
2102 bf 18,lnovr18 ; Do not restore VR18...
2103 lvxl v18,br0,r23 ; Restore VR18
1c79356b
A
2104
2105lnovr18:
9bccf70c
A
2106 bf 19,lnovr19 ; Do not restore VR19...
2107 lvxl v19,r30,r23 ; Restore VR19
1c79356b
A
2108
2109lnovr19:
9bccf70c
A
2110 la r21,savevr26(r14) ; Point to line 13
2111 bf 9,lnol12 ; No line 12 to do...
2112 dcbt br0,r20 ; Touch cache line 12
1c79356b
A
2113
2114lnol12:
9bccf70c
A
2115 la r23,savevr22(r14) ; Point to V22/V23 pair
2116 bf 20,lnovr20 ; Do not restore VR20...
2117 lvxl v20,br0,r22 ; Restore VR20
1c79356b
A
2118
2119lnovr20:
9bccf70c
A
2120 bf 21,lnovr21 ; Do not restore VR21...
2121 lvxl v21,r30,r22 ; Restore VR21
1c79356b
A
2122
2123lnovr21:
9bccf70c
A
2124 la r20,savevr28(r14) ; Point to line 14
2125 bf 11,lnol13 ; No line 13 to do...
2126 dcbt br0,r21 ; Touch cache line 13
1c79356b
A
2127
2128lnol13:
9bccf70c
A
2129 la r22,savevr24(r14) ; Point to V24/V25 pair
2130 bf 22,lnovr22 ; Do not restore VR22...
2131 lvxl v22,br0,r23 ; Restore VR22
1c79356b
A
2132
2133lnovr22:
9bccf70c
A
2134 bf 23,lnovr23 ; Do not restore VR23...
2135 lvxl v23,r30,r23 ; Restore VR23
1c79356b
A
2136
2137lnovr23:
9bccf70c
A
2138 la r21,savevr30(r14) ; Point to line 15
2139 bf 13,lnol14 ; No line 14 to do...
2140 dcbt br0,r20 ; Touch cache line 14
1c79356b
A
2141
2142lnol14:
9bccf70c
A
2143 la r23,savevr26(r14) ; Point to V26/V27 pair
2144 bf 24,lnovr24 ; Do not restore VR24...
2145 lvxl v24,br0,r22 ; Restore VR24
1c79356b
A
2146
2147lnovr24:
9bccf70c
A
2148 bf 25,lnovr25 ; Do not restore VR25...
2149 lvxl v25,r30,r22 ; Restore VR25
1c79356b
A
2150
2151lnovr25:
9bccf70c
A
2152 bf 15,lnol15 ; No line 15 to do...
2153 dcbt br0,r21 ; Touch cache line 15
1c79356b
A
2154
2155lnol15:
2156;
2157; Note: All needed cache lines have been touched now
2158;
9bccf70c
A
2159 la r22,savevr28(r14) ; Point to V28/V29 pair
2160 bf 26,lnovr26 ; Do not restore VR26...
2161 lvxl v26,br0,r23 ; Restore VR26
1c79356b
A
2162
2163lnovr26:
9bccf70c
A
2164 bf 27,lnovr27 ; Do not restore VR27...
2165 lvxl v27,r30,r23 ; Restore VR27
1c79356b
A
2166
2167lnovr27:
9bccf70c
A
2168 la r23,savevr30(r14) ; Point to V30/V31 pair
2169 bf 28,lnovr28 ; Do not restore VR28...
2170 lvxl v28,br0,r22 ; Restore VR28
1c79356b
A
2171
2172lnovr28:
9bccf70c
A
2173 bf 29,lnovr29 ; Do not restore VR29...
2174 lvxl v29,r30,r22 ; Restore VR29
1c79356b
A
2175
2176lnovr29:
9bccf70c
A
2177 bf 30,lnovr30 ; Do not restore VR30...
2178 lvxl v30,br0,r23 ; Restore VR30
1c79356b
A
2179
2180lnovr30:
2181;
2182; Everything is restored now except for VR31. We need it to get
9bccf70c
A
2183; the QNaNBarbarian value to put into idle vector registers.
2184; Note: V31 was set above to QNaNbarbarian
1c79356b
A
2185;
2186
9bccf70c
A
2187 cmpwi r10,-1 ; Handle the quick case of all registers in use
2188 beq- mstlvr31 ; Not likely, but all are in use...
2189 mtcrf 255,r10 ; Get mask of valid registers
1c79356b 2190
9bccf70c
A
2191 bt 0,ni0 ; Register is ok already...
2192 vor v0,v31,v31 ; Copy into the next register
1c79356b 2193ni0:
9bccf70c
A
2194 bt 1,ni1 ; Register is ok already...
2195 vor v1,v31,v31 ; Copy into the next register
1c79356b 2196ni1:
9bccf70c
A
2197 bt 2,ni2 ; Register is ok already...
2198 vor v2,v31,v31 ; Copy into the next register
1c79356b 2199ni2:
9bccf70c
A
2200 bt 3,ni3 ; Register is ok already...
2201 vor v3,v31,v31 ; Copy into the next register
1c79356b 2202ni3:
9bccf70c
A
2203 bt 4,ni4 ; Register is ok already...
2204 vor v4,v31,v31 ; Copy into the next register
1c79356b 2205ni4:
9bccf70c
A
2206 bt 5,ni5 ; Register is ok already...
2207 vor v5,v31,v31 ; Copy into the next register
1c79356b 2208ni5:
9bccf70c
A
2209 bt 6,ni6 ; Register is ok already...
2210 vor v6,v31,v31 ; Copy into the next register
1c79356b 2211ni6:
9bccf70c
A
2212 bt 7,ni7 ; Register is ok already...
2213 vor v7,v31,v31 ; Copy into the next register
1c79356b 2214ni7:
9bccf70c
A
2215 bt 8,ni8 ; Register is ok already...
2216 vor v8,v31,v31 ; Copy into the next register
1c79356b 2217ni8:
9bccf70c
A
2218 bt 9,ni9 ; Register is ok already...
2219 vor v9,v31,v31 ; Copy into the next register
1c79356b 2220ni9:
9bccf70c
A
2221 bt 10,ni10 ; Register is ok already...
2222 vor v10,v31,v31 ; Copy into the next register
1c79356b 2223ni10:
9bccf70c
A
2224 bt 11,ni11 ; Register is ok already...
2225 vor v11,v31,v31 ; Copy into the next register
1c79356b 2226ni11:
9bccf70c
A
2227 bt 12,ni12 ; Register is ok already...
2228 vor v12,v31,v31 ; Copy into the next register
1c79356b 2229ni12:
9bccf70c
A
2230 bt 13,ni13 ; Register is ok already...
2231 vor v13,v31,v31 ; Copy into the next register
1c79356b 2232ni13:
9bccf70c
A
2233 bt 14,ni14 ; Register is ok already...
2234 vor v14,v31,v31 ; Copy into the next register
1c79356b 2235ni14:
9bccf70c
A
2236 bt 15,ni15 ; Register is ok already...
2237 vor v15,v31,v31 ; Copy into the next register
1c79356b 2238ni15:
9bccf70c
A
2239 bt 16,ni16 ; Register is ok already...
2240 vor v16,v31,v31 ; Copy into the next register
1c79356b 2241ni16:
9bccf70c
A
2242 bt 17,ni17 ; Register is ok already...
2243 vor v17,v31,v31 ; Copy into the next register
1c79356b 2244ni17:
9bccf70c
A
2245 bt 18,ni18 ; Register is ok already...
2246 vor v18,v31,v31 ; Copy into the next register
1c79356b 2247ni18:
9bccf70c
A
2248 bt 19,ni19 ; Register is ok already...
2249 vor v19,v31,v31 ; Copy into the next register
1c79356b 2250ni19:
9bccf70c
A
2251 bt 20,ni20 ; Register is ok already...
2252 vor v20,v31,v31 ; Copy into the next register
1c79356b 2253ni20:
9bccf70c
A
2254 bt 21,ni21 ; Register is ok already...
2255 vor v21,v31,v31 ; Copy into the next register
1c79356b 2256ni21:
9bccf70c
A
2257 bt 22,ni22 ; Register is ok already...
2258 vor v22,v31,v31 ; Copy into the next register
1c79356b 2259ni22:
9bccf70c
A
2260 bt 23,ni23 ; Register is ok already...
2261 vor v23,v31,v31 ; Copy into the next register
1c79356b 2262ni23:
9bccf70c
A
2263 bt 24,ni24 ; Register is ok already...
2264 vor v24,v31,v31 ; Copy into the next register
1c79356b 2265ni24:
9bccf70c
A
2266 bt 25,ni25 ; Register is ok already...
2267 vor v25,v31,v31 ; Copy into the next register
1c79356b 2268ni25:
9bccf70c
A
2269 bt 26,ni26 ; Register is ok already...
2270 vor v26,v31,v31 ; Copy into the next register
1c79356b 2271ni26:
9bccf70c
A
2272 bt 27,ni27 ; Register is ok already...
2273 vor v27,v31,v31 ; Copy into the next register
1c79356b 2274ni27:
9bccf70c
A
2275 bt 28,ni28 ; Register is ok already...
2276 vor v28,v31,v31 ; Copy into the next register
1c79356b 2277ni28:
9bccf70c
A
2278 bt 29,ni29 ; Register is ok already...
2279 vor v29,v31,v31 ; Copy into the next register
1c79356b 2280ni29:
9bccf70c
A
2281 bt 30,ni30 ; Register is ok already...
2282 vor v30,v31,v31 ; Copy into the next register
1c79356b 2283ni30:
9bccf70c 2284 bf 31,lnovr31 ; V31 is empty, no need to restore...
1c79356b 2285
9bccf70c 2286mstlvr31: lvxl v31,r30,r23 ; Restore VR31
1c79356b 2287
9bccf70c
A
2288lnovr31: mr r3,r14 ; Get the old savearea (we popped it before)
2289 bl EXT(save_ret) ; Toss it
1c79356b 2290
9bccf70c
A
2291vrenable: lwz r8,savesrr1(r25) ; Get the msr of the interrupted guy
2292 rlwinm r5,r25,0,0,19 ; Get the page address of the savearea
2293 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
2294 lwz r10,ACT_MACT_SPF(r17) ; Get the special flags
2295 lwz r5,SACvrswap(r5) ; Get Virtual to Real translation
1c79356b 2296 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
9bccf70c
A
2297 rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are doing this for user state
2298 stw r8,savesrr1(r25) ; Set the msr of the interrupted guy
2299 xor r3,r25,r5 ; Get the real address of the savearea
b4c24cb9 2300 beq- vrnuser ; We are not user state...
9bccf70c
A
2301 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
2302 stw r10,spcFlags(r26) ; Set per_proc copy
1c79356b
A
2303
2304vrnuser:
2305#if FPVECDBG
9bccf70c
A
2306 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2307 li r2,0x5F07 ; (TEST/DEBUG)
2308 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2309 sc ; (TEST/DEBUG)
1c79356b 2310#endif
9bccf70c 2311 b EXT(exception_exit) ; Exit to the fray...
1c79356b
A
2312
2313/*
2314 * Initialize the registers to some bogus value
1c79356b
A
2315 */
2316
2317ProtectTheAmericanWay:
2318
2319#if FPVECDBG
9bccf70c
A
2320 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2321 li r2,0x5F06 ; (TEST/DEBUG)
2322 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2323 sc ; (TEST/DEBUG)
1c79356b 2324#endif
9bccf70c
A
2325
2326 vor v0,v31,v31 ; Copy into the next register
2327 vor v1,v31,v31 ; Copy into the next register
2328 vor v2,v31,v31 ; Copy into the next register
2329 vor v3,v31,v31 ; Copy into the next register
2330 vor v4,v31,v31 ; Copy into the next register
2331 vor v5,v31,v31 ; Copy into the next register
2332 vor v6,v31,v31 ; Copy into the next register
2333 vor v7,v31,v31 ; Copy into the next register
2334 vor v8,v31,v31 ; Copy into the next register
2335 vor v9,v31,v31 ; Copy into the next register
2336 vor v10,v31,v31 ; Copy into the next register
2337 vor v11,v31,v31 ; Copy into the next register
2338 vor v12,v31,v31 ; Copy into the next register
2339 vor v13,v31,v31 ; Copy into the next register
2340 vor v14,v31,v31 ; Copy into the next register
2341 vor v15,v31,v31 ; Copy into the next register
2342 vor v16,v31,v31 ; Copy into the next register
2343 vor v17,v31,v31 ; Copy into the next register
2344 vor v18,v31,v31 ; Copy into the next register
2345 vor v19,v31,v31 ; Copy into the next register
2346 vor v20,v31,v31 ; Copy into the next register
2347 vor v21,v31,v31 ; Copy into the next register
2348 vor v22,v31,v31 ; Copy into the next register
2349 vor v23,v31,v31 ; Copy into the next register
2350 vor v24,v31,v31 ; Copy into the next register
2351 vor v25,v31,v31 ; Copy into the next register
2352 vor v26,v31,v31 ; Copy into the next register
2353 vor v27,v31,v31 ; Copy into the next register
2354 vor v28,v31,v31 ; Copy into the next register
2355 vor v29,v31,v31 ; Copy into the next register
2356 vor v30,v31,v31 ; Copy into the next register
2357 b vrenable ; Finish setting it all up...
2358
2359
2360
2361;
2362; We get here when we are switching to the same context at the same level and the context
2363; is still live. Essentially, all we are doing is turning on the faility. It may have
2364; gotten turned off due to doing a context save for the current level or a context switch
2365; back to the live guy.
2366;
2367
2368 .align 5
2369
2370vsthesame:
2371
2372#if FPVECDBG
2373 lis r0,hi16(CutTrace) ; (TEST/DEBUG)
2374 li r2,0x5F0A ; (TEST/DEBUG)
2375 oris r0,r0,lo16(CutTrace) ; (TEST/DEBUG)
2376 sc ; (TEST/DEBUG)
2377#endif
2378 beq- cr1,vrenable ; Not saved yet, nothing to pop, go enable and exit...
2379
2380 lwz r11,SAVlevel(r30) ; Get the level of top saved context
2381 lwz r14,SAVprev(r30) ; Get the previous savearea
2382
2383 cmplw r11,r31 ; Are live and saved the same?
2384
2385 bne+ vrenable ; Level not the same, nothing to pop, go enable and exit...
2386
2387 mr r3,r30 ; Get the old savearea (we popped it before)
2388 bl EXT(save_ret) ; Toss it
2389 b vrenable ; Go enable and exit...
2390
2391
2392;
2393; This function invalidates any live vector context for the passed in facility_context.
2394; This is intended to be called just before act_machine_sv_free tosses saveareas.
1c79356b 2395;
1c79356b 2396
9bccf70c
A
2397 .align 5
2398 .globl EXT(toss_live_vec)
1c79356b 2399
9bccf70c
A
2400LEXT(toss_live_vec)
2401
2402 mfmsr r9 ; Get the MSR
2403 rlwinm r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interuptions
2404 rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now?
2405 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Make sure vector is turned off
2406 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Make sure fpu is turned off
2407 mtmsr r0 ; No interruptions
2408 isync
2409 beq+ tlvnotours ; Vector off, can not be live here...
1c79356b 2410
9bccf70c
A
2411 mfsprg r8,0 ; Get the per proc
2412
2413;
2414; Note that at this point, since vecs are on, we are the owner
2415; of live state on this processor
2416;
2417
2418 lwz r6,VMXowner(r8) ; Get the thread that owns the vector
2419 li r0,0 ; Clear this just in case we need it
2420 cmplw r6,r3 ; Are we tossing our own context?
2421 bne- tlvnotours ; Nope...
2422
2423 vspltish v1,1 ; Turn on the non-Java bit and saturate
2424 vspltisw v0,1 ; Turn on the saturate bit
2425 vxor v1,v1,v0 ; Turn off saturate
2426 mtspr vrsave,r0 ; Clear VRSAVE
2427 mtvscr v1 ; Set the non-java, no saturate status
2428
2429tlvnotours: lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2430 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2431 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2432 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2433 li r10,VMXowner ; Displacement to vector owner
2434 add r11,r12,r11 ; Point to the owner per_proc
2435 li r0,0 ; Set a 0 to invalidate context
2436
2437tlvinvothr: lwarx r12,r10,r11 ; Get the owner
2438 cmplw r12,r3 ; Does he still have this context?
2439 bne+ tlvexit ; Nope, leave...
2440 stwcx. r0,r10,r11 ; Try to invalidate it
2441 bne- tlvinvothr ; Try again if there was a collision...
2442
2443tlvexit: mtmsr r9 ; Restore interruptions
2444 isync ; Could be turning off vectors here
2445 blr ; Leave....
2446
2447#if 0
2448;
2449; This function invalidates any live vector context for the passed in facility_context
2450; if the level is current. It also tosses the corresponding savearea if there is one.
2451; This function is primarily used whenever we detect a VRSave that is all zeros.
2452;
2453
2454 .align 5
2455 .globl EXT(vec_trash)
2456
2457LEXT(vec_trash)
2458
2459 lwz r12,facAct(r3) ; Get the activation
2460 lwz r11,VMXlevel(r3) ; Get the context level
2461 lwz r10,ACT_MACT_PCB(r12) ; Grab the current level for the thread
2462 lwz r9,VMXsave(r3) ; Get the savearea, if any
2463 cmplw r10,r11 ; Are we at the right level?
2464 cmplwi cr1,r9,0 ; Remember if there is a savearea
2465 bnelr+ ; No, we do nothing...
2466
2467 lwz r11,VMXcpu(r3) ; Get the cpu on which we last loaded context
2468 lis r12,hi16(EXT(per_proc_info)) ; Set base per_proc
2469 mulli r11,r11,ppSize ; Find offset to the owner per_proc
2470 ori r12,r12,lo16(EXT(per_proc_info)) ; Set base per_proc
2471 li r10,VMXowner ; Displacement to vector owner
2472 add r11,r12,r11 ; Point to the owner per_proc
2473 li r0,0 ; Set a 0 to invalidate context
2474
2475vtinvothr: lwarx r12,r10,r11 ; Get the owner
2476 cmplw r12,r3 ; Does he still have this context?
2477 bne vtnotlive ; Nope, not live anywhere...
2478 stwcx. r0,r10,r11 ; Try to invalidate it
2479 bne- vtinvothr ; Try again if there was a collision...
2480
2481vtnotlive: beqlr+ cr1 ; Leave if there is no savearea
2482 lwz r8,SAVlevel(r9) ; Get the level of the savearea
2483 cmplw r8,r11 ; Savearea for the current level?
2484 bnelr+ ; No, nothing to release...
2485
2486 lwz r8,SAVprev(r9) ; Pick up the previous area
2487 mr. r8,r8 ; Is there a previous?
2488 beq- vtnoprev ; Nope...
2489 lwz r7,SAVlevel(r8) ; Get the level associated with save
2490
2491vtnoprev: stw r8,VMXsave(r3) ; Dequeue this savearea
2492 stw r7,VMXlevel(r3) ; Pop the level
2493
2494 mr r3,r9 ; Get the savearea to release
2495 b EXT(save_ret) ; Go and toss the save area (note, we will return from there)...
2496#endif
2497
2498;
2499; Just some test code to force vector and/or floating point in the kernel
2500;
2501
2502 .align 5
2503 .globl EXT(fctx_test)
1c79356b 2504
9bccf70c
A
2505LEXT(fctx_test)
2506
2507 mfsprg r3,0 ; Get the per_proc block
2508 lwz r3,PP_ACTIVE_THREAD(r3) ; Get the thread pointer
2509 mr. r3,r3 ; Are we actually up and running?
2510 beqlr- ; No...
2511
2512 fmr f0,f0 ; Use floating point
2513 mftb r4 ; Get time base for a random number
2514 li r5,1 ; Get a potential vrsave to use
2515 andi. r4,r4,0x3F ; Get a number from 0 - 63
2516 slw r5,r5,r4 ; Choose a register to save (should be 0 half the time)
2517 mtspr vrsave,r5 ; Set VRSave
2518 vor v0,v0,v0 ; Use vectors
2519 blr