2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
27 #include <kern/thread.h>
28 #include <kern/thread_act.h>
29 #include <kern/misc_protos.h>
30 #include <mach/ppc/thread_status.h>
31 #include <ppc/proc_reg.h>
32 #include <ppc/exception.h>
33 #include <ppc/misc_protos.h>
34 #include <ppc/savearea.h>
35 #include <ppc/thread_act.h>
36 #include <ppc/Firmware.h>
38 #include <vm/vm_map.h>
40 extern unsigned int killprint
;
41 extern double FloatInit
;
42 extern unsigned long QNaNbarbarian
[4];
43 extern void thread_bootstrap_return(void);
44 extern struct Saveanchor saveanchor
;
45 extern int real_ncpus
; /* Number of actual CPUs */
47 #define USRSTACK 0xc0000000
68 unsigned int get_msr_exportmask(void);
69 unsigned int get_msr_nbits(void);
70 unsigned int get_msr_rbits(void);
71 void ppc_checkthreadstate(void *, int);
72 void thread_set_child(thread_act_t child
, int pid
);
73 void thread_set_parent(thread_act_t parent
, int pid
);
76 * Maps state flavor to number of words in the state:
78 unsigned int state_count
[] = {
80 PPC_THREAD_STATE_COUNT
,
81 PPC_FLOAT_STATE_COUNT
,
82 PPC_EXCEPTION_STATE_COUNT
,
83 PPC_VECTOR_STATE_COUNT
,
84 PPC_THREAD_STATE64_COUNT
,
85 PPC_EXCEPTION_STATE64_COUNT
,
91 * Get the status of the specified thread.
95 machine_thread_get_state(
97 thread_flavor_t flavor
,
98 thread_state_t tstate
,
99 mach_msg_type_number_t
*count
)
102 register struct savearea
*sv
; /* Pointer to the context savearea */
103 register savearea_fpu
*fsv
;
104 register savearea_vec
*vsv
;
107 unsigned int vrvalidwrk
;
109 register struct ppc_thread_state
*ts
;
110 register struct ppc_thread_state64
*xts
;
111 register struct ppc_exception_state
*es
;
112 register struct ppc_exception_state64
*xes
;
113 register struct ppc_float_state
*fs
;
114 register struct ppc_vector_state
*vs
;
116 genuser
= find_user_regs(thr_act
); /* Find the current user general context for this activation */
120 case THREAD_STATE_FLAVOR_LIST
:
123 return (KERN_INVALID_ARGUMENT
);
126 tstate
[0] = PPC_THREAD_STATE
;
127 tstate
[1] = PPC_FLOAT_STATE
;
128 tstate
[2] = PPC_EXCEPTION_STATE
;
129 tstate
[3] = PPC_VECTOR_STATE
;
130 tstate
[4] = PPC_THREAD_STATE64
;
131 tstate
[5] = PPC_EXCEPTION_STATE64
;
136 case PPC_THREAD_STATE
:
138 if (*count
< PPC_THREAD_STATE_COUNT
) { /* Is the count ok? */
139 return KERN_INVALID_ARGUMENT
;
142 ts
= (struct ppc_thread_state
*) tstate
;
144 sv
= genuser
; /* Copy this over */
146 if(sv
) { /* Is there a save area yet? */
147 ts
->r0
= (unsigned int)sv
->save_r0
;
148 ts
->r1
= (unsigned int)sv
->save_r1
;
149 ts
->r2
= (unsigned int)sv
->save_r2
;
150 ts
->r3
= (unsigned int)sv
->save_r3
;
151 ts
->r4
= (unsigned int)sv
->save_r4
;
152 ts
->r5
= (unsigned int)sv
->save_r5
;
153 ts
->r6
= (unsigned int)sv
->save_r6
;
154 ts
->r7
= (unsigned int)sv
->save_r7
;
155 ts
->r8
= (unsigned int)sv
->save_r8
;
156 ts
->r9
= (unsigned int)sv
->save_r9
;
157 ts
->r10
= (unsigned int)sv
->save_r10
;
158 ts
->r11
= (unsigned int)sv
->save_r11
;
159 ts
->r12
= (unsigned int)sv
->save_r12
;
160 ts
->r13
= (unsigned int)sv
->save_r13
;
161 ts
->r14
= (unsigned int)sv
->save_r14
;
162 ts
->r15
= (unsigned int)sv
->save_r15
;
163 ts
->r16
= (unsigned int)sv
->save_r16
;
164 ts
->r17
= (unsigned int)sv
->save_r17
;
165 ts
->r18
= (unsigned int)sv
->save_r18
;
166 ts
->r19
= (unsigned int)sv
->save_r19
;
167 ts
->r20
= (unsigned int)sv
->save_r20
;
168 ts
->r21
= (unsigned int)sv
->save_r21
;
169 ts
->r22
= (unsigned int)sv
->save_r22
;
170 ts
->r23
= (unsigned int)sv
->save_r23
;
171 ts
->r24
= (unsigned int)sv
->save_r24
;
172 ts
->r25
= (unsigned int)sv
->save_r25
;
173 ts
->r26
= (unsigned int)sv
->save_r26
;
174 ts
->r27
= (unsigned int)sv
->save_r27
;
175 ts
->r28
= (unsigned int)sv
->save_r28
;
176 ts
->r29
= (unsigned int)sv
->save_r29
;
177 ts
->r30
= (unsigned int)sv
->save_r30
;
178 ts
->r31
= (unsigned int)sv
->save_r31
;
179 ts
->cr
= (unsigned int)sv
->save_cr
;
180 ts
->xer
= (unsigned int)sv
->save_xer
;
181 ts
->lr
= (unsigned int)sv
->save_lr
;
182 ts
->ctr
= (unsigned int)sv
->save_ctr
;
183 ts
->srr0
= (unsigned int)sv
->save_srr0
;
184 ts
->srr1
= (unsigned int)sv
->save_srr1
;
185 ts
->mq
= 0; /* MQ register (601 only) */
186 ts
->vrsave
= (unsigned int)sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
188 else { /* No user state yet. Save seemingly random values. */
190 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
191 ((unsigned int *)&ts
->r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
192 ((unsigned int *)&ts
->r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
196 ts
->lr
= ((unsigned int *)&FloatInit
)[0];
197 ts
->ctr
= ((unsigned int *)&FloatInit
)[1];
198 ts
->srr0
= ((unsigned int *)&FloatInit
)[0];
199 ts
->srr1
= MSR_EXPORT_MASK_SET
;
201 ts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
204 *count
= PPC_THREAD_STATE_COUNT
; /* Pass back the amount we actually copied */
208 case PPC_THREAD_STATE64
:
210 if (*count
< PPC_THREAD_STATE64_COUNT
) { /* Is the count ok? */
211 return KERN_INVALID_ARGUMENT
;
214 xts
= (struct ppc_thread_state64
*) tstate
;
216 sv
= genuser
; /* Copy this over */
218 if(sv
) { /* Is there a save area yet? */
219 xts
->r0
= sv
->save_r0
;
220 xts
->r1
= sv
->save_r1
;
221 xts
->r2
= sv
->save_r2
;
222 xts
->r3
= sv
->save_r3
;
223 xts
->r4
= sv
->save_r4
;
224 xts
->r5
= sv
->save_r5
;
225 xts
->r6
= sv
->save_r6
;
226 xts
->r7
= sv
->save_r7
;
227 xts
->r8
= sv
->save_r8
;
228 xts
->r9
= sv
->save_r9
;
229 xts
->r10
= sv
->save_r10
;
230 xts
->r11
= sv
->save_r11
;
231 xts
->r12
= sv
->save_r12
;
232 xts
->r13
= sv
->save_r13
;
233 xts
->r14
= sv
->save_r14
;
234 xts
->r15
= sv
->save_r15
;
235 xts
->r16
= sv
->save_r16
;
236 xts
->r17
= sv
->save_r17
;
237 xts
->r18
= sv
->save_r18
;
238 xts
->r19
= sv
->save_r19
;
239 xts
->r20
= sv
->save_r20
;
240 xts
->r21
= sv
->save_r21
;
241 xts
->r22
= sv
->save_r22
;
242 xts
->r23
= sv
->save_r23
;
243 xts
->r24
= sv
->save_r24
;
244 xts
->r25
= sv
->save_r25
;
245 xts
->r26
= sv
->save_r26
;
246 xts
->r27
= sv
->save_r27
;
247 xts
->r28
= sv
->save_r28
;
248 xts
->r29
= sv
->save_r29
;
249 xts
->r30
= sv
->save_r30
;
250 xts
->r31
= sv
->save_r31
;
251 xts
->cr
= sv
->save_cr
;
252 xts
->xer
= sv
->save_xer
;
253 xts
->lr
= sv
->save_lr
;
254 xts
->ctr
= sv
->save_ctr
;
255 xts
->srr0
= sv
->save_srr0
;
256 xts
->srr1
= sv
->save_srr1
;
257 xts
->vrsave
= sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
259 else { /* No user state yet. Save seemingly random values. */
261 for(i
=0; i
< 32; i
++) { /* Fill up with defaults */
262 ((unsigned long long *)&xts
->r0
)[i
] = ((unsigned long long *)&FloatInit
)[0];
266 xts
->lr
= ((unsigned long long *)&FloatInit
)[0];
267 xts
->ctr
= ((unsigned long long *)&FloatInit
)[0];
268 xts
->srr0
= ((unsigned long long *)&FloatInit
)[0];
269 xts
->srr1
= MSR_EXPORT_MASK_SET
;
270 xts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
273 *count
= PPC_THREAD_STATE64_COUNT
; /* Pass back the amount we actually copied */
276 case PPC_EXCEPTION_STATE
:
278 if (*count
< PPC_EXCEPTION_STATE_COUNT
) {
279 return KERN_INVALID_ARGUMENT
;
282 es
= (struct ppc_exception_state
*) tstate
;
283 sv
= genuser
; /* Copy this over */
285 if(sv
) { /* See if valid state yet */
286 es
->dar
= (unsigned int)sv
->save_dar
;
287 es
->dsisr
= sv
->save_dsisr
;
288 es
->exception
= sv
->save_exception
;
290 else { /* Nope, not yet */
293 es
->exception
= ((unsigned int *)&FloatInit
)[0];
296 *count
= PPC_EXCEPTION_STATE_COUNT
;
299 case PPC_EXCEPTION_STATE64
:
301 if (*count
< PPC_EXCEPTION_STATE64_COUNT
) {
302 return KERN_INVALID_ARGUMENT
;
305 xes
= (struct ppc_exception_state64
*) tstate
;
306 sv
= genuser
; /* Copy this over */
308 if(sv
) { /* See if valid state yet */
309 xes
->dar
= sv
->save_dar
;
310 xes
->dsisr
= sv
->save_dsisr
;
311 xes
->exception
= sv
->save_exception
;
313 else { /* Nope, not yet */
316 xes
->exception
= ((unsigned int *)&FloatInit
)[0];
319 *count
= PPC_EXCEPTION_STATE64_COUNT
;
322 case PPC_FLOAT_STATE
:
324 if (*count
< PPC_FLOAT_STATE_COUNT
) {
325 return KERN_INVALID_ARGUMENT
;
328 fpu_save(thr_act
->mact
.curctx
); /* Just in case it's live, save it */
330 fs
= (struct ppc_float_state
*) tstate
; /* Point to destination */
332 fsv
= find_user_fpu(thr_act
); /* Get the user's fpu savearea */
334 if(fsv
) { /* See if we have any */
335 bcopy((char *)&fsv
->save_fp0
, (char *)fs
, 32*8); /* 32 registers */
336 fs
->fpscr_pad
= 0; /* Be clean and tidy */
337 if(genuser
) fs
->fpscr
= genuser
->save_fpscr
; /* Set the fpscr value to general */
338 else fs
->fpscr
= 0; /* If no user, initialize this */
340 else { /* No floating point yet */
342 for(i
=0; i
< 32; i
++) { /* Initialize floating points */
343 fs
->fpregs
[i
] = FloatInit
; /* Initial value */
345 fs
->fpscr_pad
= 0; /* Initial value */
346 fs
->fpscr
= 0; /* Initial value */
349 *count
= PPC_FLOAT_STATE_COUNT
;
353 case PPC_VECTOR_STATE
:
355 if (*count
< PPC_VECTOR_STATE_COUNT
) {
356 return KERN_INVALID_ARGUMENT
;
359 vec_save(thr_act
->mact
.curctx
); /* Just in case it's live, save it */
361 vs
= (struct ppc_vector_state
*) tstate
; /* Point to destination */
363 vsv
= find_user_vec(thr_act
); /* Find the vector savearea */
365 if(vsv
) { /* See if we have any */
367 vrvalidwrk
= vsv
->save_vrvalid
; /* Get the valid flags */
368 vs
->save_vrvalid
= vsv
->save_vrvalid
; /* Set the valid flags */
369 if(genuser
) for(j
=0; j
< 4; j
++) vs
->save_vscr
[j
] = genuser
->save_vscr
[j
]; /* Set value for vscr */
371 vs
->save_vscr
[0] = 0; /* Set an initial value if no general user yet */
372 vs
->save_vscr
[1] = 0;
373 vs
->save_vscr
[2] = 0;
374 vs
->save_vscr
[3] = 0x00010000; /* Always start with Java mode off */
376 for(i
=0; i
< 32; i
++) { /* Copy the saved registers and invalidate the others */
377 for(j
=0; j
< 4; j
++) {
378 if(vrvalidwrk
& 0x80000000) (vs
->save_vr
)[i
][j
] =
379 ((unsigned int *)&(vsv
->save_vr0
))[(i
* 4) + j
]; /* We have this register saved */
380 else vs
->save_vr
[i
][j
] = QNaNbarbarian
[j
]; /* Set invalid value */
382 vrvalidwrk
= vrvalidwrk
<< 1; /* Shift over to the next */
385 else { /* No vector yet */
387 for(i
=0; i
< 32; i
++) { /* Initialize vector registers */
388 for(j
=0; j
< 4; j
++) vs
->save_vr
[i
][j
] = QNaNbarbarian
[j
]; /* Initial value */
391 if(genuser
) for(j
=0; j
< 4; j
++) vs
->save_vscr
[j
] = genuser
->save_vscr
[j
]; /* Set value for vscr */
393 vs
->save_vscr
[0] = 0; /* Set an initial value if no general user yet */
394 vs
->save_vscr
[1] = 0;
395 vs
->save_vscr
[2] = 0;
396 vs
->save_vscr
[3] = 0x00010000; /* Always start with Java mode off */
398 vs
->save_vrvalid
= 0; /* Clear the valid flags */
401 for (i
=0; i
< 4; i
++) vs
->save_pad5
[i
] = 0; /* Clear cruft */
402 for (i
=0; i
< 7; i
++) vs
->save_pad6
[i
] = 0; /* Clear cruft */
404 *count
= PPC_VECTOR_STATE_COUNT
;
408 return KERN_INVALID_ARGUMENT
;
411 /* Close cousin of machine_thread_get_state().
412 * This function is currently incomplete since we don't really need vector
413 * or FP for the core dump (the save area can be accessed directly if the
414 * user is so inclined). Also the function name is something of a misnomer,
415 * see the comment above find_kern_regs().
419 machine_thread_get_kern_state(
420 thread_act_t thr_act
,
421 thread_flavor_t flavor
,
422 thread_state_t tstate
,
423 mach_msg_type_number_t
*count
)
426 register struct savearea
*sv
; /* Pointer to the context savearea */
429 unsigned int vrvalidwrk
;
431 register struct ppc_thread_state
*ts
;
432 register struct ppc_thread_state64
*xts
;
433 register struct ppc_exception_state
*es
;
434 register struct ppc_exception_state64
*xes
;
436 genkern
= find_kern_regs(thr_act
);
440 case THREAD_STATE_FLAVOR_LIST
:
443 return (KERN_INVALID_ARGUMENT
);
446 tstate
[0] = PPC_THREAD_STATE
;
447 tstate
[1] = PPC_FLOAT_STATE
;
448 tstate
[2] = PPC_EXCEPTION_STATE
;
449 tstate
[3] = PPC_VECTOR_STATE
;
450 tstate
[4] = PPC_THREAD_STATE64
;
451 tstate
[5] = PPC_EXCEPTION_STATE64
;
456 case PPC_THREAD_STATE
:
458 if (*count
< PPC_THREAD_STATE_COUNT
) { /* Is the count ok? */
459 return KERN_INVALID_ARGUMENT
;
462 ts
= (struct ppc_thread_state
*) tstate
;
464 sv
= genkern
; /* Copy this over */
466 if(sv
) { /* Is there a save area yet? */
467 ts
->r0
= (unsigned int)sv
->save_r0
;
468 ts
->r1
= (unsigned int)sv
->save_r1
;
469 ts
->r2
= (unsigned int)sv
->save_r2
;
470 ts
->r3
= (unsigned int)sv
->save_r3
;
471 ts
->r4
= (unsigned int)sv
->save_r4
;
472 ts
->r5
= (unsigned int)sv
->save_r5
;
473 ts
->r6
= (unsigned int)sv
->save_r6
;
474 ts
->r7
= (unsigned int)sv
->save_r7
;
475 ts
->r8
= (unsigned int)sv
->save_r8
;
476 ts
->r9
= (unsigned int)sv
->save_r9
;
477 ts
->r10
= (unsigned int)sv
->save_r10
;
478 ts
->r11
= (unsigned int)sv
->save_r11
;
479 ts
->r12
= (unsigned int)sv
->save_r12
;
480 ts
->r13
= (unsigned int)sv
->save_r13
;
481 ts
->r14
= (unsigned int)sv
->save_r14
;
482 ts
->r15
= (unsigned int)sv
->save_r15
;
483 ts
->r16
= (unsigned int)sv
->save_r16
;
484 ts
->r17
= (unsigned int)sv
->save_r17
;
485 ts
->r18
= (unsigned int)sv
->save_r18
;
486 ts
->r19
= (unsigned int)sv
->save_r19
;
487 ts
->r20
= (unsigned int)sv
->save_r20
;
488 ts
->r21
= (unsigned int)sv
->save_r21
;
489 ts
->r22
= (unsigned int)sv
->save_r22
;
490 ts
->r23
= (unsigned int)sv
->save_r23
;
491 ts
->r24
= (unsigned int)sv
->save_r24
;
492 ts
->r25
= (unsigned int)sv
->save_r25
;
493 ts
->r26
= (unsigned int)sv
->save_r26
;
494 ts
->r27
= (unsigned int)sv
->save_r27
;
495 ts
->r28
= (unsigned int)sv
->save_r28
;
496 ts
->r29
= (unsigned int)sv
->save_r29
;
497 ts
->r30
= (unsigned int)sv
->save_r30
;
498 ts
->r31
= (unsigned int)sv
->save_r31
;
499 ts
->cr
= (unsigned int)sv
->save_cr
;
500 ts
->xer
= (unsigned int)sv
->save_xer
;
501 ts
->lr
= (unsigned int)sv
->save_lr
;
502 ts
->ctr
= (unsigned int)sv
->save_ctr
;
503 ts
->srr0
= (unsigned int)sv
->save_srr0
;
504 ts
->srr1
= (unsigned int)sv
->save_srr1
;
505 ts
->mq
= 0; /* MQ register (601 only) */
506 ts
->vrsave
= (unsigned int)sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
508 else { /* No state yet. Save seemingly random values. */
510 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
511 ((unsigned int *)&ts
->r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
512 ((unsigned int *)&ts
->r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
516 ts
->lr
= ((unsigned int *)&FloatInit
)[0];
517 ts
->ctr
= ((unsigned int *)&FloatInit
)[1];
518 ts
->srr0
= ((unsigned int *)&FloatInit
)[0];
519 ts
->srr1
= MSR_EXPORT_MASK_SET
;
521 ts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
524 *count
= PPC_THREAD_STATE_COUNT
; /* Pass back the amount we actually copied */
528 case PPC_THREAD_STATE64
:
530 if (*count
< PPC_THREAD_STATE64_COUNT
) { /* Is the count ok? */
531 return KERN_INVALID_ARGUMENT
;
534 xts
= (struct ppc_thread_state64
*) tstate
;
536 sv
= genkern
; /* Copy this over */
538 if(sv
) { /* Is there a save area yet? */
539 xts
->r0
= sv
->save_r0
;
540 xts
->r1
= sv
->save_r1
;
541 xts
->r2
= sv
->save_r2
;
542 xts
->r3
= sv
->save_r3
;
543 xts
->r4
= sv
->save_r4
;
544 xts
->r5
= sv
->save_r5
;
545 xts
->r6
= sv
->save_r6
;
546 xts
->r7
= sv
->save_r7
;
547 xts
->r8
= sv
->save_r8
;
548 xts
->r9
= sv
->save_r9
;
549 xts
->r10
= sv
->save_r10
;
550 xts
->r11
= sv
->save_r11
;
551 xts
->r12
= sv
->save_r12
;
552 xts
->r13
= sv
->save_r13
;
553 xts
->r14
= sv
->save_r14
;
554 xts
->r15
= sv
->save_r15
;
555 xts
->r16
= sv
->save_r16
;
556 xts
->r17
= sv
->save_r17
;
557 xts
->r18
= sv
->save_r18
;
558 xts
->r19
= sv
->save_r19
;
559 xts
->r20
= sv
->save_r20
;
560 xts
->r21
= sv
->save_r21
;
561 xts
->r22
= sv
->save_r22
;
562 xts
->r23
= sv
->save_r23
;
563 xts
->r24
= sv
->save_r24
;
564 xts
->r25
= sv
->save_r25
;
565 xts
->r26
= sv
->save_r26
;
566 xts
->r27
= sv
->save_r27
;
567 xts
->r28
= sv
->save_r28
;
568 xts
->r29
= sv
->save_r29
;
569 xts
->r30
= sv
->save_r30
;
570 xts
->r31
= sv
->save_r31
;
571 xts
->cr
= sv
->save_cr
;
572 xts
->xer
= sv
->save_xer
;
573 xts
->lr
= sv
->save_lr
;
574 xts
->ctr
= sv
->save_ctr
;
575 xts
->srr0
= sv
->save_srr0
;
576 xts
->srr1
= sv
->save_srr1
;
577 xts
->vrsave
= sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
579 else { /* No user state yet. Save seemingly random values. */
581 for(i
=0; i
< 32; i
++) { /* Fill up with defaults */
582 ((unsigned long long *)&xts
->r0
)[i
] = ((unsigned long long *)&FloatInit
)[0];
586 xts
->lr
= ((unsigned long long *)&FloatInit
)[0];
587 xts
->ctr
= ((unsigned long long *)&FloatInit
)[0];
588 xts
->srr0
= ((unsigned long long *)&FloatInit
)[0];
589 xts
->srr1
= MSR_EXPORT_MASK_SET
;
590 xts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
593 *count
= PPC_THREAD_STATE64_COUNT
; /* Pass back the amount we actually copied */
596 case PPC_EXCEPTION_STATE
:
598 if (*count
< PPC_EXCEPTION_STATE_COUNT
) {
599 return KERN_INVALID_ARGUMENT
;
602 es
= (struct ppc_exception_state
*) tstate
;
603 sv
= genkern
; /* Copy this over */
605 if(sv
) { /* See if valid state yet */
606 es
->dar
= (unsigned int)sv
->save_dar
;
607 es
->dsisr
= sv
->save_dsisr
;
608 es
->exception
= sv
->save_exception
;
610 else { /* Nope, not yet */
613 es
->exception
= ((unsigned int *)&FloatInit
)[0];
616 *count
= PPC_EXCEPTION_STATE_COUNT
;
619 case PPC_EXCEPTION_STATE64
:
621 if (*count
< PPC_EXCEPTION_STATE64_COUNT
) {
622 return KERN_INVALID_ARGUMENT
;
625 xes
= (struct ppc_exception_state64
*) tstate
;
626 sv
= genkern
; /* Copy this over */
628 if(sv
) { /* See if valid state yet */
629 xes
->dar
= sv
->save_dar
;
630 xes
->dsisr
= sv
->save_dsisr
;
631 xes
->exception
= sv
->save_exception
;
633 else { /* Nope, not yet */
636 xes
->exception
= ((unsigned int *)&FloatInit
)[0];
639 *count
= PPC_EXCEPTION_STATE64_COUNT
;
643 return KERN_INVALID_ARGUMENT
;
651 * Set the status of the specified thread.
654 machine_thread_set_state(
655 thread_act_t thr_act
,
656 thread_flavor_t flavor
,
657 thread_state_t tstate
,
658 mach_msg_type_number_t count
)
661 savearea
*sv
, *genuser
;
662 savearea_fpu
*fsv
, *fsvn
, *fsvo
;
663 savearea_vec
*vsv
, *vsvn
, *vsvo
;
666 register struct ppc_thread_state
*ts
;
667 register struct ppc_thread_state64
*xts
;
668 register struct ppc_exception_state
*es
;
669 register struct ppc_exception_state
*xes
;
670 register struct ppc_float_state
*fs
;
671 register struct ppc_vector_state
*vs
;
673 // dbgTrace((unsigned int)thr_act, (unsigned int)sv, flavor); /* (TEST/DEBUG) */
675 clgn
= count
; /* Get the count */
677 switch (flavor
) { /* Validate the count before we do anything else */
678 case PPC_THREAD_STATE
:
680 if (clgn
< PPC_THREAD_STATE_COUNT
) { /* Is it too short? */
681 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
685 case PPC_THREAD_STATE64
:
687 if (clgn
< PPC_THREAD_STATE64_COUNT
) { /* Is it too short? */
688 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
692 case PPC_EXCEPTION_STATE
:
694 if (clgn
< PPC_EXCEPTION_STATE_COUNT
) { /* Is it too short? */
695 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
698 case PPC_EXCEPTION_STATE64
:
700 if (clgn
< PPC_EXCEPTION_STATE64_COUNT
) { /* Is it too short? */
701 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
706 case PPC_FLOAT_STATE
:
708 if (clgn
< PPC_FLOAT_STATE_COUNT
) { /* Is it too short? */
709 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
715 case PPC_VECTOR_STATE
:
717 if (clgn
< PPC_VECTOR_STATE_COUNT
) { /* Is it too short? */
718 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
724 return KERN_INVALID_ARGUMENT
;
727 genuser
= get_user_regs(thr_act
); /* Find or allocate and initialize one */
731 case PPC_THREAD_STATE
:
733 ts
= (struct ppc_thread_state
*)tstate
;
735 genuser
->save_r0
= (uint64_t)ts
->r0
;
736 genuser
->save_r1
= (uint64_t)ts
->r1
;
737 genuser
->save_r2
= (uint64_t)ts
->r2
;
738 genuser
->save_r3
= (uint64_t)ts
->r3
;
739 genuser
->save_r4
= (uint64_t)ts
->r4
;
740 genuser
->save_r5
= (uint64_t)ts
->r5
;
741 genuser
->save_r6
= (uint64_t)ts
->r6
;
742 genuser
->save_r7
= (uint64_t)ts
->r7
;
743 genuser
->save_r8
= (uint64_t)ts
->r8
;
744 genuser
->save_r9
= (uint64_t)ts
->r9
;
745 genuser
->save_r10
= (uint64_t)ts
->r10
;
746 genuser
->save_r11
= (uint64_t)ts
->r11
;
747 genuser
->save_r12
= (uint64_t)ts
->r12
;
748 genuser
->save_r13
= (uint64_t)ts
->r13
;
749 genuser
->save_r14
= (uint64_t)ts
->r14
;
750 genuser
->save_r15
= (uint64_t)ts
->r15
;
751 genuser
->save_r16
= (uint64_t)ts
->r16
;
752 genuser
->save_r17
= (uint64_t)ts
->r17
;
753 genuser
->save_r18
= (uint64_t)ts
->r18
;
754 genuser
->save_r19
= (uint64_t)ts
->r19
;
755 genuser
->save_r20
= (uint64_t)ts
->r20
;
756 genuser
->save_r21
= (uint64_t)ts
->r21
;
757 genuser
->save_r22
= (uint64_t)ts
->r22
;
758 genuser
->save_r23
= (uint64_t)ts
->r23
;
759 genuser
->save_r24
= (uint64_t)ts
->r24
;
760 genuser
->save_r25
= (uint64_t)ts
->r25
;
761 genuser
->save_r26
= (uint64_t)ts
->r26
;
762 genuser
->save_r27
= (uint64_t)ts
->r27
;
763 genuser
->save_r28
= (uint64_t)ts
->r28
;
764 genuser
->save_r29
= (uint64_t)ts
->r29
;
765 genuser
->save_r30
= (uint64_t)ts
->r30
;
766 genuser
->save_r31
= (uint64_t)ts
->r31
;
768 genuser
->save_cr
= ts
->cr
;
769 genuser
->save_xer
= (uint64_t)ts
->xer
;
770 genuser
->save_lr
= (uint64_t)ts
->lr
;
771 genuser
->save_ctr
= (uint64_t)ts
->ctr
;
772 genuser
->save_srr0
= (uint64_t)ts
->srr0
;
773 genuser
->save_vrsave
= ts
->vrsave
; /* VRSAVE register (Altivec only) */
775 genuser
->save_srr1
= MSR_PREPARE_FOR_IMPORT(genuser
->save_srr1
, ts
->srr1
); /* Set the bits we can change */
777 genuser
->save_srr1
|= MSR_EXPORT_MASK_SET
;
779 genuser
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make sure we don't enable the floating point unit */
784 case PPC_THREAD_STATE64
:
786 xts
= (struct ppc_thread_state64
*)tstate
;
788 genuser
->save_r0
= xts
->r0
;
789 genuser
->save_r1
= xts
->r1
;
790 genuser
->save_r2
= xts
->r2
;
791 genuser
->save_r3
= xts
->r3
;
792 genuser
->save_r4
= xts
->r4
;
793 genuser
->save_r5
= xts
->r5
;
794 genuser
->save_r6
= xts
->r6
;
795 genuser
->save_r7
= xts
->r7
;
796 genuser
->save_r8
= xts
->r8
;
797 genuser
->save_r9
= xts
->r9
;
798 genuser
->save_r10
= xts
->r10
;
799 genuser
->save_r11
= xts
->r11
;
800 genuser
->save_r12
= xts
->r12
;
801 genuser
->save_r13
= xts
->r13
;
802 genuser
->save_r14
= xts
->r14
;
803 genuser
->save_r15
= xts
->r15
;
804 genuser
->save_r16
= xts
->r16
;
805 genuser
->save_r17
= xts
->r17
;
806 genuser
->save_r18
= xts
->r18
;
807 genuser
->save_r19
= xts
->r19
;
808 genuser
->save_r20
= xts
->r20
;
809 genuser
->save_r21
= xts
->r21
;
810 genuser
->save_r22
= xts
->r22
;
811 genuser
->save_r23
= xts
->r23
;
812 genuser
->save_r24
= xts
->r24
;
813 genuser
->save_r25
= xts
->r25
;
814 genuser
->save_r26
= xts
->r26
;
815 genuser
->save_r27
= xts
->r27
;
816 genuser
->save_r28
= xts
->r28
;
817 genuser
->save_r29
= xts
->r29
;
818 genuser
->save_r30
= xts
->r30
;
819 genuser
->save_r31
= xts
->r31
;
821 genuser
->save_cr
= xts
->cr
;
822 genuser
->save_xer
= xts
->xer
;
823 genuser
->save_lr
= xts
->lr
;
824 genuser
->save_ctr
= xts
->ctr
;
825 genuser
->save_srr0
= xts
->srr0
;
826 genuser
->save_vrsave
= xts
->vrsave
; /* VRSAVE register (Altivec only) */
828 genuser
->save_srr1
= MSR_PREPARE_FOR_IMPORT(genuser
->save_srr1
, xts
->srr1
); /* Set the bits we can change */
830 genuser
->save_srr1
|= MSR_EXPORT_MASK_SET
;
832 genuser
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make sure we don't enable the floating point unit */
837 case PPC_EXCEPTION_STATE
:
839 es
= (struct ppc_exception_state
*) tstate
;
841 genuser
->save_dar
= (uint64_t)es
->dar
;
842 genuser
->save_dsisr
= es
->dsisr
;
843 genuser
->save_exception
= es
->exception
;
848 * It's pretty worthless to try to change this stuff, but we'll do it anyway.
851 case PPC_EXCEPTION_STATE64
:
853 xes
= (struct ppc_exception_state
*) tstate
;
855 genuser
->save_dar
= xes
->dar
;
856 genuser
->save_dsisr
= xes
->dsisr
;
857 genuser
->save_exception
= xes
->exception
;
861 case PPC_FLOAT_STATE
:
863 toss_live_fpu(thr_act
->mact
.curctx
); /* Toss my floating point if live anywhere */
865 fsv
= find_user_fpu(thr_act
); /* Get the user's floating point context */
867 if(!fsv
) { /* Do we have one yet? */
868 fsv
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
869 fsv
->save_hdr
.save_flags
= (fsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
870 fsv
->save_hdr
.save_act
= (struct thread_activation
*)thr_act
; /* Point to the activation */
871 fsv
->save_hdr
.save_prev
= 0; /* Mark no more */
872 fsv
->save_hdr
.save_level
= 0; /* Mark user state */
874 if(!thr_act
->mact
.curctx
->FPUsave
) thr_act
->mact
.curctx
->FPUsave
= fsv
; /* If no floating point, chain us first */
877 fsvn
= fsvo
= thr_act
->mact
.curctx
->FPUsave
; /* Remember first one */
879 while (fsvn
) { /* Go until we hit the end */
880 fsvo
= fsvn
; /* Remember the previous one */
881 fsvn
= CAST_DOWN(savearea_fpu
*, fsvo
->save_hdr
.save_prev
); /* Skip on to the next */
884 fsvo
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)fsv
); /* Queue us on in */
889 fs
= (struct ppc_float_state
*) tstate
; /* Point to source */
892 bcopy((char *)fs
, (char *)&fsv
->save_fp0
, 32*8); /* Move in the 32 registers */
894 genuser
->save_fpscr
= fs
->fpscr
; /* Copy the fpscr value to normal */
899 case PPC_VECTOR_STATE
:
901 toss_live_vec(thr_act
->mact
.curctx
); /* Toss my vector if live anywhere */
903 vsv
= find_user_vec(thr_act
); /* Get the user's vector context */
905 if(!vsv
) { /* Do we have one yet? */
906 vsv
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
907 vsv
->save_hdr
.save_flags
= (vsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as vector */
908 vsv
->save_hdr
.save_act
= (struct thread_activation
*)thr_act
; /* Point to the activation */
909 vsv
->save_hdr
.save_prev
= 0; /* Mark no more */
910 vsv
->save_hdr
.save_level
= 0; /* Mark user state */
912 if(!thr_act
->mact
.curctx
->VMXsave
) thr_act
->mact
.curctx
->VMXsave
= vsv
; /* If no vector, chain us first */
915 vsvn
= vsvo
= thr_act
->mact
.curctx
->VMXsave
; /* Remember first one */
917 while (vsvn
) { /* Go until we hit the end */
918 vsvo
= vsvn
; /* Remember the previous one */
919 vsvn
= CAST_DOWN(savearea_vec
*, vsvo
->save_hdr
.save_prev
); /* Skip on to the next */
922 vsvo
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)vsv
); /* Queue us on in */
927 vs
= (struct ppc_vector_state
*) tstate
; /* Point to source */
929 bcopy((char *)vs
, (char *)&vsv
->save_vr0
, 32*16); /* 32 registers plus status and validity and pad */
930 vsv
->save_vrvalid
= vs
->save_vrvalid
; /* Set validity bits */
933 for(i
= 0; i
< 4; i
++) genuser
->save_vscr
[i
] = vs
->save_vscr
[i
]; /* Set value for vscr */
939 return KERN_INVALID_ARGUMENT
;
944 * Duplicates the context of one thread into a new one.
945 * The new thread is assumed to be new and have no user state contexts except maybe a general one.
946 * We also assume that the old thread can't be running anywhere.
948 * We're only going to be duplicating user context here. That means that we will have to
949 * eliminate any floating point or vector kernel contexts and carry across the user state ones.
952 kern_return_t
machine_thread_dup(thread_act_t self
, thread_act_t target
) {
955 savearea_fpu
*fsv
, *fsvn
;
956 savearea_vec
*vsv
, *vsvn
;
957 unsigned int spc
, i
, *srs
;
959 fpu_save(self
->mact
.curctx
); /* Make certain floating point state is all saved */
960 vec_save(self
->mact
.curctx
); /* Make certain the vector state is all saved */
962 sv
= get_user_regs(target
); /* Allocate and initialze context in the new activation */
964 osv
= find_user_regs(self
); /* Find the original context */
966 return (KERN_FAILURE
);
968 bcopy((char *)((unsigned int)osv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
969 (char *)((unsigned int)sv
+ sizeof(savearea_comm
)),
970 sizeof(struct savearea
) - sizeof(savearea_comm
));
972 sv
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make certain that floating point and vector are turned off */
974 fsv
= find_user_fpu(self
); /* Get any user floating point */
976 target
->mact
.curctx
->FPUsave
= 0; /* Assume no floating point */
978 if(fsv
) { /* Did we find one? */
979 fsvn
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
980 fsvn
->save_hdr
.save_flags
= (fsvn
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
981 fsvn
->save_hdr
.save_act
= (struct thread_activation
*)target
; /* Point to the activation */
982 fsvn
->save_hdr
.save_prev
= 0; /* Mark no more */
983 fsvn
->save_hdr
.save_level
= 0; /* Mark user state */
985 target
->mact
.curctx
->FPUsave
= fsvn
; /* Chain in the floating point */
987 bcopy((char *)((unsigned int)fsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
988 (char *)((unsigned int)fsvn
+ sizeof(savearea_comm
)),
989 sizeof(struct savearea
) - sizeof(savearea_comm
));
992 vsv
= find_user_vec(self
); /* Get any user vector */
994 target
->mact
.curctx
->VMXsave
= 0; /* Assume no vector */
996 if(vsv
) { /* Did we find one? */
997 vsvn
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
998 vsvn
->save_hdr
.save_flags
= (vsvn
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as float */
999 vsvn
->save_hdr
.save_act
= (struct thread_activation
*)target
; /* Point to the activation */
1000 vsvn
->save_hdr
.save_prev
= 0; /* Mark no more */
1001 vsvn
->save_hdr
.save_level
= 0; /* Mark user state */
1003 target
->mact
.curctx
->VMXsave
= vsvn
; /* Chain in the floating point */
1005 bcopy((char *)((unsigned int)vsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1006 (char *)((unsigned int)vsvn
+ sizeof(savearea_comm
)),
1007 sizeof(struct savearea
) - sizeof(savearea_comm
));
1010 return (KERN_SUCCESS
);
1014 * Initializes a fresh set of user state values. If there is no user state context,
1015 * one is created. Floats and VMX are not created.
1017 * We only set initial values if there was no context found.
1020 savearea
*get_user_regs(thread_act_t act
) {
1023 unsigned int spc
, i
, *srs
;
1026 return act
->mact
.upcb
;
1028 sv
= act
->mact
.pcb
; /* Get the top savearea on the stack */
1029 osv
= 0; /* Set no user savearea yet */
1031 while(sv
) { /* Find the user context */
1032 osv
= sv
; /* Save the last one */
1033 sv
= CAST_DOWN(savearea
*, sv
->save_hdr
.save_prev
); /* Get the previous context */
1036 sv
= save_alloc(); /* Get one */
1037 sv
->save_hdr
.save_flags
= (sv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVgeneral
<< SAVtypeshft
); /* Mark as in use as general */
1038 sv
->save_hdr
.save_act
= (struct thread_activation
*)act
; /* Point to the activation */
1039 sv
->save_hdr
.save_prev
= 0; /* Mark no more */
1040 sv
->save_hdr
.save_level
= 0; /* Mark user state */
1042 if(osv
) { /* Did we already have one? */
1043 osv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)sv
); /* Chain us on the end */
1045 else { /* We are the first */
1046 act
->mact
.pcb
= sv
; /* Put it there */
1048 act
->mact
.upcb
= sv
; /* Set user pcb */
1050 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
1051 ((unsigned int *)&sv
->save_r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
1052 ((unsigned int *)&sv
->save_r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
1056 sv
->save_lr
= (uint64_t)FloatInit
;
1057 sv
->save_ctr
= (uint64_t)FloatInit
;
1058 sv
->save_srr0
= (uint64_t)FloatInit
;
1059 sv
->save_srr1
= (uint64_t)MSR_EXPORT_MASK_SET
;
1061 sv
->save_fpscr
= 0; /* Clear all floating point exceptions */
1063 sv
->save_vrsave
= 0; /* Set the vector save state */
1064 sv
->save_vscr
[0] = 0x00000000;
1065 sv
->save_vscr
[1] = 0x00000000;
1066 sv
->save_vscr
[2] = 0x00000000;
1067 sv
->save_vscr
[3] = 0x00010000; /* Disable java mode and clear saturated */
1069 return sv
; /* Bye bye... */
1073 * Find the user state context. If there is no user state context,
1074 * we just return a 0.
1077 savearea
*find_user_regs(thread_act_t act
) {
1078 return act
->mact
.upcb
;
1081 /* The name of this call is something of a misnomer since the mact.pcb can
1082 * contain chained saveareas, but it will do for now..
1084 savearea
*find_kern_regs(thread_act_t act
) {
1085 return act
->mact
.pcb
;
1089 * Find the user state floating point context. If there is no user state context,
1090 * we just return a 0.
1093 savearea_fpu
*find_user_fpu(thread_act_t act
) {
1097 fsv
= act
->mact
.curctx
->FPUsave
; /* Get the start of the floating point chain */
1099 while(fsv
) { /* Look until the end or we find it */
1100 if(!(fsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
1101 fsv
= CAST_DOWN(savearea_fpu
*, fsv
->save_hdr
.save_prev
); /* Try the previous one */
1104 return fsv
; /* Bye bye... */
1108 * Find the user state vector context. If there is no user state context,
1109 * we just return a 0.
1112 savearea_vec
*find_user_vec(thread_act_t act
) {
1116 vsv
= act
->mact
.curctx
->VMXsave
; /* Get the start of the vector chain */
1118 while(vsv
) { /* Look until the end or we find it */
1119 if(!(vsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
1120 vsv
= CAST_DOWN(savearea_vec
*, vsv
->save_hdr
.save_prev
); /* Try the previous one */
1123 return vsv
; /* Bye bye... */
1126 * Find the user state vector context for the current thread. If there is no user state context,
1127 * we just return a 0.
1130 savearea_vec
*find_user_vec_curr(void) {
1135 act
= current_act(); /* Get the current activation */
1137 vec_save(act
->mact
.curctx
); /* Force save if live */
1139 vsv
= act
->mact
.curctx
->VMXsave
; /* Get the start of the vector chain */
1141 while(vsv
) { /* Look until the end or we find it */
1142 if(!(vsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
1143 vsv
= CAST_DOWN(savearea_vec
*, vsv
->save_hdr
.save_prev
); /* Try the previous one */
1146 return vsv
; /* Bye bye... */
1152 * Return the user stack pointer from the machine
1153 * dependent thread state info.
1159 thread_state_t tstate
,
1161 vm_offset_t
*user_stack
,
1165 struct ppc_thread_state
*state
;
1170 if (*user_stack
== 0)
1171 *user_stack
= USRSTACK
;
1176 case PPC_THREAD_STATE
:
1177 if (count
< PPC_THREAD_STATE_COUNT
)
1178 return (KERN_INVALID_ARGUMENT
);
1180 state
= (struct ppc_thread_state
*) tstate
;
1183 * If a valid user stack is specified, use it.
1185 *user_stack
= state
->r1
? state
->r1
: USRSTACK
;
1187 if (customstack
&& state
->r1
)
1192 return (KERN_INVALID_ARGUMENT
);
1195 return (KERN_SUCCESS
);
1200 * thread_setuserstack:
1202 * Sets the user stack pointer into the machine
1203 * dependent thread state info.
1205 void thread_setuserstack(thread_act_t act
, unsigned int user_stack
)
1209 sv
= get_user_regs(act
); /* Get the user state registers */
1211 sv
->save_r1
= (uint64_t)user_stack
;
1217 * thread_adjuserstack:
1219 * Returns the adjusted user stack pointer from the machine
1220 * dependent thread state info.
1222 unsigned int thread_adjuserstack(thread_act_t act
, int adjust
)
1226 sv
= get_user_regs(act
); /* Get the user state registers */
1228 sv
->save_r1
+= adjust
; /* Adjust the stack */
1230 return (unsigned int)sv
->save_r1
; /* Return the adjusted stack */
1235 * thread_setentrypoint:
1237 * Sets the user PC into the machine
1238 * dependent thread state info.
1241 void thread_setentrypoint(thread_act_t act
, unsigned int entry
)
1245 sv
= get_user_regs(act
); /* Get the user state registers */
1247 sv
->save_srr0
= (uint64_t)entry
;
1256 thread_state_t tstate
,
1258 vm_offset_t
*entry_point
1261 struct ppc_thread_state
*state
;
1266 if (*entry_point
== 0)
1267 *entry_point
= VM_MIN_ADDRESS
;
1271 case PPC_THREAD_STATE
:
1272 if (count
< PPC_THREAD_STATE_COUNT
)
1273 return (KERN_INVALID_ARGUMENT
);
1275 state
= (struct ppc_thread_state
*) tstate
;
1278 * If a valid entry point is specified, use it.
1280 *entry_point
= state
->srr0
? state
->srr0
: VM_MIN_ADDRESS
;
1283 return (KERN_INVALID_ARGUMENT
);
1286 return (KERN_SUCCESS
);
1289 unsigned int get_msr_exportmask(void)
1291 return (MSR_EXPORT_MASK_SET
);
1294 unsigned int get_msr_nbits(void)
1296 return (MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1298 unsigned int get_msr_rbits(void)
1300 return (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1303 void ppc_checkthreadstate(void * tsptr
, int flavor
)
1305 if (flavor
== PPC_THREAD_STATE64
) {
1306 struct ppc_thread_state64
*ts64
=(struct ppc_thread_state64
*)tsptr
;
1308 /* Make sure naughty bits are off and necessary bits are on */
1309 ts64
->srr1
&= ~(MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1310 ts64
->srr1
|= (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1312 struct ppc_thread_state
*ts
=(struct ppc_thread_state
*)tsptr
;
1314 /* Make sure naughty bits are off and necessary bits are on */
1315 ts
->srr1
&= ~(MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1316 ts
->srr1
|= (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1321 void thread_set_child(thread_act_t child
, int pid
)
1323 struct savearea
*child_state
;
1325 child_state
= get_user_regs(child
);
1327 child_state
->save_r3
= (uint_t
)pid
;
1328 child_state
->save_r4
= 1ULL;
1330 void thread_set_parent(thread_act_t parent
, int pid
)
1332 struct savearea
*parent_state
;
1334 parent_state
= get_user_regs(parent
);
1336 parent_state
->save_r3
= (uint64_t)pid
;
1337 parent_state
->save_r4
= 0;
1341 * Saves the complete context (general, floating point, and vector) of the current activation.
1342 * We will collect everything into an opaque block of 1 to 3 saveareas and pass back a
1345 * The savearea is made to look like it belongs to the source activation. This needs to
1346 * be adjusted when these contexts are attached to a new activation.
1350 void *act_thread_csave(void) {
1353 savearea_fpu
*fsv
, *ofsv
;
1354 savearea_vec
*vsv
, *ovsv
;
1355 unsigned int spc
, i
, *srs
;
1359 act
= current_act(); /* Find ourselves */
1361 fpu_save(act
->mact
.curctx
); /* Make certain floating point state is all saved */
1362 vec_save(act
->mact
.curctx
); /* Make certain the vector state is all saved */
1364 osv
= find_user_regs(act
); /* Get our savearea */
1367 panic("act_thread_csave: attempting to preserve the context of an activation with none (%08X)\n", act
);
1370 sv
= save_alloc(); /* Get a fresh save area to save into */
1371 sv
->save_hdr
.save_flags
= (sv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVgeneral
<< SAVtypeshft
); /* Mark as in use as general */
1372 sv
->save_hdr
.save_act
= (struct thread_activation
*)act
; /* Point to the activation */
1373 sv
->save_hdr
.save_prev
= 0; /* Mark no more */
1374 sv
->save_hdr
.save_level
= 0; /* Mark user state */
1377 bcopy((char *)((unsigned int)osv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1378 (char *)((unsigned int)sv
+ sizeof(savearea_comm
)),
1379 sizeof(struct savearea
) - sizeof(savearea_comm
));
1381 sv
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make certain that floating point and vector are turned off */
1383 sv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1384 sv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1387 ofsv
= find_user_fpu(act
); /* Get any user floating point */
1389 sv
->save_hdr
.save_misc0
= 0; /* Assume no floating point */
1391 if(ofsv
) { /* Did we find one? */
1392 fsv
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
1393 fsv
->save_hdr
.save_flags
= (fsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
1394 fsv
->save_hdr
.save_act
= (struct thread_activation
*)act
; /* Point to the activation */
1395 fsv
->save_hdr
.save_prev
= 0; /* Mark no more */
1396 fsv
->save_hdr
.save_level
= 0; /* Mark user state */
1397 fsv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1398 fsv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1400 sv
->save_hdr
.save_misc0
= (uint64_t)((uintptr_t)fsv
); /* Remember this one */
1402 bcopy((char *)((unsigned int)ofsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1403 (char *)((unsigned int)fsv
+ sizeof(savearea_comm
)),
1404 sizeof(struct savearea
) - sizeof(savearea_comm
));
1407 ovsv
= find_user_vec(act
); /* Get any user vector */
1409 sv
->save_hdr
.save_misc1
= 0; /* Assume no vector */
1411 if(ovsv
) { /* Did we find one? */
1412 vsv
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
1413 vsv
->save_hdr
.save_flags
= (vsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as float */
1414 vsv
->save_hdr
.save_act
= (struct thread_activation
*)act
; /* Point to the activation */
1415 vsv
->save_hdr
.save_prev
= 0; /* Mark no more */
1416 vsv
->save_hdr
.save_level
= 0; /* Mark user state */
1417 vsv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1418 vsv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1420 sv
->save_hdr
.save_misc1
= (uint64_t)((uintptr_t)vsv
); /* Chain in the floating point */
1422 bcopy((char *)((unsigned int)ovsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1423 (char *)((unsigned int)vsv
+ sizeof(savearea_comm
)),
1424 sizeof(struct savearea
) - sizeof(savearea_comm
));
1427 return (void *)sv
; /* Bye bye... */
1433 * Attaches saved user state context to an activation. We will replace any
1434 * user state context with what is passed in. The saved context consists of a
1435 * savearea that was setup by
1436 * We will collect everything into one savearea and pass that back.
1438 * The savearea is made to look like it belongs to the source activation. This needs to
1439 * be adjusted when these contexts are attached to a new activation.
1443 void act_thread_catt(void *ctx
) {
1445 savearea
*sv
, *osv
, *psv
;
1446 savearea_fpu
*fsv
, *ofsv
, *pfsv
;
1447 savearea_vec
*vsv
, *ovsv
, *pvsv
;
1448 unsigned int spc
, i
, *srs
;
1451 sv
= (savearea
*)ctx
; /* Make this easier for C */
1453 fsv
= CAST_DOWN(savearea_fpu
*, sv
->save_hdr
.save_misc0
); /* Get a possible floating point savearea */
1454 vsv
= CAST_DOWN(savearea_vec
*, sv
->save_hdr
.save_misc1
); /* Get a possible vector savearea */
1456 if((sv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (sv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1457 panic("act_thread_catt: attempt to attach invalid general context savearea - %08X\n", sv
); /* Die */
1460 if(fsv
&& ((fsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (fsv
->save_hdr
.save_misc3
!= 0xE5DA11A5))) { /* See if valid savearea */
1461 panic("act_thread_catt: attempt to attach invalid float context savearea - %08X\n", fsv
); /* Die */
1464 if(vsv
&& ((vsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (vsv
->save_hdr
.save_misc3
!= 0xE5DA11A5))) { /* See if valid savearea */
1465 panic("act_thread_catt: attempt to attach invalid vector context savearea - %08X\n", vsv
); /* Die */
1468 act
= current_act(); /* Find ourselves */
1470 toss_live_fpu(act
->mact
.curctx
); /* Toss my floating point if live anywhere */
1471 toss_live_vec(act
->mact
.curctx
); /* Toss my vector if live anywhere */
1473 sv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1474 sv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1475 sv
->save_hdr
.save_act
= (struct thread_activation
*)act
; /* Set us as owner */
1477 spc
= (unsigned int)act
->map
->pmap
->space
; /* Get the space we're in */
1479 osv
= act
->mact
.pcb
; /* Get the top general savearea */
1481 while(osv
) { /* Any saved state? */
1482 if(osv
->save_srr1
& MASK(MSR_PR
)) break; /* Leave if this is user state */
1483 psv
= osv
; /* Save previous savearea address */
1484 osv
= CAST_DOWN(savearea
*, osv
->save_hdr
.save_prev
); /* Get one underneath our's */
1487 if(osv
) { /* Did we find one? */
1488 if(psv
) psv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1489 else act
->mact
.pcb
= 0; /* to the start if the only one */
1491 save_release(osv
); /* Nope, release it */
1495 if(psv
) psv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)sv
); /* Chain us to the end or */
1496 else act
->mact
.pcb
= (pcb_t
)sv
; /* to the start if the only one */
1497 act
->mact
.upcb
= (pcb_t
)sv
; /* Set the user pcb */
1499 ovsv
= act
->mact
.curctx
->VMXsave
; /* Get the top vector savearea */
1502 while(ovsv
) { /* Any VMX saved state? */
1503 if(!(ovsv
->save_hdr
.save_level
)) break; /* Leave if this is user state */
1504 pvsv
= ovsv
; /* Save previous savearea address */
1505 ovsv
= CAST_DOWN(savearea_vec
*, ovsv
->save_hdr
.save_prev
); /* Get one underneath our's */
1508 if(ovsv
) { /* Did we find one? */
1509 if(pvsv
) pvsv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1510 else act
->mact
.curctx
->VMXsave
= 0; /* to the start if the only one */
1512 save_release((savearea
*)ovsv
); /* Nope, release it */
1515 if(vsv
) { /* Are we sticking any vector on this one? */
1516 if(pvsv
) pvsv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)vsv
); /* Yes, chain us to the end or */
1517 else act
->mact
.curctx
->VMXsave
= vsv
; /* to the start if the only one */
1519 vsv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1520 vsv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1521 vsv
->save_hdr
.save_act
= (struct thread_activation
*)act
; /* Set us as owner */
1524 ofsv
= act
->mact
.curctx
->FPUsave
; /* Get the top float savearea */
1527 while(ofsv
) { /* Any float saved state? */
1528 if(!(ofsv
->save_hdr
.save_level
)) break; /* Leave if this is user state */
1529 pfsv
= ofsv
; /* Save previous savearea address */
1530 ofsv
= CAST_DOWN(savearea_fpu
*, ofsv
->save_hdr
.save_prev
); /* Get one underneath our's */
1533 if(ofsv
) { /* Did we find one? */
1534 if(pfsv
) pfsv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1535 else act
->mact
.curctx
->FPUsave
= 0; /* to the start if the only one */
1537 save_release((savearea
*)ofsv
); /* Nope, release it */
1540 if(fsv
) { /* Are we sticking any vector on this one? */
1541 if(pfsv
) pfsv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)fsv
); /* Yes, chain us to the end or */
1542 else act
->mact
.curctx
->FPUsave
= fsv
; /* to the start if the only one */
1544 fsv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1545 fsv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1546 fsv
->save_hdr
.save_act
= (struct thread_activation
*)act
; /* Set us as owner */
1554 * Releases saved context. We need this because the saved context is opague.
1555 * be adjusted when these contexts are attached to a new activation.
1559 void act_thread_cfree(void *ctx
) {
1562 savearea_fpu
*fsv
, *ofsv
;
1563 savearea_vec
*vsv
, *ovsv
, *pvsv
;
1565 sv
= (savearea
*)ctx
; /* Make this easier for C */
1567 fsv
= CAST_DOWN(savearea_fpu
*, sv
->save_hdr
.save_misc0
); /* Get a possible floating point savearea */
1568 vsv
= CAST_DOWN(savearea_vec
*, sv
->save_hdr
.save_misc1
); /* Get a possible vector savearea */
1570 if((sv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (sv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1571 panic("act_thread_cfree: attempt to detatch invalid general context savearea - %08X\n", sv
); /* Die */
1574 save_release(sv
); /* Toss the general savearea */
1576 if(fsv
) { /* See if there is any saved floating point */
1577 if((fsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (fsv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1578 panic("act_thread_cfree: attempt to detatch invalid float context savearea - %08X\n", fsv
); /* Die */
1581 save_release((savearea
*)fsv
); /* Toss saved context */
1584 if(vsv
) { /* See if there is any saved floating point */
1585 if((vsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (vsv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1586 panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %08X\n", vsv
); /* Die */
1589 save_release((savearea
*)vsv
); /* Toss saved context */
1596 * thread_enable_fpe:
1598 * enables or disables floating point exceptions for the thread.
1601 int thread_enable_fpe(thread_act_t act
, int onoff
)
1604 unsigned int oldmsr
;
1606 sv
= find_user_regs(act
); /* Find the user registers */
1607 if(!sv
) sv
= get_user_regs(act
); /* Didn't find any, allocate and initialize o
1610 oldmsr
= sv
->save_srr1
; /* Get the old msr */
1612 if(onoff
) sv
->save_srr1
= oldmsr
| MASK(MSR_FE0
) | MASK(MSR_FE1
); /* Flip on precise FP exceptions */
1613 else sv
->save_srr1
= oldmsr
& ~(MASK(MSR_FE0
) | MASK(MSR_FE1
)); /* Flip on precise FP exceptions */
1615 return ((oldmsr
& (MASK(MSR_FE0
) | MASK(MSR_FE1
))) != 0); /* Return if it was enabled or not */