2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
30 #include <kern/thread.h>
31 #include <kern/thread_act.h>
32 #include <kern/misc_protos.h>
33 #include <mach/ppc/thread_status.h>
34 #include <ppc/proc_reg.h>
35 #include <ppc/exception.h>
36 #include <ppc/misc_protos.h>
37 #include <ppc/savearea.h>
38 #include <ppc/thread_act.h>
39 #include <ppc/Firmware.h>
41 #include <vm/vm_map.h>
43 extern unsigned int killprint
;
44 extern double FloatInit
;
45 extern unsigned long QNaNbarbarian
[4];
46 extern void thread_bootstrap_return(void);
47 extern struct Saveanchor saveanchor
;
48 extern int real_ncpus
; /* Number of actual CPUs */
50 #define USRSTACK 0xc0000000
71 unsigned int get_msr_exportmask(void);
72 unsigned int get_msr_nbits(void);
73 unsigned int get_msr_rbits(void);
74 void ppc_checkthreadstate(void *, int);
75 void thread_set_child(thread_act_t child
, int pid
);
76 void thread_set_parent(thread_act_t parent
, int pid
);
79 * Maps state flavor to number of words in the state:
81 unsigned int state_count
[] = {
83 PPC_THREAD_STATE_COUNT
,
84 PPC_FLOAT_STATE_COUNT
,
85 PPC_EXCEPTION_STATE_COUNT
,
86 PPC_VECTOR_STATE_COUNT
,
87 PPC_THREAD_STATE64_COUNT
,
88 PPC_EXCEPTION_STATE64_COUNT
,
94 * Get the status of the specified thread.
98 act_machine_get_state(
100 thread_flavor_t flavor
,
101 thread_state_t tstate
,
102 mach_msg_type_number_t
*count
)
105 register struct savearea
*sv
; /* Pointer to the context savearea */
106 register savearea_fpu
*fsv
;
107 register savearea_vec
*vsv
;
110 unsigned int vrvalidwrk
;
112 register struct ppc_thread_state
*ts
;
113 register struct ppc_thread_state64
*xts
;
114 register struct ppc_exception_state
*es
;
115 register struct ppc_exception_state64
*xes
;
116 register struct ppc_float_state
*fs
;
117 register struct ppc_vector_state
*vs
;
119 genuser
= find_user_regs(thr_act
); /* Find the current user general context for this activation */
123 case THREAD_STATE_FLAVOR_LIST
:
126 return (KERN_INVALID_ARGUMENT
);
129 tstate
[0] = PPC_THREAD_STATE
;
130 tstate
[1] = PPC_FLOAT_STATE
;
131 tstate
[2] = PPC_EXCEPTION_STATE
;
132 tstate
[3] = PPC_VECTOR_STATE
;
133 tstate
[4] = PPC_THREAD_STATE64
;
134 tstate
[5] = PPC_EXCEPTION_STATE64
;
139 case PPC_THREAD_STATE
:
141 if (*count
< PPC_THREAD_STATE_COUNT
) { /* Is the count ok? */
142 return KERN_INVALID_ARGUMENT
;
145 ts
= (struct ppc_thread_state
*) tstate
;
147 sv
= genuser
; /* Copy this over */
149 if(sv
) { /* Is there a save area yet? */
150 ts
->r0
= (unsigned int)sv
->save_r0
;
151 ts
->r1
= (unsigned int)sv
->save_r1
;
152 ts
->r2
= (unsigned int)sv
->save_r2
;
153 ts
->r3
= (unsigned int)sv
->save_r3
;
154 ts
->r4
= (unsigned int)sv
->save_r4
;
155 ts
->r5
= (unsigned int)sv
->save_r5
;
156 ts
->r6
= (unsigned int)sv
->save_r6
;
157 ts
->r7
= (unsigned int)sv
->save_r7
;
158 ts
->r8
= (unsigned int)sv
->save_r8
;
159 ts
->r9
= (unsigned int)sv
->save_r9
;
160 ts
->r10
= (unsigned int)sv
->save_r10
;
161 ts
->r11
= (unsigned int)sv
->save_r11
;
162 ts
->r12
= (unsigned int)sv
->save_r12
;
163 ts
->r13
= (unsigned int)sv
->save_r13
;
164 ts
->r14
= (unsigned int)sv
->save_r14
;
165 ts
->r15
= (unsigned int)sv
->save_r15
;
166 ts
->r16
= (unsigned int)sv
->save_r16
;
167 ts
->r17
= (unsigned int)sv
->save_r17
;
168 ts
->r18
= (unsigned int)sv
->save_r18
;
169 ts
->r19
= (unsigned int)sv
->save_r19
;
170 ts
->r20
= (unsigned int)sv
->save_r20
;
171 ts
->r21
= (unsigned int)sv
->save_r21
;
172 ts
->r22
= (unsigned int)sv
->save_r22
;
173 ts
->r23
= (unsigned int)sv
->save_r23
;
174 ts
->r24
= (unsigned int)sv
->save_r24
;
175 ts
->r25
= (unsigned int)sv
->save_r25
;
176 ts
->r26
= (unsigned int)sv
->save_r26
;
177 ts
->r27
= (unsigned int)sv
->save_r27
;
178 ts
->r28
= (unsigned int)sv
->save_r28
;
179 ts
->r29
= (unsigned int)sv
->save_r29
;
180 ts
->r30
= (unsigned int)sv
->save_r30
;
181 ts
->r31
= (unsigned int)sv
->save_r31
;
182 ts
->cr
= (unsigned int)sv
->save_cr
;
183 ts
->xer
= (unsigned int)sv
->save_xer
;
184 ts
->lr
= (unsigned int)sv
->save_lr
;
185 ts
->ctr
= (unsigned int)sv
->save_ctr
;
186 ts
->srr0
= (unsigned int)sv
->save_srr0
;
187 ts
->srr1
= (unsigned int)sv
->save_srr1
;
188 ts
->mq
= 0; /* MQ register (601 only) */
189 ts
->vrsave
= (unsigned int)sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
191 else { /* No user state yet. Save seemingly random values. */
193 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
194 ((unsigned int *)&ts
->r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
195 ((unsigned int *)&ts
->r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
199 ts
->lr
= ((unsigned int *)&FloatInit
)[0];
200 ts
->ctr
= ((unsigned int *)&FloatInit
)[1];
201 ts
->srr0
= ((unsigned int *)&FloatInit
)[0];
202 ts
->srr1
= MSR_EXPORT_MASK_SET
;
204 ts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
207 *count
= PPC_THREAD_STATE_COUNT
; /* Pass back the amount we actually copied */
211 case PPC_THREAD_STATE64
:
213 if (*count
< PPC_THREAD_STATE64_COUNT
) { /* Is the count ok? */
214 return KERN_INVALID_ARGUMENT
;
217 xts
= (struct ppc_thread_state64
*) tstate
;
219 sv
= genuser
; /* Copy this over */
221 if(sv
) { /* Is there a save area yet? */
222 xts
->r0
= sv
->save_r0
;
223 xts
->r1
= sv
->save_r1
;
224 xts
->r2
= sv
->save_r2
;
225 xts
->r3
= sv
->save_r3
;
226 xts
->r4
= sv
->save_r4
;
227 xts
->r5
= sv
->save_r5
;
228 xts
->r6
= sv
->save_r6
;
229 xts
->r7
= sv
->save_r7
;
230 xts
->r8
= sv
->save_r8
;
231 xts
->r9
= sv
->save_r9
;
232 xts
->r10
= sv
->save_r10
;
233 xts
->r11
= sv
->save_r11
;
234 xts
->r12
= sv
->save_r12
;
235 xts
->r13
= sv
->save_r13
;
236 xts
->r14
= sv
->save_r14
;
237 xts
->r15
= sv
->save_r15
;
238 xts
->r16
= sv
->save_r16
;
239 xts
->r17
= sv
->save_r17
;
240 xts
->r18
= sv
->save_r18
;
241 xts
->r19
= sv
->save_r19
;
242 xts
->r20
= sv
->save_r20
;
243 xts
->r21
= sv
->save_r21
;
244 xts
->r22
= sv
->save_r22
;
245 xts
->r23
= sv
->save_r23
;
246 xts
->r24
= sv
->save_r24
;
247 xts
->r25
= sv
->save_r25
;
248 xts
->r26
= sv
->save_r26
;
249 xts
->r27
= sv
->save_r27
;
250 xts
->r28
= sv
->save_r28
;
251 xts
->r29
= sv
->save_r29
;
252 xts
->r30
= sv
->save_r30
;
253 xts
->r31
= sv
->save_r31
;
254 xts
->cr
= sv
->save_cr
;
255 xts
->xer
= sv
->save_xer
;
256 xts
->lr
= sv
->save_lr
;
257 xts
->ctr
= sv
->save_ctr
;
258 xts
->srr0
= sv
->save_srr0
;
259 xts
->srr1
= sv
->save_srr1
;
260 xts
->vrsave
= sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
262 else { /* No user state yet. Save seemingly random values. */
264 for(i
=0; i
< 32; i
++) { /* Fill up with defaults */
265 ((unsigned long long *)&xts
->r0
)[i
] = ((unsigned long long *)&FloatInit
)[0];
269 xts
->lr
= ((unsigned long long *)&FloatInit
)[0];
270 xts
->ctr
= ((unsigned long long *)&FloatInit
)[0];
271 xts
->srr0
= ((unsigned long long *)&FloatInit
)[0];
272 xts
->srr1
= MSR_EXPORT_MASK_SET
;
273 xts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
276 *count
= PPC_THREAD_STATE64_COUNT
; /* Pass back the amount we actually copied */
279 case PPC_EXCEPTION_STATE
:
281 if (*count
< PPC_EXCEPTION_STATE_COUNT
) {
282 return KERN_INVALID_ARGUMENT
;
285 es
= (struct ppc_exception_state
*) tstate
;
286 sv
= genuser
; /* Copy this over */
288 if(sv
) { /* See if valid state yet */
289 es
->dar
= (unsigned int)sv
->save_dar
;
290 es
->dsisr
= sv
->save_dsisr
;
291 es
->exception
= sv
->save_exception
;
293 else { /* Nope, not yet */
296 es
->exception
= ((unsigned int *)&FloatInit
)[0];
299 *count
= PPC_EXCEPTION_STATE_COUNT
;
302 case PPC_EXCEPTION_STATE64
:
304 if (*count
< PPC_EXCEPTION_STATE64_COUNT
) {
305 return KERN_INVALID_ARGUMENT
;
308 xes
= (struct ppc_exception_state64
*) tstate
;
309 sv
= genuser
; /* Copy this over */
311 if(sv
) { /* See if valid state yet */
312 xes
->dar
= sv
->save_dar
;
313 xes
->dsisr
= sv
->save_dsisr
;
314 xes
->exception
= sv
->save_exception
;
316 else { /* Nope, not yet */
319 xes
->exception
= ((unsigned int *)&FloatInit
)[0];
322 *count
= PPC_EXCEPTION_STATE64_COUNT
;
325 case PPC_FLOAT_STATE
:
327 if (*count
< PPC_FLOAT_STATE_COUNT
) {
328 return KERN_INVALID_ARGUMENT
;
331 fpu_save(thr_act
->mact
.curctx
); /* Just in case it's live, save it */
333 fs
= (struct ppc_float_state
*) tstate
; /* Point to destination */
335 fsv
= find_user_fpu(thr_act
); /* Get the user's fpu savearea */
337 if(fsv
) { /* See if we have any */
338 bcopy((char *)&fsv
->save_fp0
, (char *)fs
, 32*8); /* 32 registers */
339 fs
->fpscr_pad
= 0; /* Be clean and tidy */
340 if(genuser
) fs
->fpscr
= genuser
->save_fpscr
; /* Set the fpscr value to general */
341 else fs
->fpscr
= 0; /* If no user, initialize this */
343 else { /* No floating point yet */
345 for(i
=0; i
< 32; i
++) { /* Initialize floating points */
346 fs
->fpregs
[i
] = FloatInit
; /* Initial value */
348 fs
->fpscr_pad
= 0; /* Initial value */
349 fs
->fpscr
= 0; /* Initial value */
352 *count
= PPC_FLOAT_STATE_COUNT
;
356 case PPC_VECTOR_STATE
:
358 if (*count
< PPC_VECTOR_STATE_COUNT
) {
359 return KERN_INVALID_ARGUMENT
;
362 vec_save(thr_act
->mact
.curctx
); /* Just in case it's live, save it */
364 vs
= (struct ppc_vector_state
*) tstate
; /* Point to destination */
366 vsv
= find_user_vec(thr_act
); /* Find the vector savearea */
368 if(vsv
) { /* See if we have any */
370 vrvalidwrk
= vsv
->save_vrvalid
; /* Get the valid flags */
371 vs
->save_vrvalid
= vsv
->save_vrvalid
; /* Set the valid flags */
372 if(genuser
) for(j
=0; j
< 4; j
++) vs
->save_vscr
[j
] = genuser
->save_vscr
[j
]; /* Set value for vscr */
374 vs
->save_vscr
[0] = 0; /* Set an initial value if no general user yet */
375 vs
->save_vscr
[1] = 0;
376 vs
->save_vscr
[2] = 0;
377 vs
->save_vscr
[3] = 0x00010000; /* Always start with Java mode off */
379 for(i
=0; i
< 32; i
++) { /* Copy the saved registers and invalidate the others */
380 for(j
=0; j
< 4; j
++) {
381 if(vrvalidwrk
& 0x80000000) (vs
->save_vr
)[i
][j
] =
382 ((unsigned int *)&(vsv
->save_vr0
))[(i
* 4) + j
]; /* We have this register saved */
383 else vs
->save_vr
[i
][j
] = QNaNbarbarian
[j
]; /* Set invalid value */
385 vrvalidwrk
= vrvalidwrk
<< 1; /* Shift over to the next */
388 else { /* No vector yet */
390 for(i
=0; i
< 32; i
++) { /* Initialize vector registers */
391 for(j
=0; j
< 4; j
++) vs
->save_vr
[i
][j
] = QNaNbarbarian
[j
]; /* Initial value */
394 if(genuser
) for(j
=0; j
< 4; j
++) vs
->save_vscr
[j
] = genuser
->save_vscr
[j
]; /* Set value for vscr */
396 vs
->save_vscr
[0] = 0; /* Set an initial value if no general user yet */
397 vs
->save_vscr
[1] = 0;
398 vs
->save_vscr
[2] = 0;
399 vs
->save_vscr
[3] = 0x00010000; /* Always start with Java mode off */
401 vs
->save_vrvalid
= 0; /* Clear the valid flags */
404 for (i
=0; i
< 4; i
++) vs
->save_pad5
[i
] = 0; /* Clear cruft */
405 for (i
=0; i
< 7; i
++) vs
->save_pad6
[i
] = 0; /* Clear cruft */
407 *count
= PPC_VECTOR_STATE_COUNT
;
411 return KERN_INVALID_ARGUMENT
;
419 * Set the status of the specified thread.
422 act_machine_set_state(
423 thread_act_t thr_act
,
424 thread_flavor_t flavor
,
425 thread_state_t tstate
,
426 mach_msg_type_number_t count
)
429 savearea
*sv
, *genuser
;
430 savearea_fpu
*fsv
, *fsvn
, *fsvo
;
431 savearea_vec
*vsv
, *vsvn
, *vsvo
;
434 register struct ppc_thread_state
*ts
;
435 register struct ppc_thread_state64
*xts
;
436 register struct ppc_exception_state
*es
;
437 register struct ppc_exception_state
*xes
;
438 register struct ppc_float_state
*fs
;
439 register struct ppc_vector_state
*vs
;
441 int kernel_act
= thr_act
->kernel_loading
|| thr_act
->kernel_loaded
;
443 // dbgTrace((unsigned int)thr_act, (unsigned int)sv, flavor); /* (TEST/DEBUG) */
445 clgn
= count
; /* Get the count */
447 switch (flavor
) { /* Validate the count before we do anything else */
448 case PPC_THREAD_STATE
:
450 if (clgn
< PPC_THREAD_STATE_COUNT
) { /* Is it too short? */
451 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
455 case PPC_THREAD_STATE64
:
457 if (clgn
< PPC_THREAD_STATE64_COUNT
) { /* Is it too short? */
458 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
462 case PPC_EXCEPTION_STATE
:
464 if (clgn
< PPC_EXCEPTION_STATE_COUNT
) { /* Is it too short? */
465 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
468 case PPC_EXCEPTION_STATE64
:
470 if (clgn
< PPC_EXCEPTION_STATE64_COUNT
) { /* Is it too short? */
471 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
476 case PPC_FLOAT_STATE
:
478 if (clgn
< PPC_FLOAT_STATE_COUNT
) { /* Is it too short? */
479 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
485 case PPC_VECTOR_STATE
:
487 if (clgn
< PPC_VECTOR_STATE_COUNT
) { /* Is it too short? */
488 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
494 return KERN_INVALID_ARGUMENT
;
497 genuser
= get_user_regs(thr_act
); /* Find or allocate and initialize one */
501 case PPC_THREAD_STATE
:
503 ts
= (struct ppc_thread_state
*)tstate
;
505 genuser
->save_r0
= (uint64_t)ts
->r0
;
506 genuser
->save_r1
= (uint64_t)ts
->r1
;
507 genuser
->save_r2
= (uint64_t)ts
->r2
;
508 genuser
->save_r3
= (uint64_t)ts
->r3
;
509 genuser
->save_r4
= (uint64_t)ts
->r4
;
510 genuser
->save_r5
= (uint64_t)ts
->r5
;
511 genuser
->save_r6
= (uint64_t)ts
->r6
;
512 genuser
->save_r7
= (uint64_t)ts
->r7
;
513 genuser
->save_r8
= (uint64_t)ts
->r8
;
514 genuser
->save_r9
= (uint64_t)ts
->r9
;
515 genuser
->save_r10
= (uint64_t)ts
->r10
;
516 genuser
->save_r11
= (uint64_t)ts
->r11
;
517 genuser
->save_r12
= (uint64_t)ts
->r12
;
518 genuser
->save_r13
= (uint64_t)ts
->r13
;
519 genuser
->save_r14
= (uint64_t)ts
->r14
;
520 genuser
->save_r15
= (uint64_t)ts
->r15
;
521 genuser
->save_r16
= (uint64_t)ts
->r16
;
522 genuser
->save_r17
= (uint64_t)ts
->r17
;
523 genuser
->save_r18
= (uint64_t)ts
->r18
;
524 genuser
->save_r19
= (uint64_t)ts
->r19
;
525 genuser
->save_r20
= (uint64_t)ts
->r20
;
526 genuser
->save_r21
= (uint64_t)ts
->r21
;
527 genuser
->save_r22
= (uint64_t)ts
->r22
;
528 genuser
->save_r23
= (uint64_t)ts
->r23
;
529 genuser
->save_r24
= (uint64_t)ts
->r24
;
530 genuser
->save_r25
= (uint64_t)ts
->r25
;
531 genuser
->save_r26
= (uint64_t)ts
->r26
;
532 genuser
->save_r27
= (uint64_t)ts
->r27
;
533 genuser
->save_r28
= (uint64_t)ts
->r28
;
534 genuser
->save_r29
= (uint64_t)ts
->r29
;
535 genuser
->save_r30
= (uint64_t)ts
->r30
;
536 genuser
->save_r31
= (uint64_t)ts
->r31
;
538 genuser
->save_cr
= ts
->cr
;
539 genuser
->save_xer
= (uint64_t)ts
->xer
;
540 genuser
->save_lr
= (uint64_t)ts
->lr
;
541 genuser
->save_ctr
= (uint64_t)ts
->ctr
;
542 genuser
->save_srr0
= (uint64_t)ts
->srr0
;
543 genuser
->save_vrsave
= ts
->vrsave
; /* VRSAVE register (Altivec only) */
545 genuser
->save_srr1
= MSR_PREPARE_FOR_IMPORT(genuser
->save_srr1
, ts
->srr1
); /* Set the bits we can change */
547 if(!kernel_act
) genuser
->save_srr1
|= MSR_EXPORT_MASK_SET
; /* If not a kernel guy, force the magic bits on */
549 genuser
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make sure we don't enable the floating point unit */
554 case PPC_THREAD_STATE64
:
556 xts
= (struct ppc_thread_state64
*)tstate
;
558 genuser
->save_r0
= xts
->r0
;
559 genuser
->save_r1
= xts
->r1
;
560 genuser
->save_r2
= xts
->r2
;
561 genuser
->save_r3
= xts
->r3
;
562 genuser
->save_r4
= xts
->r4
;
563 genuser
->save_r5
= xts
->r5
;
564 genuser
->save_r6
= xts
->r6
;
565 genuser
->save_r7
= xts
->r7
;
566 genuser
->save_r8
= xts
->r8
;
567 genuser
->save_r9
= xts
->r9
;
568 genuser
->save_r10
= xts
->r10
;
569 genuser
->save_r11
= xts
->r11
;
570 genuser
->save_r12
= xts
->r12
;
571 genuser
->save_r13
= xts
->r13
;
572 genuser
->save_r14
= xts
->r14
;
573 genuser
->save_r15
= xts
->r15
;
574 genuser
->save_r16
= xts
->r16
;
575 genuser
->save_r17
= xts
->r17
;
576 genuser
->save_r18
= xts
->r18
;
577 genuser
->save_r19
= xts
->r19
;
578 genuser
->save_r20
= xts
->r20
;
579 genuser
->save_r21
= xts
->r21
;
580 genuser
->save_r22
= xts
->r22
;
581 genuser
->save_r23
= xts
->r23
;
582 genuser
->save_r24
= xts
->r24
;
583 genuser
->save_r25
= xts
->r25
;
584 genuser
->save_r26
= xts
->r26
;
585 genuser
->save_r27
= xts
->r27
;
586 genuser
->save_r28
= xts
->r28
;
587 genuser
->save_r29
= xts
->r29
;
588 genuser
->save_r30
= xts
->r30
;
589 genuser
->save_r31
= xts
->r31
;
591 genuser
->save_cr
= xts
->cr
;
592 genuser
->save_xer
= xts
->xer
;
593 genuser
->save_lr
= xts
->lr
;
594 genuser
->save_ctr
= xts
->ctr
;
595 genuser
->save_srr0
= xts
->srr0
;
596 genuser
->save_vrsave
= xts
->vrsave
; /* VRSAVE register (Altivec only) */
598 genuser
->save_srr1
= MSR_PREPARE_FOR_IMPORT(genuser
->save_srr1
, xts
->srr1
); /* Set the bits we can change */
600 if(!kernel_act
) genuser
->save_srr1
|= MSR_EXPORT_MASK_SET
; /* If not a kernel guy, force the magic bits on */
602 genuser
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make sure we don't enable the floating point unit */
607 case PPC_EXCEPTION_STATE
:
609 es
= (struct ppc_exception_state
*) tstate
;
611 genuser
->save_dar
= (uint64_t)es
->dar
;
612 genuser
->save_dsisr
= es
->dsisr
;
613 genuser
->save_exception
= es
->exception
;
618 * It's pretty worthless to try to change this stuff, but we'll do it anyway.
621 case PPC_EXCEPTION_STATE64
:
623 xes
= (struct ppc_exception_state
*) tstate
;
625 genuser
->save_dar
= xes
->dar
;
626 genuser
->save_dsisr
= xes
->dsisr
;
627 genuser
->save_exception
= xes
->exception
;
631 case PPC_FLOAT_STATE
:
633 toss_live_fpu(thr_act
->mact
.curctx
); /* Toss my floating point if live anywhere */
635 fsv
= find_user_fpu(thr_act
); /* Get the user's floating point context */
637 if(!fsv
) { /* Do we have one yet? */
638 fsv
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
639 fsv
->save_hdr
.save_flags
= (fsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
640 fsv
->save_hdr
.save_act
= thr_act
; /* Point to the activation */
641 fsv
->save_hdr
.save_prev
= 0; /* Mark no more */
642 fsv
->save_hdr
.save_level
= 0; /* Mark user state */
644 if(!thr_act
->mact
.curctx
->FPUsave
) thr_act
->mact
.curctx
->FPUsave
= fsv
; /* If no floating point, chain us first */
647 fsvn
= fsvo
= thr_act
->mact
.curctx
->FPUsave
; /* Remember first one */
649 while (fsvn
) { /* Go until we hit the end */
650 fsvo
= fsvn
; /* Remember the previous one */
651 fsvn
= (savearea_fpu
*)fsvo
->save_hdr
.save_prev
; /* Skip on to the next */
654 fsvo
->save_hdr
.save_prev
= (addr64_t
)fsv
; /* Queue us on in */
659 fs
= (struct ppc_float_state
*) tstate
; /* Point to source */
662 bcopy((char *)fs
, (char *)&fsv
->save_fp0
, 32*8); /* Move in the 32 registers */
664 genuser
->save_fpscr
= fs
->fpscr
; /* Copy the fpscr value to normal */
669 case PPC_VECTOR_STATE
:
671 toss_live_vec(thr_act
->mact
.curctx
); /* Toss my vector if live anywhere */
673 vsv
= find_user_vec(thr_act
); /* Get the user's vector context */
675 if(!vsv
) { /* Do we have one yet? */
676 vsv
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
677 vsv
->save_hdr
.save_flags
= (vsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as vector */
678 vsv
->save_hdr
.save_act
= thr_act
; /* Point to the activation */
679 vsv
->save_hdr
.save_prev
= 0; /* Mark no more */
680 vsv
->save_hdr
.save_level
= 0; /* Mark user state */
682 if(!thr_act
->mact
.curctx
->VMXsave
) thr_act
->mact
.curctx
->VMXsave
= vsv
; /* If no vector, chain us first */
685 vsvn
= vsvo
= thr_act
->mact
.curctx
->VMXsave
; /* Remember first one */
687 while (vsvn
) { /* Go until we hit the end */
688 vsvo
= vsvn
; /* Remember the previous one */
689 vsvn
= (savearea_vec
*)vsvo
->save_hdr
.save_prev
; /* Skip on to the next */
692 vsvo
->save_hdr
.save_prev
= (addr64_t
)vsv
; /* Queue us on in */
697 vs
= (struct ppc_vector_state
*) tstate
; /* Point to source */
699 bcopy((char *)vs
, (char *)&vsv
->save_vr0
, 32*16); /* 32 registers plus status and validity and pad */
700 vsv
->save_vrvalid
= vs
->save_vrvalid
; /* Set validity bits */
703 for(i
= 0; i
< 4; i
++) genuser
->save_vscr
[i
] = vs
->save_vscr
[i
]; /* Set value for vscr */
709 return KERN_INVALID_ARGUMENT
;
714 * Duplicates the context of one thread into a new one.
715 * The new thread is assumed to be new and have no user state contexts except maybe a general one.
716 * We also assume that the old thread can't be running anywhere.
718 * We're only going to be duplicating user context here. That means that we will have to
719 * eliminate any floating point or vector kernel contexts and carry across the user state ones.
722 void act_thread_dup(thread_act_t old
, thread_act_t
new) {
725 savearea_fpu
*fsv
, *fsvn
;
726 savearea_vec
*vsv
, *vsvn
;
727 unsigned int spc
, i
, *srs
;
729 fpu_save(old
->mact
.curctx
); /* Make certain floating point state is all saved */
730 vec_save(old
->mact
.curctx
); /* Make certain the vector state is all saved */
732 sv
= get_user_regs(new); /* Allocate and initialze context in the new activation */
734 osv
= find_user_regs(old
); /* Find the original context */
736 panic("act_thread_dup: old activation (%08X) has no general user context\n", old
);
739 bcopy((char *)((unsigned int)osv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
740 (char *)((unsigned int)sv
+ sizeof(savearea_comm
)),
741 sizeof(struct savearea
) - sizeof(savearea_comm
));
743 sv
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make certain that floating point and vector are turned off */
745 fsv
= find_user_fpu(old
); /* Get any user floating point */
747 new->mact
.curctx
->FPUsave
= 0; /* Assume no floating point */
749 if(fsv
) { /* Did we find one? */
750 fsvn
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
751 fsvn
->save_hdr
.save_flags
= (fsvn
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
752 fsvn
->save_hdr
.save_act
= new; /* Point to the activation */
753 fsvn
->save_hdr
.save_prev
= 0; /* Mark no more */
754 fsvn
->save_hdr
.save_level
= 0; /* Mark user state */
756 new->mact
.curctx
->FPUsave
= fsvn
; /* Chain in the floating point */
758 bcopy((char *)((unsigned int)fsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
759 (char *)((unsigned int)fsvn
+ sizeof(savearea_comm
)),
760 sizeof(struct savearea
) - sizeof(savearea_comm
));
763 vsv
= find_user_vec(old
); /* Get any user vector */
765 new->mact
.curctx
->VMXsave
= 0; /* Assume no vector */
767 if(vsv
) { /* Did we find one? */
768 vsvn
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
769 vsvn
->save_hdr
.save_flags
= (vsvn
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as float */
770 vsvn
->save_hdr
.save_act
= new; /* Point to the activation */
771 vsvn
->save_hdr
.save_prev
= 0; /* Mark no more */
772 vsvn
->save_hdr
.save_level
= 0; /* Mark user state */
774 new->mact
.curctx
->VMXsave
= vsvn
; /* Chain in the floating point */
776 bcopy((char *)((unsigned int)vsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
777 (char *)((unsigned int)vsvn
+ sizeof(savearea_comm
)),
778 sizeof(struct savearea
) - sizeof(savearea_comm
));
781 return; /* Bye bye... */
785 * Initializes a fresh set of user state values. If there is no user state context,
786 * one is created. Floats and VMX are not created.
788 * We only set initial values if there was no context found.
791 savearea
*get_user_regs(thread_act_t act
) {
794 unsigned int spc
, i
, *srs
;
796 sv
= act
->mact
.pcb
; /* Get the top savearea on the stack */
797 osv
= 0; /* Set no user savearea yet */
799 while(sv
) { /* Find the user context */
800 if(sv
->save_srr1
& MASK(MSR_PR
)) return sv
; /* We found a user state context... */
802 osv
= sv
; /* Save the last one */
803 sv
= (savearea
*)sv
->save_hdr
.save_prev
; /* Get the previous context */
806 sv
= save_alloc(); /* Get one */
807 sv
->save_hdr
.save_flags
= (sv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVgeneral
<< SAVtypeshft
); /* Mark as in use as general */
808 sv
->save_hdr
.save_act
= act
; /* Point to the activation */
809 sv
->save_hdr
.save_prev
= 0; /* Mark no more */
810 sv
->save_hdr
.save_level
= 0; /* Mark user state */
812 if(osv
) { /* Did we already have one? */
813 osv
->save_hdr
.save_prev
= (addr64_t
)sv
; /* Chain us on the end */
815 else { /* We are the first */
816 act
->mact
.pcb
= sv
; /* Put it there */
819 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
820 ((unsigned int *)&sv
->save_r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
821 ((unsigned int *)&sv
->save_r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
825 sv
->save_lr
= (uint64_t)FloatInit
;
826 sv
->save_ctr
= (uint64_t)FloatInit
;
827 sv
->save_srr0
= (uint64_t)FloatInit
;
828 sv
->save_srr1
= (uint64_t)MSR_EXPORT_MASK_SET
;
830 sv
->save_fpscr
= 0; /* Clear all floating point exceptions */
832 sv
->save_vrsave
= 0; /* Set the vector save state */
833 sv
->save_vscr
[0] = 0x00000000;
834 sv
->save_vscr
[1] = 0x00000000;
835 sv
->save_vscr
[2] = 0x00000000;
836 sv
->save_vscr
[3] = 0x00010000; /* Disable java mode and clear saturated */
838 return sv
; /* Bye bye... */
842 * Find the user state context. If there is no user state context,
843 * we just return a 0.
846 savearea
*find_user_regs(thread_act_t act
) {
850 sv
= act
->mact
.pcb
; /* Get the top savearea on the stack */
852 while(sv
) { /* Find the user context */
853 if(sv
->save_srr1
& MASK(MSR_PR
)) { /* Are we looking at the user context? */
854 break; /* Outta here */
856 sv
= (savearea
*)sv
->save_hdr
.save_prev
; /* Get the previous context */
859 return sv
; /* Bye bye... */
863 * Find the user state floating point context. If there is no user state context,
864 * we just return a 0.
867 savearea_fpu
*find_user_fpu(thread_act_t act
) {
871 fsv
= act
->mact
.curctx
->FPUsave
; /* Get the start of the floating point chain */
873 while(fsv
) { /* Look until the end or we find it */
874 if(!(fsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
875 fsv
= (savearea_fpu
*)fsv
->save_hdr
.save_prev
; /* Try the previous one */
878 return fsv
; /* Bye bye... */
882 * Find the user state vector context. If there is no user state context,
883 * we just return a 0.
886 savearea_vec
*find_user_vec(thread_act_t act
) {
890 vsv
= act
->mact
.curctx
->VMXsave
; /* Get the start of the vector chain */
892 while(vsv
) { /* Look until the end or we find it */
893 if(!(vsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
894 vsv
= (savearea_vec
*)vsv
->save_hdr
.save_prev
; /* Try the previous one */
897 return vsv
; /* Bye bye... */
903 * Return the user stack pointer from the machine
904 * dependent thread state info.
910 thread_state_t tstate
,
912 vm_offset_t
*user_stack
,
916 struct ppc_thread_state
*state
;
921 if (*user_stack
== 0)
922 *user_stack
= USRSTACK
;
927 case PPC_THREAD_STATE
:
928 if (count
< PPC_THREAD_STATE_COUNT
)
929 return (KERN_INVALID_ARGUMENT
);
931 state
= (struct ppc_thread_state
*) tstate
;
934 * If a valid user stack is specified, use it.
936 *user_stack
= state
->r1
? state
->r1
: USRSTACK
;
938 if (customstack
&& state
->r1
)
943 return (KERN_INVALID_ARGUMENT
);
946 return (KERN_SUCCESS
);
951 * thread_setuserstack:
953 * Sets the user stack pointer into the machine
954 * dependent thread state info.
956 void thread_setuserstack(struct thread_activation
*act
, unsigned int user_stack
)
960 sv
= get_user_regs(act
); /* Get the user state registers */
962 sv
->save_r1
= (uint64_t)user_stack
;
968 * thread_adjuserstack:
970 * Returns the adjusted user stack pointer from the machine
971 * dependent thread state info.
973 unsigned int thread_adjuserstack(struct thread_activation
*act
, int adjust
)
977 sv
= get_user_regs(act
); /* Get the user state registers */
979 sv
->save_r1
+= adjust
; /* Adjust the stack */
981 return (unsigned int)sv
->save_r1
; /* Return the adjusted stack */
986 * thread_setentrypoint:
988 * Sets the user PC into the machine
989 * dependent thread state info.
992 void thread_setentrypoint(struct thread_activation
*act
, unsigned int entry
)
996 sv
= get_user_regs(act
); /* Get the user state registers */
998 sv
->save_srr0
= (uint64_t)entry
;
1007 thread_state_t tstate
,
1009 vm_offset_t
*entry_point
1012 struct ppc_thread_state
*state
;
1017 if (*entry_point
== 0)
1018 *entry_point
= VM_MIN_ADDRESS
;
1022 case PPC_THREAD_STATE
:
1023 if (count
< PPC_THREAD_STATE_COUNT
)
1024 return (KERN_INVALID_ARGUMENT
);
1026 state
= (struct ppc_thread_state
*) tstate
;
1029 * If a valid entry point is specified, use it.
1031 *entry_point
= state
->srr0
? state
->srr0
: VM_MIN_ADDRESS
;
1034 return (KERN_INVALID_ARGUMENT
);
1037 return (KERN_SUCCESS
);
1040 unsigned int get_msr_exportmask(void)
1042 return (MSR_EXPORT_MASK_SET
);
1045 unsigned int get_msr_nbits(void)
1047 return (MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1049 unsigned int get_msr_rbits(void)
1051 return (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1054 void ppc_checkthreadstate(void * tsptr
, int flavor
)
1056 if (flavor
== PPC_THREAD_STATE64
) {
1057 struct ppc_thread_state64
*ts64
=(struct ppc_thread_state64
*)tsptr
;
1059 /* Make sure naughty bits are off and necessary bits are on */
1060 ts64
->srr1
&= ~(MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1061 ts64
->srr1
|= (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1063 struct ppc_thread_state
*ts
=(struct ppc_thread_state
*)tsptr
;
1065 /* Make sure naughty bits are off and necessary bits are on */
1066 ts
->srr1
&= ~(MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1067 ts
->srr1
|= (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1072 void thread_set_child(thread_act_t child
, int pid
)
1074 struct savearea
*child_state
;
1076 child_state
= get_user_regs(child
);
1078 child_state
->save_r3
= (uint_t
)pid
;
1079 child_state
->save_r4
= 1ULL;
1081 void thread_set_parent(thread_act_t parent
, int pid
)
1083 struct savearea
*parent_state
;
1085 parent_state
= get_user_regs(parent
);
1087 parent_state
->save_r3
= (uint64_t)pid
;
1088 parent_state
->save_r4
= 0;
1092 * Saves the complete context (general, floating point, and vector) of the current activation.
1093 * We will collect everything into an opaque block of 1 to 3 saveareas and pass back a
1096 * The savearea is made to look like it belongs to the source activation. This needs to
1097 * be adjusted when these contexts are attached to a new activation.
1101 void *act_thread_csave(void) {
1104 savearea_fpu
*fsv
, *ofsv
;
1105 savearea_vec
*vsv
, *ovsv
;
1106 unsigned int spc
, i
, *srs
;
1110 act
= current_act(); /* Find ourselves */
1112 fpu_save(act
->mact
.curctx
); /* Make certain floating point state is all saved */
1113 vec_save(act
->mact
.curctx
); /* Make certain the vector state is all saved */
1115 osv
= find_user_regs(act
); /* Get our savearea */
1118 panic("act_thread_csave: attempting to preserve the context of an activation with none (%08X)\n", act
);
1121 sv
= save_alloc(); /* Get a fresh save area to save into */
1122 sv
->save_hdr
.save_flags
= (sv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVgeneral
<< SAVtypeshft
); /* Mark as in use as general */
1123 sv
->save_hdr
.save_act
= act
; /* Point to the activation */
1124 sv
->save_hdr
.save_prev
= 0; /* Mark no more */
1125 sv
->save_hdr
.save_level
= 0; /* Mark user state */
1128 bcopy((char *)((unsigned int)osv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1129 (char *)((unsigned int)sv
+ sizeof(savearea_comm
)),
1130 sizeof(struct savearea
) - sizeof(savearea_comm
));
1132 sv
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make certain that floating point and vector are turned off */
1134 sv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1135 sv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1138 ofsv
= find_user_fpu(act
); /* Get any user floating point */
1140 sv
->save_hdr
.save_misc0
= 0; /* Assume no floating point */
1142 if(ofsv
) { /* Did we find one? */
1143 fsv
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
1144 fsv
->save_hdr
.save_flags
= (fsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
1145 fsv
->save_hdr
.save_act
= act
; /* Point to the activation */
1146 fsv
->save_hdr
.save_prev
= 0; /* Mark no more */
1147 fsv
->save_hdr
.save_level
= 0; /* Mark user state */
1148 fsv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1149 fsv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1151 sv
->save_hdr
.save_misc0
= (uint64_t)fsv
; /* Remember this one */
1153 bcopy((char *)((unsigned int)ofsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1154 (char *)((unsigned int)fsv
+ sizeof(savearea_comm
)),
1155 sizeof(struct savearea
) - sizeof(savearea_comm
));
1158 ovsv
= find_user_vec(act
); /* Get any user vector */
1160 sv
->save_hdr
.save_misc1
= 0; /* Assume no vector */
1162 if(ovsv
) { /* Did we find one? */
1163 vsv
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
1164 vsv
->save_hdr
.save_flags
= (vsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as float */
1165 vsv
->save_hdr
.save_act
= act
; /* Point to the activation */
1166 vsv
->save_hdr
.save_prev
= 0; /* Mark no more */
1167 vsv
->save_hdr
.save_level
= 0; /* Mark user state */
1168 vsv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1169 vsv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1171 sv
->save_hdr
.save_misc1
= (uint64_t)vsv
; /* Chain in the floating point */
1173 bcopy((char *)((unsigned int)ovsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1174 (char *)((unsigned int)vsv
+ sizeof(savearea_comm
)),
1175 sizeof(struct savearea
) - sizeof(savearea_comm
));
1178 return (void *)sv
; /* Bye bye... */
1184 * Attaches saved user state context to an activation. We will replace any
1185 * user state context with what is passed in. The saved context consists of a
1186 * savearea that was setup by
1187 * We will collect everything into one savearea and pass that back.
1189 * The savearea is made to look like it belongs to the source activation. This needs to
1190 * be adjusted when these contexts are attached to a new activation.
1194 void act_thread_catt(void *ctx
) {
1196 savearea
*sv
, *osv
, *psv
;
1197 savearea_fpu
*fsv
, *ofsv
, *pfsv
;
1198 savearea_vec
*vsv
, *ovsv
, *pvsv
;
1199 unsigned int spc
, i
, *srs
;
1202 sv
= (savearea
*)ctx
; /* Make this easier for C */
1204 fsv
= (savearea_fpu
*)sv
->save_hdr
.save_misc0
; /* Get a possible floating point savearea */
1205 vsv
= (savearea_vec
*)sv
->save_hdr
.save_misc1
; /* Get a possible vector savearea */
1207 if((sv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (sv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1208 panic("act_thread_catt: attempt to attach invalid general context savearea - %08X\n", sv
); /* Die */
1211 if(fsv
&& ((fsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (fsv
->save_hdr
.save_misc3
!= 0xE5DA11A5))) { /* See if valid savearea */
1212 panic("act_thread_catt: attempt to attach invalid float context savearea - %08X\n", fsv
); /* Die */
1215 if(vsv
&& ((vsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (vsv
->save_hdr
.save_misc3
!= 0xE5DA11A5))) { /* See if valid savearea */
1216 panic("act_thread_catt: attempt to attach invalid vector context savearea - %08X\n", vsv
); /* Die */
1219 act
= current_act(); /* Find ourselves */
1221 toss_live_fpu(act
->mact
.curctx
); /* Toss my floating point if live anywhere */
1222 toss_live_vec(act
->mact
.curctx
); /* Toss my vector if live anywhere */
1224 sv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1225 sv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1226 sv
->save_hdr
.save_act
= act
; /* Set us as owner */
1228 spc
= (unsigned int)act
->map
->pmap
->space
; /* Get the space we're in */
1230 osv
= act
->mact
.pcb
; /* Get the top general savearea */
1232 while(osv
) { /* Any saved state? */
1233 if(osv
->save_srr1
& MASK(MSR_PR
)) break; /* Leave if this is user state */
1234 psv
= osv
; /* Save previous savearea address */
1235 osv
= (savearea
*)osv
->save_hdr
.save_prev
; /* Get one underneath our's */
1238 if(osv
) { /* Did we find one? */
1239 if(psv
) psv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1240 else act
->mact
.pcb
= 0; /* to the start if the only one */
1242 save_release(osv
); /* Nope, release it */
1246 if(psv
) psv
->save_hdr
.save_prev
= (addr64_t
)sv
; /* Chain us to the end or */
1247 else act
->mact
.pcb
= (pcb_t
)sv
; /* to the start if the only one */
1249 ovsv
= act
->mact
.curctx
->VMXsave
; /* Get the top vector savearea */
1252 while(ovsv
) { /* Any VMX saved state? */
1253 if(!(ovsv
->save_hdr
.save_level
)) break; /* Leave if this is user state */
1254 pvsv
= ovsv
; /* Save previous savearea address */
1255 ovsv
= (savearea_vec
*)ovsv
->save_hdr
.save_prev
; /* Get one underneath our's */
1258 if(ovsv
) { /* Did we find one? */
1259 if(pvsv
) pvsv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1260 else act
->mact
.curctx
->VMXsave
= 0; /* to the start if the only one */
1262 save_release((savearea
*)ovsv
); /* Nope, release it */
1265 if(vsv
) { /* Are we sticking any vector on this one? */
1266 if(pvsv
) pvsv
->save_hdr
.save_prev
= (addr64_t
)vsv
; /* Yes, chain us to the end or */
1267 else act
->mact
.curctx
->VMXsave
= vsv
; /* to the start if the only one */
1269 vsv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1270 vsv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1271 vsv
->save_hdr
.save_act
= act
; /* Set us as owner */
1274 ofsv
= act
->mact
.curctx
->FPUsave
; /* Get the top float savearea */
1277 while(ofsv
) { /* Any float saved state? */
1278 if(!(ofsv
->save_hdr
.save_level
)) break; /* Leave if this is user state */
1279 pfsv
= ofsv
; /* Save previous savearea address */
1280 ofsv
= (savearea_fpu
*)ofsv
->save_hdr
.save_prev
; /* Get one underneath our's */
1283 if(ofsv
) { /* Did we find one? */
1284 if(pfsv
) pfsv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1285 else act
->mact
.curctx
->FPUsave
= 0; /* to the start if the only one */
1287 save_release((savearea
*)ofsv
); /* Nope, release it */
1290 if(fsv
) { /* Are we sticking any vector on this one? */
1291 if(pfsv
) pfsv
->save_hdr
.save_prev
= (addr64_t
)fsv
; /* Yes, chain us to the end or */
1292 else act
->mact
.curctx
->FPUsave
= fsv
; /* to the start if the only one */
1294 fsv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1295 fsv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1296 fsv
->save_hdr
.save_act
= act
; /* Set us as owner */
1304 * Releases saved context. We need this because the saved context is opague.
1305 * be adjusted when these contexts are attached to a new activation.
1309 void act_thread_cfree(void *ctx
) {
1312 savearea_fpu
*fsv
, *ofsv
;
1313 savearea_vec
*vsv
, *ovsv
, *pvsv
;
1315 sv
= (savearea
*)ctx
; /* Make this easier for C */
1317 fsv
= (savearea_fpu
*)sv
->save_hdr
.save_misc0
; /* Get a possible floating point savearea */
1318 vsv
= (savearea_vec
*)sv
->save_hdr
.save_misc1
; /* Get a possible vector savearea */
1320 if((sv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (sv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1321 panic("act_thread_cfree: attempt to detatch invalid general context savearea - %08X\n", sv
); /* Die */
1324 save_release(sv
); /* Toss the general savearea */
1326 if(fsv
) { /* See if there is any saved floating point */
1327 if((fsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (fsv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1328 panic("act_thread_cfree: attempt to detatch invalid float context savearea - %08X\n", fsv
); /* Die */
1331 save_release((savearea
*)fsv
); /* Toss saved context */
1334 if(vsv
) { /* See if there is any saved floating point */
1335 if((vsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (vsv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1336 panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %08X\n", vsv
); /* Die */
1339 save_release((savearea
*)vsv
); /* Toss saved context */
1346 * thread_enable_fpe:
1348 * enables or disables floating point exceptions for the thread.
1351 int thread_enable_fpe(thread_act_t act
, int onoff
)
1354 unsigned int oldmsr
;
1356 sv
= find_user_regs(act
); /* Find the user registers */
1357 if(!sv
) sv
= get_user_regs(act
); /* Didn't find any, allocate and initialize o
1360 oldmsr
= sv
->save_srr1
; /* Get the old msr */
1362 if(onoff
) sv
->save_srr1
= oldmsr
| MASK(MSR_FE0
) | MASK(MSR_FE1
); /* Flip on precise FP exceptions */
1363 else sv
->save_srr1
= oldmsr
& ~(MASK(MSR_FE0
) | MASK(MSR_FE1
)); /* Flip on precise FP exceptions */
1365 return ((oldmsr
& (MASK(MSR_FE0
) | MASK(MSR_FE1
))) != 0); /* Return if it was enabled or not */