2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
33 #include <kern/thread.h>
34 #include <kern/misc_protos.h>
35 #include <mach/ppc/thread_status.h>
36 #include <ppc/proc_reg.h>
37 #include <ppc/cpu_internal.h>
38 #include <ppc/exception.h>
39 #include <ppc/misc_protos.h>
40 #include <ppc/fpu_protos.h>
41 #include <ppc/savearea.h>
42 #include <ppc/thread.h>
43 #include <ppc/Firmware.h>
45 typedef unsigned int fixpt_t
; /* XXX <sys/resource.h> not self contained */
46 #include <ppc/vmparam.h> /* USRSTACK, etc. */
48 #include <vm/vm_map.h>
50 extern unsigned int killprint
;
51 extern double FloatInit
;
52 extern unsigned long QNaNbarbarian
[4];
73 unsigned int get_msr_exportmask(void);
74 unsigned int get_msr_nbits(void);
75 unsigned int get_msr_rbits(void);
76 void ppc_checkthreadstate(void *, int);
77 void thread_set_child(thread_t child
, int pid
);
78 void thread_set_parent(thread_t parent
, int pid
);
79 void thread_set_cthreadself(thread_t thread
, uint64_t pself
, int isLP64
);
82 * Maps state flavor to number of words in the state:
84 /* __private_extern__ */
85 unsigned int _MachineStateCount
[] = {
87 PPC_THREAD_STATE_COUNT
,
88 PPC_FLOAT_STATE_COUNT
,
89 PPC_EXCEPTION_STATE_COUNT
,
90 PPC_VECTOR_STATE_COUNT
,
91 PPC_THREAD_STATE64_COUNT
,
92 PPC_EXCEPTION_STATE64_COUNT
,
98 * Get the status of the specified thread.
102 machine_thread_get_state(
104 thread_flavor_t flavor
,
105 thread_state_t tstate
,
106 mach_msg_type_number_t
*count
)
109 register struct savearea
*sv
; /* Pointer to the context savearea */
110 register savearea_fpu
*fsv
;
111 register savearea_vec
*vsv
;
112 struct savearea
*genuser
;
114 unsigned int vrvalidwrk
;
116 register struct ppc_thread_state
*ts
;
117 register struct ppc_thread_state64
*xts
;
118 register struct ppc_exception_state
*es
;
119 register struct ppc_exception_state64
*xes
;
120 register struct ppc_float_state
*fs
;
121 register struct ppc_vector_state
*vs
;
123 genuser
= find_user_regs(thread
);
127 case THREAD_STATE_FLAVOR_LIST
:
130 return (KERN_INVALID_ARGUMENT
);
133 tstate
[0] = PPC_THREAD_STATE
;
134 tstate
[1] = PPC_FLOAT_STATE
;
135 tstate
[2] = PPC_EXCEPTION_STATE
;
136 tstate
[3] = PPC_VECTOR_STATE
;
137 tstate
[4] = PPC_THREAD_STATE64
;
138 tstate
[5] = PPC_EXCEPTION_STATE64
;
143 case PPC_THREAD_STATE
:
145 if (*count
< PPC_THREAD_STATE_COUNT
) { /* Is the count ok? */
146 return KERN_INVALID_ARGUMENT
;
149 ts
= (struct ppc_thread_state
*) tstate
;
151 sv
= genuser
; /* Copy this over */
153 if(sv
) { /* Is there a save area yet? */
154 ts
->r0
= (unsigned int)sv
->save_r0
;
155 ts
->r1
= (unsigned int)sv
->save_r1
;
156 ts
->r2
= (unsigned int)sv
->save_r2
;
157 ts
->r3
= (unsigned int)sv
->save_r3
;
158 ts
->r4
= (unsigned int)sv
->save_r4
;
159 ts
->r5
= (unsigned int)sv
->save_r5
;
160 ts
->r6
= (unsigned int)sv
->save_r6
;
161 ts
->r7
= (unsigned int)sv
->save_r7
;
162 ts
->r8
= (unsigned int)sv
->save_r8
;
163 ts
->r9
= (unsigned int)sv
->save_r9
;
164 ts
->r10
= (unsigned int)sv
->save_r10
;
165 ts
->r11
= (unsigned int)sv
->save_r11
;
166 ts
->r12
= (unsigned int)sv
->save_r12
;
167 ts
->r13
= (unsigned int)sv
->save_r13
;
168 ts
->r14
= (unsigned int)sv
->save_r14
;
169 ts
->r15
= (unsigned int)sv
->save_r15
;
170 ts
->r16
= (unsigned int)sv
->save_r16
;
171 ts
->r17
= (unsigned int)sv
->save_r17
;
172 ts
->r18
= (unsigned int)sv
->save_r18
;
173 ts
->r19
= (unsigned int)sv
->save_r19
;
174 ts
->r20
= (unsigned int)sv
->save_r20
;
175 ts
->r21
= (unsigned int)sv
->save_r21
;
176 ts
->r22
= (unsigned int)sv
->save_r22
;
177 ts
->r23
= (unsigned int)sv
->save_r23
;
178 ts
->r24
= (unsigned int)sv
->save_r24
;
179 ts
->r25
= (unsigned int)sv
->save_r25
;
180 ts
->r26
= (unsigned int)sv
->save_r26
;
181 ts
->r27
= (unsigned int)sv
->save_r27
;
182 ts
->r28
= (unsigned int)sv
->save_r28
;
183 ts
->r29
= (unsigned int)sv
->save_r29
;
184 ts
->r30
= (unsigned int)sv
->save_r30
;
185 ts
->r31
= (unsigned int)sv
->save_r31
;
186 ts
->cr
= (unsigned int)sv
->save_cr
;
187 ts
->xer
= (unsigned int)sv
->save_xer
;
188 ts
->lr
= (unsigned int)sv
->save_lr
;
189 ts
->ctr
= (unsigned int)sv
->save_ctr
;
190 ts
->srr0
= (unsigned int)sv
->save_srr0
;
191 ts
->srr1
= (unsigned int)sv
->save_srr1
;
192 ts
->mq
= 0; /* MQ register (601 only) */
193 ts
->vrsave
= (unsigned int)sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
195 else { /* No user state yet. Save seemingly random values. */
197 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
198 ((unsigned int *)&ts
->r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
199 ((unsigned int *)&ts
->r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
203 ts
->lr
= ((unsigned int *)&FloatInit
)[0];
204 ts
->ctr
= ((unsigned int *)&FloatInit
)[1];
205 ts
->srr0
= ((unsigned int *)&FloatInit
)[0];
206 ts
->srr1
= MSR_EXPORT_MASK_SET
;
208 ts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
211 *count
= PPC_THREAD_STATE_COUNT
; /* Pass back the amount we actually copied */
215 case PPC_THREAD_STATE64
:
217 if (*count
< PPC_THREAD_STATE64_COUNT
) { /* Is the count ok? */
218 return KERN_INVALID_ARGUMENT
;
221 xts
= (struct ppc_thread_state64
*) tstate
;
223 sv
= genuser
; /* Copy this over */
225 if(sv
) { /* Is there a save area yet? */
226 xts
->r0
= sv
->save_r0
;
227 xts
->r1
= sv
->save_r1
;
228 xts
->r2
= sv
->save_r2
;
229 xts
->r3
= sv
->save_r3
;
230 xts
->r4
= sv
->save_r4
;
231 xts
->r5
= sv
->save_r5
;
232 xts
->r6
= sv
->save_r6
;
233 xts
->r7
= sv
->save_r7
;
234 xts
->r8
= sv
->save_r8
;
235 xts
->r9
= sv
->save_r9
;
236 xts
->r10
= sv
->save_r10
;
237 xts
->r11
= sv
->save_r11
;
238 xts
->r12
= sv
->save_r12
;
239 xts
->r13
= sv
->save_r13
;
240 xts
->r14
= sv
->save_r14
;
241 xts
->r15
= sv
->save_r15
;
242 xts
->r16
= sv
->save_r16
;
243 xts
->r17
= sv
->save_r17
;
244 xts
->r18
= sv
->save_r18
;
245 xts
->r19
= sv
->save_r19
;
246 xts
->r20
= sv
->save_r20
;
247 xts
->r21
= sv
->save_r21
;
248 xts
->r22
= sv
->save_r22
;
249 xts
->r23
= sv
->save_r23
;
250 xts
->r24
= sv
->save_r24
;
251 xts
->r25
= sv
->save_r25
;
252 xts
->r26
= sv
->save_r26
;
253 xts
->r27
= sv
->save_r27
;
254 xts
->r28
= sv
->save_r28
;
255 xts
->r29
= sv
->save_r29
;
256 xts
->r30
= sv
->save_r30
;
257 xts
->r31
= sv
->save_r31
;
258 xts
->cr
= sv
->save_cr
;
259 xts
->xer
= sv
->save_xer
;
260 xts
->lr
= sv
->save_lr
;
261 xts
->ctr
= sv
->save_ctr
;
262 xts
->srr0
= sv
->save_srr0
;
263 xts
->srr1
= sv
->save_srr1
;
264 xts
->vrsave
= sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
266 else { /* No user state yet. Save seemingly random values. */
268 for(i
=0; i
< 32; i
++) { /* Fill up with defaults */
269 ((unsigned long long *)&xts
->r0
)[i
] = ((unsigned long long *)&FloatInit
)[0];
273 xts
->lr
= ((unsigned long long *)&FloatInit
)[0];
274 xts
->ctr
= ((unsigned long long *)&FloatInit
)[0];
275 xts
->srr0
= ((unsigned long long *)&FloatInit
)[0];
276 xts
->srr1
= MSR_EXPORT_MASK_SET
;
277 if(task_has_64BitAddr(thread
->task
))
278 xts
->srr1
|= (uint64_t)MASK32(MSR_SF
) << 32; /* If 64-bit task, force 64-bit mode */
279 xts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
282 *count
= PPC_THREAD_STATE64_COUNT
; /* Pass back the amount we actually copied */
285 case PPC_EXCEPTION_STATE
:
287 if (*count
< PPC_EXCEPTION_STATE_COUNT
) {
288 return KERN_INVALID_ARGUMENT
;
291 es
= (struct ppc_exception_state
*) tstate
;
292 sv
= genuser
; /* Copy this over */
294 if(sv
) { /* See if valid state yet */
295 es
->dar
= (unsigned int)sv
->save_dar
;
296 es
->dsisr
= sv
->save_dsisr
;
297 es
->exception
= sv
->save_exception
;
299 else { /* Nope, not yet */
302 es
->exception
= ((unsigned int *)&FloatInit
)[0];
305 *count
= PPC_EXCEPTION_STATE_COUNT
;
308 case PPC_EXCEPTION_STATE64
:
310 if (*count
< PPC_EXCEPTION_STATE64_COUNT
) {
311 return KERN_INVALID_ARGUMENT
;
314 xes
= (struct ppc_exception_state64
*) tstate
;
315 sv
= genuser
; /* Copy this over */
317 if(sv
) { /* See if valid state yet */
318 xes
->dar
= sv
->save_dar
;
319 xes
->dsisr
= sv
->save_dsisr
;
320 xes
->exception
= sv
->save_exception
;
322 else { /* Nope, not yet */
325 xes
->exception
= ((unsigned int *)&FloatInit
)[0];
328 *count
= PPC_EXCEPTION_STATE64_COUNT
;
331 case PPC_FLOAT_STATE
:
333 if (*count
< PPC_FLOAT_STATE_COUNT
) {
334 return KERN_INVALID_ARGUMENT
;
337 fpu_save(thread
->machine
.curctx
); /* Just in case it's live, save it */
339 fs
= (struct ppc_float_state
*) tstate
; /* Point to destination */
341 fsv
= find_user_fpu(thread
); /* Get the user's fpu savearea */
343 if(fsv
) { /* See if we have any */
344 bcopy((char *)&fsv
->save_fp0
, (char *)fs
, 32*8); /* 32 registers */
345 fs
->fpscr_pad
= 0; /* Be clean and tidy */
346 if(genuser
) fs
->fpscr
= genuser
->save_fpscr
; /* Set the fpscr value to general */
347 else fs
->fpscr
= 0; /* If no user, initialize this */
349 else { /* No floating point yet */
351 for(i
=0; i
< 32; i
++) { /* Initialize floating points */
352 fs
->fpregs
[i
] = FloatInit
; /* Initial value */
354 fs
->fpscr_pad
= 0; /* Initial value */
355 fs
->fpscr
= 0; /* Initial value */
358 *count
= PPC_FLOAT_STATE_COUNT
;
362 case PPC_VECTOR_STATE
:
364 if (*count
< PPC_VECTOR_STATE_COUNT
) {
365 return KERN_INVALID_ARGUMENT
;
368 vec_save(thread
->machine
.curctx
); /* Just in case it's live, save it */
370 vs
= (struct ppc_vector_state
*) tstate
; /* Point to destination */
372 vsv
= find_user_vec(thread
); /* Find the vector savearea */
374 if(vsv
) { /* See if we have any */
376 vrvalidwrk
= vsv
->save_vrvalid
; /* Get the valid flags */
377 vs
->save_vrvalid
= vsv
->save_vrvalid
; /* Set the valid flags */
378 if(genuser
) for(j
=0; j
< 4; j
++) vs
->save_vscr
[j
] = genuser
->save_vscr
[j
]; /* Set value for vscr */
380 vs
->save_vscr
[0] = 0; /* Set an initial value if no general user yet */
381 vs
->save_vscr
[1] = 0;
382 vs
->save_vscr
[2] = 0;
383 vs
->save_vscr
[3] = 0x00010000; /* Always start with Java mode off */
385 for(i
=0; i
< 32; i
++) { /* Copy the saved registers and invalidate the others */
386 for(j
=0; j
< 4; j
++) {
387 if(vrvalidwrk
& 0x80000000) (vs
->save_vr
)[i
][j
] =
388 ((unsigned int *)&(vsv
->save_vr0
))[(i
* 4) + j
]; /* We have this register saved */
389 else vs
->save_vr
[i
][j
] = QNaNbarbarian
[j
]; /* Set invalid value */
391 vrvalidwrk
= vrvalidwrk
<< 1; /* Shift over to the next */
394 else { /* No vector yet */
396 for(i
=0; i
< 32; i
++) { /* Initialize vector registers */
397 for(j
=0; j
< 4; j
++) vs
->save_vr
[i
][j
] = QNaNbarbarian
[j
]; /* Initial value */
400 if(genuser
) for(j
=0; j
< 4; j
++) vs
->save_vscr
[j
] = genuser
->save_vscr
[j
]; /* Set value for vscr */
402 vs
->save_vscr
[0] = 0; /* Set an initial value if no general user yet */
403 vs
->save_vscr
[1] = 0;
404 vs
->save_vscr
[2] = 0;
405 vs
->save_vscr
[3] = 0x00010000; /* Always start with Java mode off */
407 vs
->save_vrvalid
= 0; /* Clear the valid flags */
410 for (i
=0; i
< 4; i
++) vs
->save_pad5
[i
] = 0; /* Clear cruft */
411 for (i
=0; i
< 7; i
++) vs
->save_pad6
[i
] = 0; /* Clear cruft */
413 *count
= PPC_VECTOR_STATE_COUNT
;
417 return KERN_INVALID_ARGUMENT
;
420 /* Close cousin of machine_thread_get_state().
421 * This function is currently incomplete since we don't really need vector
422 * or FP for the core dump (the save area can be accessed directly if the
423 * user is so inclined). Also the function name is something of a misnomer,
424 * see the comment above find_kern_regs().
428 machine_thread_get_kern_state(
430 thread_flavor_t flavor
,
431 thread_state_t tstate
,
432 mach_msg_type_number_t
*count
)
435 register struct savearea
*sv
; /* Pointer to the context savearea */
436 struct savearea
*genkern
;
439 register struct ppc_thread_state
*ts
;
440 register struct ppc_thread_state64
*xts
;
441 register struct ppc_exception_state
*es
;
442 register struct ppc_exception_state64
*xes
;
444 genkern
= find_kern_regs(thread
);
448 case THREAD_STATE_FLAVOR_LIST
:
451 return (KERN_INVALID_ARGUMENT
);
454 tstate
[0] = PPC_THREAD_STATE
;
455 tstate
[1] = PPC_FLOAT_STATE
;
456 tstate
[2] = PPC_EXCEPTION_STATE
;
457 tstate
[3] = PPC_VECTOR_STATE
;
458 tstate
[4] = PPC_THREAD_STATE64
;
459 tstate
[5] = PPC_EXCEPTION_STATE64
;
464 case PPC_THREAD_STATE
:
466 if (*count
< PPC_THREAD_STATE_COUNT
) { /* Is the count ok? */
467 return KERN_INVALID_ARGUMENT
;
470 ts
= (struct ppc_thread_state
*) tstate
;
472 sv
= genkern
; /* Copy this over */
474 if(sv
) { /* Is there a save area yet? */
475 ts
->r0
= (unsigned int)sv
->save_r0
;
476 ts
->r1
= (unsigned int)sv
->save_r1
;
477 ts
->r2
= (unsigned int)sv
->save_r2
;
478 ts
->r3
= (unsigned int)sv
->save_r3
;
479 ts
->r4
= (unsigned int)sv
->save_r4
;
480 ts
->r5
= (unsigned int)sv
->save_r5
;
481 ts
->r6
= (unsigned int)sv
->save_r6
;
482 ts
->r7
= (unsigned int)sv
->save_r7
;
483 ts
->r8
= (unsigned int)sv
->save_r8
;
484 ts
->r9
= (unsigned int)sv
->save_r9
;
485 ts
->r10
= (unsigned int)sv
->save_r10
;
486 ts
->r11
= (unsigned int)sv
->save_r11
;
487 ts
->r12
= (unsigned int)sv
->save_r12
;
488 ts
->r13
= (unsigned int)sv
->save_r13
;
489 ts
->r14
= (unsigned int)sv
->save_r14
;
490 ts
->r15
= (unsigned int)sv
->save_r15
;
491 ts
->r16
= (unsigned int)sv
->save_r16
;
492 ts
->r17
= (unsigned int)sv
->save_r17
;
493 ts
->r18
= (unsigned int)sv
->save_r18
;
494 ts
->r19
= (unsigned int)sv
->save_r19
;
495 ts
->r20
= (unsigned int)sv
->save_r20
;
496 ts
->r21
= (unsigned int)sv
->save_r21
;
497 ts
->r22
= (unsigned int)sv
->save_r22
;
498 ts
->r23
= (unsigned int)sv
->save_r23
;
499 ts
->r24
= (unsigned int)sv
->save_r24
;
500 ts
->r25
= (unsigned int)sv
->save_r25
;
501 ts
->r26
= (unsigned int)sv
->save_r26
;
502 ts
->r27
= (unsigned int)sv
->save_r27
;
503 ts
->r28
= (unsigned int)sv
->save_r28
;
504 ts
->r29
= (unsigned int)sv
->save_r29
;
505 ts
->r30
= (unsigned int)sv
->save_r30
;
506 ts
->r31
= (unsigned int)sv
->save_r31
;
507 ts
->cr
= (unsigned int)sv
->save_cr
;
508 ts
->xer
= (unsigned int)sv
->save_xer
;
509 ts
->lr
= (unsigned int)sv
->save_lr
;
510 ts
->ctr
= (unsigned int)sv
->save_ctr
;
511 ts
->srr0
= (unsigned int)sv
->save_srr0
;
512 ts
->srr1
= (unsigned int)sv
->save_srr1
;
513 ts
->mq
= 0; /* MQ register (601 only) */
514 ts
->vrsave
= (unsigned int)sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
516 else { /* No state yet. Save seemingly random values. */
518 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
519 ((unsigned int *)&ts
->r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
520 ((unsigned int *)&ts
->r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
524 ts
->lr
= ((unsigned int *)&FloatInit
)[0];
525 ts
->ctr
= ((unsigned int *)&FloatInit
)[1];
526 ts
->srr0
= ((unsigned int *)&FloatInit
)[0];
527 ts
->srr1
= MSR_EXPORT_MASK_SET
;
529 ts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
532 *count
= PPC_THREAD_STATE_COUNT
; /* Pass back the amount we actually copied */
536 case PPC_THREAD_STATE64
:
538 if (*count
< PPC_THREAD_STATE64_COUNT
) { /* Is the count ok? */
539 return KERN_INVALID_ARGUMENT
;
542 xts
= (struct ppc_thread_state64
*) tstate
;
544 sv
= genkern
; /* Copy this over */
546 if(sv
) { /* Is there a save area yet? */
547 xts
->r0
= sv
->save_r0
;
548 xts
->r1
= sv
->save_r1
;
549 xts
->r2
= sv
->save_r2
;
550 xts
->r3
= sv
->save_r3
;
551 xts
->r4
= sv
->save_r4
;
552 xts
->r5
= sv
->save_r5
;
553 xts
->r6
= sv
->save_r6
;
554 xts
->r7
= sv
->save_r7
;
555 xts
->r8
= sv
->save_r8
;
556 xts
->r9
= sv
->save_r9
;
557 xts
->r10
= sv
->save_r10
;
558 xts
->r11
= sv
->save_r11
;
559 xts
->r12
= sv
->save_r12
;
560 xts
->r13
= sv
->save_r13
;
561 xts
->r14
= sv
->save_r14
;
562 xts
->r15
= sv
->save_r15
;
563 xts
->r16
= sv
->save_r16
;
564 xts
->r17
= sv
->save_r17
;
565 xts
->r18
= sv
->save_r18
;
566 xts
->r19
= sv
->save_r19
;
567 xts
->r20
= sv
->save_r20
;
568 xts
->r21
= sv
->save_r21
;
569 xts
->r22
= sv
->save_r22
;
570 xts
->r23
= sv
->save_r23
;
571 xts
->r24
= sv
->save_r24
;
572 xts
->r25
= sv
->save_r25
;
573 xts
->r26
= sv
->save_r26
;
574 xts
->r27
= sv
->save_r27
;
575 xts
->r28
= sv
->save_r28
;
576 xts
->r29
= sv
->save_r29
;
577 xts
->r30
= sv
->save_r30
;
578 xts
->r31
= sv
->save_r31
;
579 xts
->cr
= sv
->save_cr
;
580 xts
->xer
= sv
->save_xer
;
581 xts
->lr
= sv
->save_lr
;
582 xts
->ctr
= sv
->save_ctr
;
583 xts
->srr0
= sv
->save_srr0
;
584 xts
->srr1
= sv
->save_srr1
;
585 xts
->vrsave
= sv
->save_vrsave
; /* VRSAVE register (Altivec only) */
587 else { /* No user state yet. Save seemingly random values. */
589 for(i
=0; i
< 32; i
++) { /* Fill up with defaults */
590 ((unsigned long long *)&xts
->r0
)[i
] = ((unsigned long long *)&FloatInit
)[0];
594 xts
->lr
= ((unsigned long long *)&FloatInit
)[0];
595 xts
->ctr
= ((unsigned long long *)&FloatInit
)[0];
596 xts
->srr0
= ((unsigned long long *)&FloatInit
)[0];
597 xts
->srr1
= MSR_EXPORT_MASK_SET
;
598 xts
->vrsave
= 0; /* VRSAVE register (Altivec only) */
601 *count
= PPC_THREAD_STATE64_COUNT
; /* Pass back the amount we actually copied */
604 case PPC_EXCEPTION_STATE
:
606 if (*count
< PPC_EXCEPTION_STATE_COUNT
) {
607 return KERN_INVALID_ARGUMENT
;
610 es
= (struct ppc_exception_state
*) tstate
;
611 sv
= genkern
; /* Copy this over */
613 if(sv
) { /* See if valid state yet */
614 es
->dar
= (unsigned int)sv
->save_dar
;
615 es
->dsisr
= sv
->save_dsisr
;
616 es
->exception
= sv
->save_exception
;
618 else { /* Nope, not yet */
621 es
->exception
= ((unsigned int *)&FloatInit
)[0];
624 *count
= PPC_EXCEPTION_STATE_COUNT
;
627 case PPC_EXCEPTION_STATE64
:
629 if (*count
< PPC_EXCEPTION_STATE64_COUNT
) {
630 return KERN_INVALID_ARGUMENT
;
633 xes
= (struct ppc_exception_state64
*) tstate
;
634 sv
= genkern
; /* Copy this over */
636 if(sv
) { /* See if valid state yet */
637 xes
->dar
= sv
->save_dar
;
638 xes
->dsisr
= sv
->save_dsisr
;
639 xes
->exception
= sv
->save_exception
;
641 else { /* Nope, not yet */
644 xes
->exception
= ((unsigned int *)&FloatInit
)[0];
647 *count
= PPC_EXCEPTION_STATE64_COUNT
;
651 return KERN_INVALID_ARGUMENT
;
659 * Set the status of the specified thread.
662 machine_thread_set_state(
664 thread_flavor_t flavor
,
665 thread_state_t tstate
,
666 mach_msg_type_number_t count
)
669 struct savearea
*genuser
;
670 savearea_fpu
*fsv
, *fsvn
, *fsvo
;
671 savearea_vec
*vsv
, *vsvn
, *vsvo
;
674 register struct ppc_thread_state
*ts
;
675 register struct ppc_thread_state64
*xts
;
676 register struct ppc_exception_state
*es
;
677 register struct ppc_exception_state
*xes
;
678 register struct ppc_float_state
*fs
;
679 register struct ppc_vector_state
*vs
;
681 // dbgTrace((unsigned int)thr_act, (unsigned int)0 /*sv: was never set*/, flavor); /* (TEST/DEBUG) */
683 clgn
= count
; /* Get the count */
685 switch (flavor
) { /* Validate the count before we do anything else */
686 case PPC_THREAD_STATE
:
688 if (clgn
< PPC_THREAD_STATE_COUNT
) { /* Is it too short? */
689 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
693 case PPC_THREAD_STATE64
:
695 if (clgn
< PPC_THREAD_STATE64_COUNT
) { /* Is it too short? */
696 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
700 case PPC_EXCEPTION_STATE
:
702 if (clgn
< PPC_EXCEPTION_STATE_COUNT
) { /* Is it too short? */
703 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
706 case PPC_EXCEPTION_STATE64
:
708 if (clgn
< PPC_EXCEPTION_STATE64_COUNT
) { /* Is it too short? */
709 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
714 case PPC_FLOAT_STATE
:
716 if (clgn
< PPC_FLOAT_STATE_COUNT
) { /* Is it too short? */
717 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
723 case PPC_VECTOR_STATE
:
725 if (clgn
< PPC_VECTOR_STATE_COUNT
) { /* Is it too short? */
726 return KERN_INVALID_ARGUMENT
; /* Yeah, just leave... */
732 return KERN_INVALID_ARGUMENT
;
735 genuser
= get_user_regs(thread
); /* Find or allocate and initialize one */
739 case PPC_THREAD_STATE
:
741 ts
= (struct ppc_thread_state
*)tstate
;
743 genuser
->save_r0
= (uint64_t)ts
->r0
;
744 genuser
->save_r1
= (uint64_t)ts
->r1
;
745 genuser
->save_r2
= (uint64_t)ts
->r2
;
746 genuser
->save_r3
= (uint64_t)ts
->r3
;
747 genuser
->save_r4
= (uint64_t)ts
->r4
;
748 genuser
->save_r5
= (uint64_t)ts
->r5
;
749 genuser
->save_r6
= (uint64_t)ts
->r6
;
750 genuser
->save_r7
= (uint64_t)ts
->r7
;
751 genuser
->save_r8
= (uint64_t)ts
->r8
;
752 genuser
->save_r9
= (uint64_t)ts
->r9
;
753 genuser
->save_r10
= (uint64_t)ts
->r10
;
754 genuser
->save_r11
= (uint64_t)ts
->r11
;
755 genuser
->save_r12
= (uint64_t)ts
->r12
;
756 genuser
->save_r13
= (uint64_t)ts
->r13
;
757 genuser
->save_r14
= (uint64_t)ts
->r14
;
758 genuser
->save_r15
= (uint64_t)ts
->r15
;
759 genuser
->save_r16
= (uint64_t)ts
->r16
;
760 genuser
->save_r17
= (uint64_t)ts
->r17
;
761 genuser
->save_r18
= (uint64_t)ts
->r18
;
762 genuser
->save_r19
= (uint64_t)ts
->r19
;
763 genuser
->save_r20
= (uint64_t)ts
->r20
;
764 genuser
->save_r21
= (uint64_t)ts
->r21
;
765 genuser
->save_r22
= (uint64_t)ts
->r22
;
766 genuser
->save_r23
= (uint64_t)ts
->r23
;
767 genuser
->save_r24
= (uint64_t)ts
->r24
;
768 genuser
->save_r25
= (uint64_t)ts
->r25
;
769 genuser
->save_r26
= (uint64_t)ts
->r26
;
770 genuser
->save_r27
= (uint64_t)ts
->r27
;
771 genuser
->save_r28
= (uint64_t)ts
->r28
;
772 genuser
->save_r29
= (uint64_t)ts
->r29
;
773 genuser
->save_r30
= (uint64_t)ts
->r30
;
774 genuser
->save_r31
= (uint64_t)ts
->r31
;
776 genuser
->save_cr
= ts
->cr
;
777 genuser
->save_xer
= (uint64_t)ts
->xer
;
778 genuser
->save_lr
= (uint64_t)ts
->lr
;
779 genuser
->save_ctr
= (uint64_t)ts
->ctr
;
780 genuser
->save_srr0
= (uint64_t)ts
->srr0
;
781 genuser
->save_vrsave
= ts
->vrsave
; /* VRSAVE register (Altivec only) */
783 genuser
->save_srr1
= MSR_PREPARE_FOR_IMPORT(genuser
->save_srr1
, ts
->srr1
); /* Set the bits we can change */
785 genuser
->save_srr1
|= MSR_EXPORT_MASK_SET
;
787 genuser
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make sure we don't enable the floating point unit */
789 if(task_has_64BitAddr(thread
->task
))
790 genuser
->save_srr1
|= (uint64_t)MASK32(MSR_SF
) << 32; /* If 64-bit task, force 64-bit mode */
792 genuser
->save_srr1
&= ~((uint64_t)MASK32(MSR_SF
) << 32); /* else 32-bit mode */
797 case PPC_THREAD_STATE64
:
799 xts
= (struct ppc_thread_state64
*)tstate
;
801 genuser
->save_r0
= xts
->r0
;
802 genuser
->save_r1
= xts
->r1
;
803 genuser
->save_r2
= xts
->r2
;
804 genuser
->save_r3
= xts
->r3
;
805 genuser
->save_r4
= xts
->r4
;
806 genuser
->save_r5
= xts
->r5
;
807 genuser
->save_r6
= xts
->r6
;
808 genuser
->save_r7
= xts
->r7
;
809 genuser
->save_r8
= xts
->r8
;
810 genuser
->save_r9
= xts
->r9
;
811 genuser
->save_r10
= xts
->r10
;
812 genuser
->save_r11
= xts
->r11
;
813 genuser
->save_r12
= xts
->r12
;
814 genuser
->save_r13
= xts
->r13
;
815 genuser
->save_r14
= xts
->r14
;
816 genuser
->save_r15
= xts
->r15
;
817 genuser
->save_r16
= xts
->r16
;
818 genuser
->save_r17
= xts
->r17
;
819 genuser
->save_r18
= xts
->r18
;
820 genuser
->save_r19
= xts
->r19
;
821 genuser
->save_r20
= xts
->r20
;
822 genuser
->save_r21
= xts
->r21
;
823 genuser
->save_r22
= xts
->r22
;
824 genuser
->save_r23
= xts
->r23
;
825 genuser
->save_r24
= xts
->r24
;
826 genuser
->save_r25
= xts
->r25
;
827 genuser
->save_r26
= xts
->r26
;
828 genuser
->save_r27
= xts
->r27
;
829 genuser
->save_r28
= xts
->r28
;
830 genuser
->save_r29
= xts
->r29
;
831 genuser
->save_r30
= xts
->r30
;
832 genuser
->save_r31
= xts
->r31
;
834 genuser
->save_cr
= xts
->cr
;
835 genuser
->save_xer
= xts
->xer
;
836 genuser
->save_lr
= xts
->lr
;
837 genuser
->save_ctr
= xts
->ctr
;
838 genuser
->save_srr0
= xts
->srr0
;
839 genuser
->save_vrsave
= xts
->vrsave
; /* VRSAVE register (Altivec only) */
841 genuser
->save_srr1
= MSR_PREPARE_FOR_IMPORT(genuser
->save_srr1
, xts
->srr1
); /* Set the bits we can change */
843 genuser
->save_srr1
|= MSR_EXPORT_MASK_SET
;
845 genuser
->save_srr1
&= ~(MASK(MSR_FP
) | MASK(MSR_VEC
)); /* Make sure we don't enable the floating point unit */
847 if(task_has_64BitAddr(thread
->task
))
848 genuser
->save_srr1
|= (uint64_t)MASK32(MSR_SF
) << 32; /* If 64-bit task, force 64-bit mode */
850 genuser
->save_srr1
&= ~((uint64_t)MASK32(MSR_SF
) << 32); /* else 32-bit mode */
855 case PPC_EXCEPTION_STATE
:
857 es
= (struct ppc_exception_state
*) tstate
;
859 genuser
->save_dar
= (uint64_t)es
->dar
;
860 genuser
->save_dsisr
= es
->dsisr
;
861 genuser
->save_exception
= es
->exception
;
866 * It's pretty worthless to try to change this stuff, but we'll do it anyway.
869 case PPC_EXCEPTION_STATE64
:
871 xes
= (struct ppc_exception_state
*) tstate
;
873 genuser
->save_dar
= xes
->dar
;
874 genuser
->save_dsisr
= xes
->dsisr
;
875 genuser
->save_exception
= xes
->exception
;
879 case PPC_FLOAT_STATE
:
881 toss_live_fpu(thread
->machine
.curctx
); /* Toss my floating point if live anywhere */
883 fsv
= find_user_fpu(thread
); /* Get the user's floating point context */
885 if(!fsv
) { /* Do we have one yet? */
886 fsv
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
887 fsv
->save_hdr
.save_flags
= (fsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
888 fsv
->save_hdr
.save_act
= thread
;
889 fsv
->save_hdr
.save_prev
= 0; /* Mark no more */
890 fsv
->save_hdr
.save_level
= 0; /* Mark user state */
892 if(!thread
->machine
.curctx
->FPUsave
) thread
->machine
.curctx
->FPUsave
= fsv
; /* If no floating point, chain us first */
895 fsvn
= fsvo
= thread
->machine
.curctx
->FPUsave
; /* Remember first one */
897 while (fsvn
) { /* Go until we hit the end */
898 fsvo
= fsvn
; /* Remember the previous one */
899 fsvn
= CAST_DOWN(savearea_fpu
*, fsvo
->save_hdr
.save_prev
); /* Skip on to the next */
902 fsvo
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)fsv
); /* Queue us on in */
907 fs
= (struct ppc_float_state
*) tstate
; /* Point to source */
910 bcopy((char *)fs
, (char *)&fsv
->save_fp0
, 32*8); /* Move in the 32 registers */
912 genuser
->save_fpscr
= fs
->fpscr
; /* Copy the fpscr value to normal */
917 case PPC_VECTOR_STATE
:
919 toss_live_vec(thread
->machine
.curctx
); /* Toss my vector if live anywhere */
921 vsv
= find_user_vec(thread
); /* Get the user's vector context */
923 if(!vsv
) { /* Do we have one yet? */
924 vsv
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
925 vsv
->save_hdr
.save_flags
= (vsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as vector */
926 vsv
->save_hdr
.save_act
= thread
;
927 vsv
->save_hdr
.save_prev
= 0; /* Mark no more */
928 vsv
->save_hdr
.save_level
= 0; /* Mark user state */
930 if(!thread
->machine
.curctx
->VMXsave
) thread
->machine
.curctx
->VMXsave
= vsv
; /* If no vector, chain us first */
933 vsvn
= vsvo
= thread
->machine
.curctx
->VMXsave
; /* Remember first one */
935 while (vsvn
) { /* Go until we hit the end */
936 vsvo
= vsvn
; /* Remember the previous one */
937 vsvn
= CAST_DOWN(savearea_vec
*, vsvo
->save_hdr
.save_prev
); /* Skip on to the next */
940 vsvo
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)vsv
); /* Queue us on in */
945 vs
= (struct ppc_vector_state
*) tstate
; /* Point to source */
947 bcopy((char *)vs
, (char *)&vsv
->save_vr0
, 32*16); /* 32 registers plus status and validity and pad */
948 vsv
->save_vrvalid
= vs
->save_vrvalid
; /* Set validity bits */
951 for(i
= 0; i
< 4; i
++) genuser
->save_vscr
[i
] = vs
->save_vscr
[i
]; /* Set value for vscr */
957 return KERN_INVALID_ARGUMENT
;
963 thread_set_wq_state64(thread_t thread
, thread_state_t tstate
)
965 struct ppc_thread_state64
*ts
;
966 struct savearea
*genuser
;
967 thread_t curth
= current_thread();
969 genuser
= get_user_regs(thread
); /* Find or allocate and initialize one */
970 ts
= (struct ppc_thread_state64
*)tstate
;
975 genuser
->save_r1
= ts
->r1
;
976 genuser
->save_r3
= ts
->r3
;
977 genuser
->save_r4
= ts
->r4
;
978 genuser
->save_r5
= ts
->r5
;
979 genuser
->save_r6
= ts
->r6
;
980 genuser
->save_r7
= ts
->r7
;
981 genuser
->save_r8
= ts
->r8
;
982 genuser
->save_srr0
= ts
->srr0
;
984 genuser
->save_srr1
= (uint64_t)MSR_EXPORT_MASK_SET
;
986 if (task_has_64BitAddr(thread
->task
))
987 genuser
->save_srr1
|= (uint64_t)MASK32(MSR_SF
) << 32; /* If 64-bit task, force 64-bit mode */
990 thread_unlock(thread
);
995 * This is where registers that are not normally specified by the mach-o
996 * file on an execve should be nullified, perhaps to avoid a covert channel.
997 * We've never bothered to clear FPRs or VRs, but it is important to clear
998 * the FPSCR, which is kept in the general state but not set by the general
999 * flavor (ie, PPC_THREAD_STATE or PPC_THREAD_STATE64.)
1002 machine_thread_state_initialize(
1005 struct savearea
*sv
;
1007 sv
= get_user_regs(thread
); /* Find or allocate and initialize one */
1009 sv
->save_fpscr
= 0; /* Clear all floating point exceptions */
1010 sv
->save_vrsave
= 0; /* Set the vector save state */
1011 sv
->save_vscr
[0] = 0x00000000;
1012 sv
->save_vscr
[1] = 0x00000000;
1013 sv
->save_vscr
[2] = 0x00000000;
1014 sv
->save_vscr
[3] = 0x00010000; /* Disable java mode and clear saturated */
1016 return KERN_SUCCESS
;
1021 * Duplicates the context of one thread into a new one.
1022 * The new thread is assumed to be new and have no user state contexts except maybe a general one.
1023 * We also assume that the old thread can't be running anywhere.
1025 * We're only going to be duplicating user context here. That means that we will have to
1026 * eliminate any floating point or vector kernel contexts and carry across the user state ones.
1034 struct savearea
*sv
, *osv
;
1035 savearea_fpu
*fsv
, *fsvn
;
1036 savearea_vec
*vsv
, *vsvn
;
1038 fpu_save(self
->machine
.curctx
); /* Make certain floating point state is all saved */
1039 vec_save(self
->machine
.curctx
); /* Make certain the vector state is all saved */
1041 sv
= get_user_regs(target
); /* Allocate and initialze context in the new activation */
1043 osv
= find_user_regs(self
); /* Find the original context */
1045 return (KERN_FAILURE
);
1047 bcopy((char *)((unsigned int)osv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1048 (char *)((unsigned int)sv
+ sizeof(savearea_comm
)),
1049 sizeof(struct savearea
) - sizeof(savearea_comm
));
1051 sv
->save_srr1
&= (uint64_t)(~(MASK(MSR_FP
) | MASK(MSR_VEC
))); /* Make certain that floating point and vector are turned off */
1053 fsv
= find_user_fpu(self
); /* Get any user floating point */
1055 target
->machine
.curctx
->FPUsave
= NULL
; /* Assume no floating point */
1057 if(fsv
) { /* Did we find one? */
1058 fsvn
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
1059 fsvn
->save_hdr
.save_flags
= (fsvn
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
1060 fsvn
->save_hdr
.save_act
= target
;
1061 fsvn
->save_hdr
.save_prev
= 0; /* Mark no more */
1062 fsvn
->save_hdr
.save_level
= 0; /* Mark user state */
1064 target
->machine
.curctx
->FPUsave
= fsvn
; /* Chain in the floating point */
1066 bcopy((char *)((unsigned int)fsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1067 (char *)((unsigned int)fsvn
+ sizeof(savearea_comm
)),
1068 sizeof(struct savearea
) - sizeof(savearea_comm
));
1071 vsv
= find_user_vec(self
); /* Get any user vector */
1073 target
->machine
.curctx
->VMXsave
= NULL
; /* Assume no vector */
1075 if(vsv
) { /* Did we find one? */
1076 vsvn
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
1077 vsvn
->save_hdr
.save_flags
= (vsvn
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as float */
1078 vsvn
->save_hdr
.save_act
= target
;
1079 vsvn
->save_hdr
.save_prev
= 0; /* Mark no more */
1080 vsvn
->save_hdr
.save_level
= 0; /* Mark user state */
1082 target
->machine
.curctx
->VMXsave
= vsvn
; /* Chain in the floating point */
1084 bcopy((char *)((unsigned int)vsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1085 (char *)((unsigned int)vsvn
+ sizeof(savearea_comm
)),
1086 sizeof(struct savearea
) - sizeof(savearea_comm
));
1089 return (KERN_SUCCESS
);
1093 * Initializes a fresh set of user state values. If there is no user state context,
1094 * one is created. Floats and VMX are not created.
1096 * We only set initial values if there was no context found.
1103 struct savearea
*sv
, *osv
;
1106 if (thread
->machine
.upcb
)
1107 return thread
->machine
.upcb
;
1109 sv
= thread
->machine
.pcb
; /* Get the top savearea on the stack */
1110 osv
= NULL
; /* Set no user savearea yet */
1112 while(sv
) { /* Find the user context */
1113 osv
= sv
; /* Save the last one */
1114 sv
= CAST_DOWN(struct savearea
*, sv
->save_hdr
.save_prev
); /* Get the previous context */
1117 sv
= save_alloc(); /* Get one */
1118 sv
->save_hdr
.save_flags
= (sv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVgeneral
<< SAVtypeshft
); /* Mark as in use as general */
1119 sv
->save_hdr
.save_act
= thread
;
1120 sv
->save_hdr
.save_prev
= 0; /* Mark no more */
1121 sv
->save_hdr
.save_level
= 0; /* Mark user state */
1123 if(osv
) { /* Did we already have one? */
1124 osv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)sv
); /* Chain us on the end */
1126 else { /* We are the first */
1127 thread
->machine
.pcb
= sv
; /* Put it there */
1129 thread
->machine
.upcb
= sv
; /* Set user pcb */
1131 for(i
=0; i
< 32; i
+=2) { /* Fill up with defaults */
1132 ((unsigned int *)&sv
->save_r0
)[i
] = ((unsigned int *)&FloatInit
)[0];
1133 ((unsigned int *)&sv
->save_r0
)[i
+1] = ((unsigned int *)&FloatInit
)[1];
1137 sv
->save_lr
= (uint64_t)FloatInit
;
1138 sv
->save_ctr
= (uint64_t)FloatInit
;
1139 sv
->save_srr0
= (uint64_t)FloatInit
;
1140 sv
->save_srr1
= (uint64_t)MSR_EXPORT_MASK_SET
;
1141 if(task_has_64BitAddr(thread
->task
))
1142 sv
->save_srr1
|= (uint64_t)MASK32(MSR_SF
) << 32; /* If 64-bit task, force 64-bit mode */
1144 sv
->save_fpscr
= 0; /* Clear all floating point exceptions */
1146 sv
->save_vrsave
= 0; /* Set the vector save state */
1147 sv
->save_vscr
[0] = 0x00000000;
1148 sv
->save_vscr
[1] = 0x00000000;
1149 sv
->save_vscr
[2] = 0x00000000;
1150 sv
->save_vscr
[3] = 0x00010000; /* Disable java mode and clear saturated */
1152 return sv
; /* Bye bye... */
1156 * Find the user state context. If there is no user state context,
1157 * we just return a 0.
1164 return thread
->machine
.upcb
;
1167 /* The name of this call is something of a misnomer since the mact.pcb can
1168 * contain chained saveareas, but it will do for now..
1174 return thread
->machine
.pcb
;
1178 * Find the user state floating point context. If there is no user state context,
1179 * we just return a 0.
1189 intr
= ml_set_interrupts_enabled(FALSE
);
1190 fsv
= thread
->machine
.curctx
->FPUsave
; /* Get the start of the floating point chain */
1192 while(fsv
) { /* Look until the end or we find it */
1193 if(!(fsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
1194 fsv
= CAST_DOWN(savearea_fpu
*, fsv
->save_hdr
.save_prev
); /* Try the previous one */
1196 (void) ml_set_interrupts_enabled(intr
);
1198 return fsv
; /* Bye bye... */
1202 * Find the user state vector context. If there is no user state context,
1203 * we just return a 0.
1213 intr
= ml_set_interrupts_enabled(FALSE
);
1214 vsv
= thread
->machine
.curctx
->VMXsave
; /* Get the start of the vector chain */
1216 while(vsv
) { /* Look until the end or we find it */
1217 if(!(vsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
1218 vsv
= CAST_DOWN(savearea_vec
*, vsv
->save_hdr
.save_prev
); /* Try the previous one */
1220 (void) ml_set_interrupts_enabled(intr
);
1222 return vsv
; /* Bye bye... */
1225 * Find the user state vector context for the current thread. If there is no user state context,
1226 * we just return a 0.
1229 savearea_vec
*find_user_vec_curr(void) {
1232 thread_t thread
= current_thread();
1235 vec_save(thread
->machine
.curctx
); /* Force save if live */
1237 intr
= ml_set_interrupts_enabled(FALSE
);
1238 vsv
= thread
->machine
.curctx
->VMXsave
; /* Get the start of the vector chain */
1240 while(vsv
) { /* Look until the end or we find it */
1241 if(!(vsv
->save_hdr
.save_level
)) break; /* Is the the user state stuff? (the level is 0 if so) */
1242 vsv
= CAST_DOWN(savearea_vec
*, vsv
->save_hdr
.save_prev
); /* Try the previous one */
1244 (void) ml_set_interrupts_enabled(intr
);
1246 return vsv
; /* Bye bye... */
1252 * Return the user stack pointer from the machine
1253 * dependent thread state info.
1257 __unused thread_t thread
,
1259 thread_state_t tstate
,
1261 mach_vm_offset_t
*user_stack
,
1270 case PPC_THREAD_STATE
:
1272 struct ppc_thread_state
*state
;
1274 if (count
< PPC_THREAD_STATE_COUNT
)
1275 return (KERN_INVALID_ARGUMENT
);
1277 state
= (struct ppc_thread_state
*) tstate
;
1280 * If a valid user stack is specified, use it.
1283 *user_stack
= CAST_USER_ADDR_T(state
->r1
);
1287 *user_stack
= CAST_USER_ADDR_T(USRSTACK
);
1294 case PPC_THREAD_STATE64
:
1296 struct ppc_thread_state64
*state64
;
1298 if (count
< PPC_THREAD_STATE64_COUNT
)
1299 return (KERN_INVALID_ARGUMENT
);
1301 state64
= (struct ppc_thread_state64
*)tstate
;
1304 * If a valid user stack is specified, use it.
1306 if (state64
->r1
!= MACH_VM_MIN_ADDRESS
) {
1307 *user_stack
= state64
->r1
;
1311 *user_stack
= USRSTACK64
;
1319 return (KERN_INVALID_ARGUMENT
);
1322 return (KERN_SUCCESS
);
1327 * thread_setuserstack:
1329 * Sets the user stack pointer into the machine
1330 * dependent thread state info.
1333 thread_setuserstack(thread_t thread
, mach_vm_address_t user_stack
)
1335 struct savearea
*sv
;
1337 sv
= get_user_regs(thread
); /* Get the user state registers */
1339 sv
->save_r1
= user_stack
;
1345 thread_set_cthreadself(thread_t thread
, uint64_t pself
, int isLP64
)
1347 struct savearea
*sv
;
1350 thread
->machine
.cthread_self
= pself
;
1352 sv
= get_user_regs(thread
); /* Get the user state registers */
1354 thread
->machine
.cthread_self
= pself
;
1355 sv
->save_r13
= pself
;
1361 * thread_adjuserstack:
1363 * Returns the adjusted user stack pointer from the machine
1364 * dependent thread state info. Usef for small (<2G) deltas.
1367 thread_adjuserstack(thread_t thread
, int adjust
)
1369 struct savearea
*sv
;
1371 sv
= get_user_regs(thread
); /* Get the user state registers */
1373 sv
->save_r1
+= adjust
; /* Adjust the stack */
1375 return sv
->save_r1
; /* Return the adjusted stack */
1380 thread_setsinglestep(thread_t thread
, int on
)
1382 struct savearea
*sv
;
1384 sv
= get_user_regs(thread
); /* Get the user state registers */
1387 sv
->save_srr1
|= MASK(MSR_SE
);
1389 sv
->save_srr1
&= ~MASK(MSR_SE
);
1391 return (KERN_SUCCESS
);
1395 * thread_setentrypoint:
1397 * Sets the user PC into the machine
1398 * dependent thread state info.
1402 thread_setentrypoint(thread_t thread
, uint64_t entry
)
1404 struct savearea
*sv
;
1406 sv
= get_user_regs(thread
); /* Get the user state registers */
1408 sv
->save_srr0
= entry
;
1413 __unused thread_t thread
,
1415 thread_state_t tstate
,
1417 mach_vm_offset_t
*entry_point
1421 /* Silly code: "if *entry_point is 0, make it 0" */
1425 if (*entry_point
== 0ULL)
1426 *entry_point
= MACH_VM_MIN_ADDRESS
;
1430 case PPC_THREAD_STATE
:
1432 struct ppc_thread_state
*state
;
1434 if (count
< PPC_THREAD_STATE_COUNT
)
1435 return (KERN_INVALID_ARGUMENT
);
1437 state
= (struct ppc_thread_state
*) tstate
;
1440 * If a valid entry point is specified, use it.
1443 *entry_point
= CAST_USER_ADDR_T(state
->srr0
);
1445 *entry_point
= CAST_USER_ADDR_T(VM_MIN_ADDRESS
);
1450 case PPC_THREAD_STATE64
:
1452 struct ppc_thread_state64
*state64
;
1454 if (count
< PPC_THREAD_STATE_COUNT
)
1455 return (KERN_INVALID_ARGUMENT
);
1457 state64
= (struct ppc_thread_state64
*)tstate
;
1460 * If a valid entry point is specified, use it.
1462 if (state64
->srr0
) {
1463 *entry_point
= state64
->srr0
;
1465 *entry_point
= MACH_VM_MIN_ADDRESS
;
1471 return (KERN_INVALID_ARGUMENT
);
1474 return (KERN_SUCCESS
);
1477 unsigned int get_msr_exportmask(void)
1479 return (MSR_EXPORT_MASK_SET
);
1482 unsigned int get_msr_nbits(void)
1484 return (MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1486 unsigned int get_msr_rbits(void)
1488 return (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1491 void ppc_checkthreadstate(void * tsptr
, int flavor
)
1493 if (flavor
== PPC_THREAD_STATE64
) {
1494 struct ppc_thread_state64
*ts64
=(struct ppc_thread_state64
*)tsptr
;
1496 /* Make sure naughty bits are off and necessary bits are on */
1497 ts64
->srr1
&= ~(MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1498 ts64
->srr1
|= (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1500 struct ppc_thread_state
*ts
=(struct ppc_thread_state
*)tsptr
;
1502 /* Make sure naughty bits are off and necessary bits are on */
1503 ts
->srr1
&= ~(MASK(MSR_POW
)|MASK(MSR_ILE
)|MASK(MSR_IP
)|MASK(MSR_LE
));
1504 ts
->srr1
|= (MASK(MSR_PR
)|MASK(MSR_ME
)|MASK(MSR_IR
)|MASK(MSR_DR
)|MASK(MSR_EE
));
1514 struct savearea
*child_state
;
1516 child_state
= get_user_regs(child
);
1518 child_state
->save_r3
= (uint_t
)pid
;
1519 child_state
->save_r4
= 1ULL;
1526 struct savearea
*parent_state
;
1528 parent_state
= get_user_regs(parent
);
1530 parent_state
->save_r3
= (uint64_t)pid
;
1531 parent_state
->save_r4
= 0;
1535 * Saves the complete context (general, floating point, and vector) of the current activation.
1536 * We will collect everything into an opaque block of 1 to 3 saveareas and pass back a
1539 * The savearea is made to look like it belongs to the source activation. This needs to
1540 * be adjusted when these contexts are attached to a new activation.
1544 void *act_thread_csave(void) {
1546 struct savearea
*sv
, *osv
;
1547 savearea_fpu
*fsv
, *ofsv
;
1548 savearea_vec
*vsv
, *ovsv
;
1552 thread
= current_thread();
1554 fpu_save(thread
->machine
.curctx
); /* Make certain floating point state is all saved */
1555 vec_save(thread
->machine
.curctx
); /* Make certain the vector state is all saved */
1557 osv
= find_user_regs(thread
); /* Get our savearea */
1560 panic("act_thread_csave: attempting to preserve the context of an activation with none (%p)\n", thread
);
1563 sv
= save_alloc(); /* Get a fresh save area to save into */
1564 sv
->save_hdr
.save_flags
= (sv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVgeneral
<< SAVtypeshft
); /* Mark as in use as general */
1565 sv
->save_hdr
.save_act
= thread
;
1566 sv
->save_hdr
.save_prev
= 0; /* Mark no more */
1567 sv
->save_hdr
.save_level
= 0; /* Mark user state */
1570 bcopy((char *)((unsigned int)osv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1571 (char *)((unsigned int)sv
+ sizeof(savearea_comm
)),
1572 sizeof(struct savearea
) - sizeof(savearea_comm
));
1574 sv
->save_srr1
&= (uint64_t)(~(MASK(MSR_FP
) | MASK(MSR_VEC
))); /* Make certain that floating point and vector are turned off */
1576 sv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1577 sv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1580 ofsv
= find_user_fpu(thread
); /* Get any user floating point */
1582 sv
->save_hdr
.save_misc0
= 0; /* Assume no floating point */
1584 if(ofsv
) { /* Did we find one? */
1585 fsv
= (savearea_fpu
*)save_alloc(); /* If we still don't have one, get a new one */
1586 fsv
->save_hdr
.save_flags
= (fsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVfloat
<< SAVtypeshft
); /* Mark as in use as float */
1587 fsv
->save_hdr
.save_act
= thread
;
1588 fsv
->save_hdr
.save_prev
= 0; /* Mark no more */
1589 fsv
->save_hdr
.save_level
= 0; /* Mark user state */
1590 fsv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1591 fsv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1593 sv
->save_hdr
.save_misc0
= (uint64_t)((uintptr_t)fsv
); /* Remember this one */
1595 bcopy((char *)((unsigned int)ofsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1596 (char *)((unsigned int)fsv
+ sizeof(savearea_comm
)),
1597 sizeof(struct savearea
) - sizeof(savearea_comm
));
1600 ovsv
= find_user_vec(thread
); /* Get any user vector */
1602 sv
->save_hdr
.save_misc1
= 0; /* Assume no vector */
1604 if(ovsv
) { /* Did we find one? */
1605 vsv
= (savearea_vec
*)save_alloc(); /* If we still don't have one, get a new one */
1606 vsv
->save_hdr
.save_flags
= (vsv
->save_hdr
.save_flags
& ~SAVtype
) | (SAVvector
<< SAVtypeshft
); /* Mark as in use as float */
1607 vsv
->save_hdr
.save_act
= thread
;
1608 vsv
->save_hdr
.save_prev
= 0; /* Mark no more */
1609 vsv
->save_hdr
.save_level
= 0; /* Mark user state */
1610 vsv
->save_hdr
.save_misc2
= 0xDEBB1ED0; /* Eye catcher for debug */
1611 vsv
->save_hdr
.save_misc3
= 0xE5DA11A5; /* Eye catcher for debug */
1613 sv
->save_hdr
.save_misc1
= (uint64_t)((uintptr_t)vsv
); /* Chain in the floating point */
1615 bcopy((char *)((unsigned int)ovsv
+ sizeof(savearea_comm
)), /* Copy everything but the headers */
1616 (char *)((unsigned int)vsv
+ sizeof(savearea_comm
)),
1617 sizeof(struct savearea
) - sizeof(savearea_comm
));
1620 return (void *)sv
; /* Bye bye... */
1626 * Attaches saved user state context to an activation. We will replace any
1627 * user state context with what is passed in. The saved context consists of a
1628 * savearea that was setup by
1629 * We will collect everything into one savearea and pass that back.
1631 * The savearea is made to look like it belongs to the source activation. This needs to
1632 * be adjusted when these contexts are attached to a new activation.
1636 void act_thread_catt(void *ctx
) {
1638 struct savearea
*sv
, *osv
, *psv
;
1639 savearea_fpu
*fsv
, *ofsv
, *pfsv
;
1640 savearea_vec
*vsv
, *ovsv
, *pvsv
;
1644 sv
= (struct savearea
*)ctx
; /* Make this easier for C */
1646 fsv
= CAST_DOWN(savearea_fpu
*, sv
->save_hdr
.save_misc0
); /* Get a possible floating point savearea */
1647 vsv
= CAST_DOWN(savearea_vec
*, sv
->save_hdr
.save_misc1
); /* Get a possible vector savearea */
1649 if((sv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (sv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1650 panic("act_thread_catt: attempt to attach invalid general context savearea - %p\n", sv
); /* Die */
1653 if(fsv
&& ((fsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (fsv
->save_hdr
.save_misc3
!= 0xE5DA11A5))) { /* See if valid savearea */
1654 panic("act_thread_catt: attempt to attach invalid float context savearea - %p\n", fsv
); /* Die */
1657 if(vsv
&& ((vsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (vsv
->save_hdr
.save_misc3
!= 0xE5DA11A5))) { /* See if valid savearea */
1658 panic("act_thread_catt: attempt to attach invalid vector context savearea - %p\n", vsv
); /* Die */
1661 thread
= current_thread();
1663 act_machine_sv_free(thread
, 0); /* Blow away any current kernel FP or vector.
1664 We do not support those across a vfork */
1665 toss_live_fpu(thread
->machine
.curctx
); /* Toss my floating point if live anywhere */
1666 toss_live_vec(thread
->machine
.curctx
); /* Toss my vector if live anywhere */
1668 sv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1669 sv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1670 sv
->save_hdr
.save_act
= thread
;
1672 spc
= (unsigned int)thread
->map
->pmap
->space
; /* Get the space we're in */
1674 osv
= thread
->machine
.pcb
; /* Get the top general savearea */
1676 while(osv
) { /* Any saved state? */
1677 if(osv
->save_srr1
& MASK(MSR_PR
)) break; /* Leave if this is user state */
1678 psv
= osv
; /* Save previous savearea address */
1679 osv
= CAST_DOWN(struct savearea
*, osv
->save_hdr
.save_prev
); /* Get one underneath our's */
1682 if(osv
) { /* Did we find one? */
1683 if(psv
) psv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1684 else thread
->machine
.pcb
= NULL
; /* to the start if the only one */
1686 save_release(osv
); /* Nope, release it */
1690 if(psv
) psv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)sv
); /* Chain us to the end or */
1691 else thread
->machine
.pcb
= (pcb_t
)sv
; /* to the start if the only one */
1692 thread
->machine
.upcb
= (pcb_t
)sv
; /* Set the user pcb */
1694 ovsv
= thread
->machine
.curctx
->VMXsave
; /* Get the top vector savearea */
1697 while(ovsv
) { /* Any VMX saved state? */
1698 if(!(ovsv
->save_hdr
.save_level
)) break; /* Leave if this is user state */
1699 pvsv
= ovsv
; /* Save previous savearea address */
1700 ovsv
= CAST_DOWN(savearea_vec
*, ovsv
->save_hdr
.save_prev
); /* Get one underneath our's */
1703 if(ovsv
) { /* Did we find one? */
1704 if(pvsv
) pvsv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1705 else thread
->machine
.curctx
->VMXsave
= NULL
; /* to the start if the only one */
1707 save_release((struct savearea
*)ovsv
); /* Nope, release it */
1710 if(vsv
) { /* Are we sticking any vector on this one? */
1711 if(pvsv
) pvsv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)vsv
); /* Yes, chain us to the end or */
1713 thread
->machine
.curctx
->VMXsave
= vsv
; /* to the start if the only one */
1714 thread
->machine
.curctx
->VMXlevel
= NULL
; /* Insure that we don't have a leftover level */
1717 vsv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1718 vsv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1719 vsv
->save_hdr
.save_act
= thread
;
1722 ofsv
= thread
->machine
.curctx
->FPUsave
; /* Get the top float savearea */
1725 while(ofsv
) { /* Any float saved state? */
1726 if(!(ofsv
->save_hdr
.save_level
)) break; /* Leave if this is user state */
1727 pfsv
= ofsv
; /* Save previous savearea address */
1728 ofsv
= CAST_DOWN(savearea_fpu
*, ofsv
->save_hdr
.save_prev
); /* Get one underneath our's */
1731 if(ofsv
) { /* Did we find one? */
1732 if(pfsv
) pfsv
->save_hdr
.save_prev
= 0; /* Yes, clear pointer to it (it should always be last) or */
1733 else thread
->machine
.curctx
->FPUsave
= NULL
; /* to the start if the only one */
1735 save_release((struct savearea
*)ofsv
); /* Nope, release it */
1738 if(fsv
) { /* Are we sticking any vector on this one? */
1739 if(pfsv
) pfsv
->save_hdr
.save_prev
= (addr64_t
)((uintptr_t)fsv
); /* Yes, chain us to the end or */
1741 thread
->machine
.curctx
->FPUsave
= fsv
; /* to the start if the only one */
1742 thread
->machine
.curctx
->FPUlevel
= NULL
; /* Insure that we don't have a leftover level */
1745 fsv
->save_hdr
.save_misc2
= 0; /* Eye catcher for debug */
1746 fsv
->save_hdr
.save_misc3
= 0; /* Eye catcher for debug */
1747 fsv
->save_hdr
.save_act
= thread
;
1755 * Releases saved context. We need this because the saved context is opague.
1756 * be adjusted when these contexts are attached to a new activation.
1761 act_thread_cfree(void *ctx
)
1764 struct savearea
*sv
;
1768 sv
= (struct savearea
*)ctx
; /* Make this easier for C */
1770 fsv
= CAST_DOWN(savearea_fpu
*, sv
->save_hdr
.save_misc0
); /* Get a possible floating point savearea */
1771 vsv
= CAST_DOWN(savearea_vec
*, sv
->save_hdr
.save_misc1
); /* Get a possible vector savearea */
1773 if((sv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (sv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1774 panic("act_thread_cfree: attempt to detatch invalid general context savearea - %p\n", sv
); /* Die */
1777 save_release(sv
); /* Toss the general savearea */
1779 if(fsv
) { /* See if there is any saved floating point */
1780 if((fsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (fsv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1781 panic("act_thread_cfree: attempt to detatch invalid float context savearea - %p\n", fsv
); /* Die */
1784 save_release((struct savearea
*)fsv
); /* Toss saved context */
1787 if(vsv
) { /* See if there is any saved floating point */
1788 if((vsv
->save_hdr
.save_misc2
!= 0xDEBB1ED0) || (vsv
->save_hdr
.save_misc3
!= 0xE5DA11A5)) { /* See if valid savearea */
1789 panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %p\n", vsv
); /* Die */
1792 save_release((struct savearea
*)vsv
); /* Toss saved context */
1799 * thread_enable_fpe:
1801 * enables or disables floating point exceptions for the thread.
1804 int thread_enable_fpe(
1808 struct savearea
*sv
;
1811 sv
= find_user_regs(thread
); /* Find the user registers */
1812 if(!sv
) sv
= get_user_regs(thread
); /* Didn't find any, allocate and initialize one */
1814 oldmsr
= sv
->save_srr1
; /* Get the old msr */
1816 if(onoff
) sv
->save_srr1
= oldmsr
| (uint64_t)(MASK(MSR_FE0
) | MASK(MSR_FE1
)); /* Flip on precise FP exceptions */
1817 else sv
->save_srr1
= oldmsr
& (uint64_t)(~(MASK(MSR_FE0
) | MASK(MSR_FE1
))); /* Flip on precise FP exceptions */
1819 return ((oldmsr
& (MASK(MSR_FE0
) | MASK(MSR_FE1
))) != 0); /* Return if it was enabled or not */