]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/status.c
xnu-1504.7.4.tar.gz
[apple/xnu.git] / osfmk / ppc / status.c
1 /*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 *
31 */
32
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>
44
45 typedef unsigned int fixpt_t; /* XXX <sys/resource.h> not self contained */
46 #include <ppc/vmparam.h> /* USRSTACK, etc. */
47
48 #include <vm/vm_map.h>
49
50 extern unsigned int killprint;
51 extern double FloatInit;
52 extern unsigned long QNaNbarbarian[4];
53
54 kern_return_t
55 thread_userstack(
56 thread_t,
57 int,
58 thread_state_t,
59 unsigned int,
60 mach_vm_offset_t *,
61 int *
62 );
63
64 kern_return_t
65 thread_entrypoint(
66 thread_t,
67 int,
68 thread_state_t,
69 unsigned int,
70 mach_vm_offset_t *
71 );
72
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);
80
81 /*
82 * Maps state flavor to number of words in the state:
83 */
84 /* __private_extern__ */
85 unsigned int _MachineStateCount[] = {
86 /* FLAVOR_LIST */ 0,
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,
93 };
94
95 /*
96 * thread_getstatus:
97 *
98 * Get the status of the specified thread.
99 */
100
101 kern_return_t
102 machine_thread_get_state(
103 thread_t thread,
104 thread_flavor_t flavor,
105 thread_state_t tstate,
106 mach_msg_type_number_t *count)
107 {
108
109 register struct savearea *sv; /* Pointer to the context savearea */
110 register savearea_fpu *fsv;
111 register savearea_vec *vsv;
112 struct savearea *genuser;
113 int i, j;
114 unsigned int vrvalidwrk;
115
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;
122
123 genuser = find_user_regs(thread);
124
125 switch (flavor) {
126
127 case THREAD_STATE_FLAVOR_LIST:
128
129 if (*count < 6) {
130 return (KERN_INVALID_ARGUMENT);
131 }
132
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;
139 *count = 6;
140
141 return KERN_SUCCESS;
142
143 case PPC_THREAD_STATE:
144
145 if (*count < PPC_THREAD_STATE_COUNT) { /* Is the count ok? */
146 return KERN_INVALID_ARGUMENT;
147 }
148
149 ts = (struct ppc_thread_state *) tstate;
150
151 sv = genuser; /* Copy this over */
152
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) */
194 }
195 else { /* No user state yet. Save seemingly random values. */
196
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];
200 }
201 ts->cr = 0;
202 ts->xer = 0;
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;
207 ts->mq = 0;
208 ts->vrsave = 0; /* VRSAVE register (Altivec only) */
209 }
210
211 *count = PPC_THREAD_STATE_COUNT; /* Pass back the amount we actually copied */
212 return KERN_SUCCESS;
213
214
215 case PPC_THREAD_STATE64:
216
217 if (*count < PPC_THREAD_STATE64_COUNT) { /* Is the count ok? */
218 return KERN_INVALID_ARGUMENT;
219 }
220
221 xts = (struct ppc_thread_state64 *) tstate;
222
223 sv = genuser; /* Copy this over */
224
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) */
265 }
266 else { /* No user state yet. Save seemingly random values. */
267
268 for(i=0; i < 32; i++) { /* Fill up with defaults */
269 ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
270 }
271 xts->cr = 0;
272 xts->xer = 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) */
280 }
281
282 *count = PPC_THREAD_STATE64_COUNT; /* Pass back the amount we actually copied */
283 return KERN_SUCCESS;
284
285 case PPC_EXCEPTION_STATE:
286
287 if (*count < PPC_EXCEPTION_STATE_COUNT) {
288 return KERN_INVALID_ARGUMENT;
289 }
290
291 es = (struct ppc_exception_state *) tstate;
292 sv = genuser; /* Copy this over */
293
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;
298 }
299 else { /* Nope, not yet */
300 es->dar = 0;
301 es->dsisr = 0;
302 es->exception = ((unsigned int *)&FloatInit)[0];
303 }
304
305 *count = PPC_EXCEPTION_STATE_COUNT;
306 return KERN_SUCCESS;
307
308 case PPC_EXCEPTION_STATE64:
309
310 if (*count < PPC_EXCEPTION_STATE64_COUNT) {
311 return KERN_INVALID_ARGUMENT;
312 }
313
314 xes = (struct ppc_exception_state64 *) tstate;
315 sv = genuser; /* Copy this over */
316
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;
321 }
322 else { /* Nope, not yet */
323 xes->dar = 0;
324 xes->dsisr = 0;
325 xes->exception = ((unsigned int *)&FloatInit)[0];
326 }
327
328 *count = PPC_EXCEPTION_STATE64_COUNT;
329 return KERN_SUCCESS;
330
331 case PPC_FLOAT_STATE:
332
333 if (*count < PPC_FLOAT_STATE_COUNT) {
334 return KERN_INVALID_ARGUMENT;
335 }
336
337 fpu_save(thread->machine.curctx); /* Just in case it's live, save it */
338
339 fs = (struct ppc_float_state *) tstate; /* Point to destination */
340
341 fsv = find_user_fpu(thread); /* Get the user's fpu savearea */
342
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 */
348 }
349 else { /* No floating point yet */
350
351 for(i=0; i < 32; i++) { /* Initialize floating points */
352 fs->fpregs[i] = FloatInit; /* Initial value */
353 }
354 fs->fpscr_pad = 0; /* Initial value */
355 fs->fpscr = 0; /* Initial value */
356 }
357
358 *count = PPC_FLOAT_STATE_COUNT;
359
360 return KERN_SUCCESS;
361
362 case PPC_VECTOR_STATE:
363
364 if (*count < PPC_VECTOR_STATE_COUNT) {
365 return KERN_INVALID_ARGUMENT;
366 }
367
368 vec_save(thread->machine.curctx); /* Just in case it's live, save it */
369
370 vs = (struct ppc_vector_state *) tstate; /* Point to destination */
371
372 vsv = find_user_vec(thread); /* Find the vector savearea */
373
374 if(vsv) { /* See if we have any */
375
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 */
379 else {
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 */
384 }
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 */
390 }
391 vrvalidwrk = vrvalidwrk << 1; /* Shift over to the next */
392 }
393 }
394 else { /* No vector yet */
395
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 */
398 }
399
400 if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j]; /* Set value for vscr */
401 else {
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 */
406 }
407 vs->save_vrvalid = 0; /* Clear the valid flags */
408 }
409
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 */
412
413 *count = PPC_VECTOR_STATE_COUNT;
414 return KERN_SUCCESS;
415
416 default:
417 return KERN_INVALID_ARGUMENT;
418 }
419 }
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().
425 */
426
427 kern_return_t
428 machine_thread_get_kern_state(
429 thread_t thread,
430 thread_flavor_t flavor,
431 thread_state_t tstate,
432 mach_msg_type_number_t *count)
433 {
434
435 register struct savearea *sv; /* Pointer to the context savearea */
436 struct savearea *genkern;
437 int i;
438
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;
443
444 genkern = find_kern_regs(thread);
445
446 switch (flavor) {
447
448 case THREAD_STATE_FLAVOR_LIST:
449
450 if (*count < 6) {
451 return (KERN_INVALID_ARGUMENT);
452 }
453
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;
460 *count = 6;
461
462 return KERN_SUCCESS;
463
464 case PPC_THREAD_STATE:
465
466 if (*count < PPC_THREAD_STATE_COUNT) { /* Is the count ok? */
467 return KERN_INVALID_ARGUMENT;
468 }
469
470 ts = (struct ppc_thread_state *) tstate;
471
472 sv = genkern; /* Copy this over */
473
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) */
515 }
516 else { /* No state yet. Save seemingly random values. */
517
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];
521 }
522 ts->cr = 0;
523 ts->xer = 0;
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;
528 ts->mq = 0;
529 ts->vrsave = 0; /* VRSAVE register (Altivec only) */
530 }
531
532 *count = PPC_THREAD_STATE_COUNT; /* Pass back the amount we actually copied */
533 return KERN_SUCCESS;
534
535
536 case PPC_THREAD_STATE64:
537
538 if (*count < PPC_THREAD_STATE64_COUNT) { /* Is the count ok? */
539 return KERN_INVALID_ARGUMENT;
540 }
541
542 xts = (struct ppc_thread_state64 *) tstate;
543
544 sv = genkern; /* Copy this over */
545
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) */
586 }
587 else { /* No user state yet. Save seemingly random values. */
588
589 for(i=0; i < 32; i++) { /* Fill up with defaults */
590 ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
591 }
592 xts->cr = 0;
593 xts->xer = 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) */
599 }
600
601 *count = PPC_THREAD_STATE64_COUNT; /* Pass back the amount we actually copied */
602 return KERN_SUCCESS;
603
604 case PPC_EXCEPTION_STATE:
605
606 if (*count < PPC_EXCEPTION_STATE_COUNT) {
607 return KERN_INVALID_ARGUMENT;
608 }
609
610 es = (struct ppc_exception_state *) tstate;
611 sv = genkern; /* Copy this over */
612
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;
617 }
618 else { /* Nope, not yet */
619 es->dar = 0;
620 es->dsisr = 0;
621 es->exception = ((unsigned int *)&FloatInit)[0];
622 }
623
624 *count = PPC_EXCEPTION_STATE_COUNT;
625 return KERN_SUCCESS;
626
627 case PPC_EXCEPTION_STATE64:
628
629 if (*count < PPC_EXCEPTION_STATE64_COUNT) {
630 return KERN_INVALID_ARGUMENT;
631 }
632
633 xes = (struct ppc_exception_state64 *) tstate;
634 sv = genkern; /* Copy this over */
635
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;
640 }
641 else { /* Nope, not yet */
642 xes->dar = 0;
643 xes->dsisr = 0;
644 xes->exception = ((unsigned int *)&FloatInit)[0];
645 }
646
647 *count = PPC_EXCEPTION_STATE64_COUNT;
648 return KERN_SUCCESS;
649
650 default:
651 return KERN_INVALID_ARGUMENT;
652 }
653 }
654
655
656 /*
657 * thread_setstatus:
658 *
659 * Set the status of the specified thread.
660 */
661 kern_return_t
662 machine_thread_set_state(
663 thread_t thread,
664 thread_flavor_t flavor,
665 thread_state_t tstate,
666 mach_msg_type_number_t count)
667 {
668
669 struct savearea *genuser;
670 savearea_fpu *fsv, *fsvn, *fsvo;
671 savearea_vec *vsv, *vsvn, *vsvo;
672 unsigned int i;
673 unsigned int clgn;
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;
680
681 // dbgTrace((unsigned int)thr_act, (unsigned int)0 /*sv: was never set*/, flavor); /* (TEST/DEBUG) */
682
683 clgn = count; /* Get the count */
684
685 switch (flavor) { /* Validate the count before we do anything else */
686 case PPC_THREAD_STATE:
687
688 if (clgn < PPC_THREAD_STATE_COUNT) { /* Is it too short? */
689 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
690 }
691 break;
692
693 case PPC_THREAD_STATE64:
694
695 if (clgn < PPC_THREAD_STATE64_COUNT) { /* Is it too short? */
696 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
697 }
698 break;
699
700 case PPC_EXCEPTION_STATE:
701
702 if (clgn < PPC_EXCEPTION_STATE_COUNT) { /* Is it too short? */
703 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
704 }
705
706 case PPC_EXCEPTION_STATE64:
707
708 if (clgn < PPC_EXCEPTION_STATE64_COUNT) { /* Is it too short? */
709 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
710 }
711
712 break;
713
714 case PPC_FLOAT_STATE:
715
716 if (clgn < PPC_FLOAT_STATE_COUNT) { /* Is it too short? */
717 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
718 }
719
720 break;
721
722
723 case PPC_VECTOR_STATE:
724
725 if (clgn < PPC_VECTOR_STATE_COUNT) { /* Is it too short? */
726 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
727 }
728
729 break;
730
731 default:
732 return KERN_INVALID_ARGUMENT;
733 }
734
735 genuser = get_user_regs(thread); /* Find or allocate and initialize one */
736
737 switch (flavor) {
738
739 case PPC_THREAD_STATE:
740
741 ts = (struct ppc_thread_state *)tstate;
742
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;
775
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) */
782
783 genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, ts->srr1); /* Set the bits we can change */
784
785 genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
786
787 genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make sure we don't enable the floating point unit */
788
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 */
791 else
792 genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32); /* else 32-bit mode */
793
794 return KERN_SUCCESS;
795
796
797 case PPC_THREAD_STATE64:
798
799 xts = (struct ppc_thread_state64 *)tstate;
800
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;
833
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) */
840
841 genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, xts->srr1); /* Set the bits we can change */
842
843 genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
844
845 genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make sure we don't enable the floating point unit */
846
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 */
849 else
850 genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32); /* else 32-bit mode */
851
852 return KERN_SUCCESS;
853
854
855 case PPC_EXCEPTION_STATE:
856
857 es = (struct ppc_exception_state *) tstate;
858
859 genuser->save_dar = (uint64_t)es->dar;
860 genuser->save_dsisr = es->dsisr;
861 genuser->save_exception = es->exception;
862
863 return KERN_SUCCESS;
864
865 /*
866 * It's pretty worthless to try to change this stuff, but we'll do it anyway.
867 */
868
869 case PPC_EXCEPTION_STATE64:
870
871 xes = (struct ppc_exception_state *) tstate;
872
873 genuser->save_dar = xes->dar;
874 genuser->save_dsisr = xes->dsisr;
875 genuser->save_exception = xes->exception;
876
877 return KERN_SUCCESS;
878
879 case PPC_FLOAT_STATE:
880
881 toss_live_fpu(thread->machine.curctx); /* Toss my floating point if live anywhere */
882
883 fsv = find_user_fpu(thread); /* Get the user's floating point context */
884
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 */
891
892 if(!thread->machine.curctx->FPUsave) thread->machine.curctx->FPUsave = fsv; /* If no floating point, chain us first */
893 else {
894
895 fsvn = fsvo = thread->machine.curctx->FPUsave; /* Remember first one */
896
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 */
900 }
901
902 fsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv); /* Queue us on in */
903 }
904
905 }
906
907 fs = (struct ppc_float_state *) tstate; /* Point to source */
908
909
910 bcopy((char *)fs, (char *)&fsv->save_fp0, 32*8); /* Move in the 32 registers */
911
912 genuser->save_fpscr = fs->fpscr; /* Copy the fpscr value to normal */
913
914 return KERN_SUCCESS;
915
916
917 case PPC_VECTOR_STATE:
918
919 toss_live_vec(thread->machine.curctx); /* Toss my vector if live anywhere */
920
921 vsv = find_user_vec(thread); /* Get the user's vector context */
922
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 */
929
930 if(!thread->machine.curctx->VMXsave) thread->machine.curctx->VMXsave = vsv; /* If no vector, chain us first */
931 else {
932
933 vsvn = vsvo = thread->machine.curctx->VMXsave; /* Remember first one */
934
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 */
938 }
939
940 vsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv); /* Queue us on in */
941 }
942
943 }
944
945 vs = (struct ppc_vector_state *) tstate; /* Point to source */
946
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 */
949
950
951 for(i = 0; i < 4; i++) genuser->save_vscr[i] = vs->save_vscr[i]; /* Set value for vscr */
952
953 return KERN_SUCCESS;
954
955
956 default:
957 return KERN_INVALID_ARGUMENT;
958 }
959 }
960
961
962 void
963 thread_set_wq_state64(thread_t thread, thread_state_t tstate)
964 {
965 struct ppc_thread_state64 *ts;
966 struct savearea *genuser;
967 thread_t curth = current_thread();
968
969 genuser = get_user_regs(thread); /* Find or allocate and initialize one */
970 ts = (struct ppc_thread_state64 *)tstate;
971
972 if (curth != thread)
973 thread_lock(thread);
974
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;
983
984 genuser->save_srr1 = (uint64_t)MSR_EXPORT_MASK_SET;
985
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 */
988
989 if (curth != thread)
990 thread_unlock(thread);
991 }
992
993
994 /*
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.)
1000 */
1001 kern_return_t
1002 machine_thread_state_initialize(
1003 thread_t thread)
1004 {
1005 struct savearea *sv;
1006
1007 sv = get_user_regs(thread); /* Find or allocate and initialize one */
1008
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 */
1015
1016 return KERN_SUCCESS;
1017 }
1018
1019
1020 /*
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.
1024 *
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.
1027 */
1028
1029 kern_return_t
1030 machine_thread_dup(
1031 thread_t self,
1032 thread_t target)
1033 {
1034 struct savearea *sv, *osv;
1035 savearea_fpu *fsv, *fsvn;
1036 savearea_vec *vsv, *vsvn;
1037
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 */
1040
1041 sv = get_user_regs(target); /* Allocate and initialze context in the new activation */
1042
1043 osv = find_user_regs(self); /* Find the original context */
1044 if(!osv)
1045 return (KERN_FAILURE);
1046
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));
1050
1051 sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC))); /* Make certain that floating point and vector are turned off */
1052
1053 fsv = find_user_fpu(self); /* Get any user floating point */
1054
1055 target->machine.curctx->FPUsave = NULL; /* Assume no floating point */
1056
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 */
1063
1064 target->machine.curctx->FPUsave = fsvn; /* Chain in the floating point */
1065
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));
1069 }
1070
1071 vsv = find_user_vec(self); /* Get any user vector */
1072
1073 target->machine.curctx->VMXsave = NULL; /* Assume no vector */
1074
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 */
1081
1082 target->machine.curctx->VMXsave = vsvn; /* Chain in the floating point */
1083
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));
1087 }
1088
1089 return (KERN_SUCCESS);
1090 }
1091
1092 /*
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.
1095 *
1096 * We only set initial values if there was no context found.
1097 */
1098
1099 struct savearea *
1100 get_user_regs(
1101 thread_t thread)
1102 {
1103 struct savearea *sv, *osv;
1104 unsigned int i;
1105
1106 if (thread->machine.upcb)
1107 return thread->machine.upcb;
1108
1109 sv = thread->machine.pcb; /* Get the top savearea on the stack */
1110 osv = NULL; /* Set no user savearea yet */
1111
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 */
1115 }
1116
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 */
1122
1123 if(osv) { /* Did we already have one? */
1124 osv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv); /* Chain us on the end */
1125 }
1126 else { /* We are the first */
1127 thread->machine.pcb = sv; /* Put it there */
1128 }
1129 thread->machine.upcb = sv; /* Set user pcb */
1130
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];
1134 }
1135 sv->save_cr = 0;
1136 sv->save_xer = 0;
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 */
1143
1144 sv->save_fpscr = 0; /* Clear all floating point exceptions */
1145
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 */
1151
1152 return sv; /* Bye bye... */
1153 }
1154
1155 /*
1156 * Find the user state context. If there is no user state context,
1157 * we just return a 0.
1158 */
1159
1160 struct savearea *
1161 find_user_regs(
1162 thread_t thread)
1163 {
1164 return thread->machine.upcb;
1165 }
1166
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..
1169 */
1170 struct savearea *
1171 find_kern_regs(
1172 thread_t thread)
1173 {
1174 return thread->machine.pcb;
1175 }
1176
1177 /*
1178 * Find the user state floating point context. If there is no user state context,
1179 * we just return a 0.
1180 */
1181
1182 savearea_fpu *
1183 find_user_fpu(
1184 thread_t thread)
1185 {
1186 savearea_fpu *fsv;
1187 boolean_t intr;
1188
1189 intr = ml_set_interrupts_enabled(FALSE);
1190 fsv = thread->machine.curctx->FPUsave; /* Get the start of the floating point chain */
1191
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 */
1195 }
1196 (void) ml_set_interrupts_enabled(intr);
1197
1198 return fsv; /* Bye bye... */
1199 }
1200
1201 /*
1202 * Find the user state vector context. If there is no user state context,
1203 * we just return a 0.
1204 */
1205
1206 savearea_vec *
1207 find_user_vec(
1208 thread_t thread)
1209 {
1210 savearea_vec *vsv;
1211 boolean_t intr;
1212
1213 intr = ml_set_interrupts_enabled(FALSE);
1214 vsv = thread->machine.curctx->VMXsave; /* Get the start of the vector chain */
1215
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 */
1219 }
1220 (void) ml_set_interrupts_enabled(intr);
1221
1222 return vsv; /* Bye bye... */
1223 }
1224 /*
1225 * Find the user state vector context for the current thread. If there is no user state context,
1226 * we just return a 0.
1227 */
1228
1229 savearea_vec *find_user_vec_curr(void) {
1230
1231 savearea_vec *vsv;
1232 thread_t thread = current_thread();
1233 boolean_t intr;
1234
1235 vec_save(thread->machine.curctx); /* Force save if live */
1236
1237 intr = ml_set_interrupts_enabled(FALSE);
1238 vsv = thread->machine.curctx->VMXsave; /* Get the start of the vector chain */
1239
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 */
1243 }
1244 (void) ml_set_interrupts_enabled(intr);
1245
1246 return vsv; /* Bye bye... */
1247 }
1248
1249 /*
1250 * thread_userstack:
1251 *
1252 * Return the user stack pointer from the machine
1253 * dependent thread state info.
1254 */
1255 kern_return_t
1256 thread_userstack(
1257 __unused thread_t thread,
1258 int flavor,
1259 thread_state_t tstate,
1260 unsigned int count,
1261 mach_vm_offset_t *user_stack,
1262 int *customstack
1263 )
1264 {
1265 /*
1266 * Set a default.
1267 */
1268
1269 switch (flavor) {
1270 case PPC_THREAD_STATE:
1271 {
1272 struct ppc_thread_state *state;
1273
1274 if (count < PPC_THREAD_STATE_COUNT)
1275 return (KERN_INVALID_ARGUMENT);
1276
1277 state = (struct ppc_thread_state *) tstate;
1278
1279 /*
1280 * If a valid user stack is specified, use it.
1281 */
1282 if (state->r1) {
1283 *user_stack = CAST_USER_ADDR_T(state->r1);
1284 if (customstack)
1285 *customstack = 1;
1286 } else {
1287 *user_stack = CAST_USER_ADDR_T(USRSTACK);
1288 if (customstack)
1289 *customstack = 0;
1290 }
1291 }
1292 break;
1293
1294 case PPC_THREAD_STATE64:
1295 {
1296 struct ppc_thread_state64 *state64;
1297
1298 if (count < PPC_THREAD_STATE64_COUNT)
1299 return (KERN_INVALID_ARGUMENT);
1300
1301 state64 = (struct ppc_thread_state64 *)tstate;
1302
1303 /*
1304 * If a valid user stack is specified, use it.
1305 */
1306 if (state64->r1 != MACH_VM_MIN_ADDRESS) {
1307 *user_stack = state64->r1;
1308 if (customstack)
1309 *customstack = 1;
1310 } else {
1311 *user_stack = USRSTACK64;
1312 if (customstack)
1313 *customstack = 0;
1314 }
1315 }
1316 break;
1317
1318 default :
1319 return (KERN_INVALID_ARGUMENT);
1320 }
1321
1322 return (KERN_SUCCESS);
1323 }
1324
1325
1326 /*
1327 * thread_setuserstack:
1328 *
1329 * Sets the user stack pointer into the machine
1330 * dependent thread state info.
1331 */
1332 void
1333 thread_setuserstack(thread_t thread, mach_vm_address_t user_stack)
1334 {
1335 struct savearea *sv;
1336
1337 sv = get_user_regs(thread); /* Get the user state registers */
1338
1339 sv->save_r1 = user_stack;
1340
1341 return;
1342 }
1343
1344 void
1345 thread_set_cthreadself(thread_t thread, uint64_t pself, int isLP64)
1346 {
1347 struct savearea *sv;
1348
1349 if (isLP64 == 0) {
1350 thread->machine.cthread_self = pself;
1351 } else {
1352 sv = get_user_regs(thread); /* Get the user state registers */
1353
1354 thread->machine.cthread_self = pself;
1355 sv->save_r13 = pself;
1356 }
1357 }
1358
1359
1360 /*
1361 * thread_adjuserstack:
1362 *
1363 * Returns the adjusted user stack pointer from the machine
1364 * dependent thread state info. Usef for small (<2G) deltas.
1365 */
1366 uint64_t
1367 thread_adjuserstack(thread_t thread, int adjust)
1368 {
1369 struct savearea *sv;
1370
1371 sv = get_user_regs(thread); /* Get the user state registers */
1372
1373 sv->save_r1 += adjust; /* Adjust the stack */
1374
1375 return sv->save_r1; /* Return the adjusted stack */
1376
1377 }
1378
1379 kern_return_t
1380 thread_setsinglestep(thread_t thread, int on)
1381 {
1382 struct savearea *sv;
1383
1384 sv = get_user_regs(thread); /* Get the user state registers */
1385
1386 if (on)
1387 sv->save_srr1 |= MASK(MSR_SE);
1388 else
1389 sv->save_srr1 &= ~MASK(MSR_SE);
1390
1391 return (KERN_SUCCESS);
1392 }
1393
1394 /*
1395 * thread_setentrypoint:
1396 *
1397 * Sets the user PC into the machine
1398 * dependent thread state info.
1399 */
1400
1401 void
1402 thread_setentrypoint(thread_t thread, uint64_t entry)
1403 {
1404 struct savearea *sv;
1405
1406 sv = get_user_regs(thread); /* Get the user state registers */
1407
1408 sv->save_srr0 = entry;
1409 }
1410
1411 kern_return_t
1412 thread_entrypoint(
1413 __unused thread_t thread,
1414 int flavor,
1415 thread_state_t tstate,
1416 unsigned int count,
1417 mach_vm_offset_t *entry_point
1418 )
1419 {
1420 #if 0
1421 /* Silly code: "if *entry_point is 0, make it 0" */
1422 /*
1423 * Set a default.
1424 */
1425 if (*entry_point == 0ULL)
1426 *entry_point = MACH_VM_MIN_ADDRESS;
1427 #endif
1428
1429 switch (flavor) {
1430 case PPC_THREAD_STATE:
1431 {
1432 struct ppc_thread_state *state;
1433
1434 if (count < PPC_THREAD_STATE_COUNT)
1435 return (KERN_INVALID_ARGUMENT);
1436
1437 state = (struct ppc_thread_state *) tstate;
1438
1439 /*
1440 * If a valid entry point is specified, use it.
1441 */
1442 if (state->srr0) {
1443 *entry_point = CAST_USER_ADDR_T(state->srr0);
1444 } else {
1445 *entry_point = CAST_USER_ADDR_T(VM_MIN_ADDRESS);
1446 }
1447 }
1448 break;
1449
1450 case PPC_THREAD_STATE64:
1451 {
1452 struct ppc_thread_state64 *state64;
1453
1454 if (count < PPC_THREAD_STATE_COUNT)
1455 return (KERN_INVALID_ARGUMENT);
1456
1457 state64 = (struct ppc_thread_state64 *)tstate;
1458
1459 /*
1460 * If a valid entry point is specified, use it.
1461 */
1462 if (state64->srr0) {
1463 *entry_point = state64->srr0;
1464 } else {
1465 *entry_point = MACH_VM_MIN_ADDRESS;
1466 }
1467 }
1468 break;
1469
1470 default:
1471 return (KERN_INVALID_ARGUMENT);
1472 }
1473
1474 return (KERN_SUCCESS);
1475 }
1476
1477 unsigned int get_msr_exportmask(void)
1478 {
1479 return (MSR_EXPORT_MASK_SET);
1480 }
1481
1482 unsigned int get_msr_nbits(void)
1483 {
1484 return (MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1485 }
1486 unsigned int get_msr_rbits(void)
1487 {
1488 return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1489 }
1490
1491 void ppc_checkthreadstate(void * tsptr, int flavor)
1492 {
1493 if (flavor == PPC_THREAD_STATE64) {
1494 struct ppc_thread_state64 *ts64 =(struct ppc_thread_state64 *)tsptr;
1495
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));
1499 } else {
1500 struct ppc_thread_state *ts =(struct ppc_thread_state *)tsptr;
1501
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));
1505 }
1506 return;
1507 }
1508
1509 void
1510 thread_set_child(
1511 thread_t child,
1512 int pid)
1513 {
1514 struct savearea *child_state;
1515
1516 child_state = get_user_regs(child);
1517
1518 child_state->save_r3 = (uint_t)pid;
1519 child_state->save_r4 = 1ULL;
1520 }
1521 void
1522 thread_set_parent(
1523 thread_t parent,
1524 int pid)
1525 {
1526 struct savearea *parent_state;
1527
1528 parent_state = get_user_regs(parent);
1529
1530 parent_state->save_r3 = (uint64_t)pid;
1531 parent_state->save_r4 = 0;
1532 }
1533
1534 /*
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
1537 * pointer to that.
1538 *
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.
1541 *
1542 */
1543
1544 void *act_thread_csave(void) {
1545
1546 struct savearea *sv, *osv;
1547 savearea_fpu *fsv, *ofsv;
1548 savearea_vec *vsv, *ovsv;
1549
1550 thread_t thread;
1551
1552 thread = current_thread();
1553
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 */
1556
1557 osv = find_user_regs(thread); /* Get our savearea */
1558
1559 if(!osv) {
1560 panic("act_thread_csave: attempting to preserve the context of an activation with none (%p)\n", thread);
1561 }
1562
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 */
1568
1569
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));
1573
1574 sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC))); /* Make certain that floating point and vector are turned off */
1575
1576 sv->save_hdr.save_misc2 = 0xDEBB1ED0; /* Eye catcher for debug */
1577 sv->save_hdr.save_misc3 = 0xE5DA11A5; /* Eye catcher for debug */
1578
1579
1580 ofsv = find_user_fpu(thread); /* Get any user floating point */
1581
1582 sv->save_hdr.save_misc0 = 0; /* Assume no floating point */
1583
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 */
1592
1593 sv->save_hdr.save_misc0 = (uint64_t)((uintptr_t)fsv); /* Remember this one */
1594
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));
1598 }
1599
1600 ovsv = find_user_vec(thread); /* Get any user vector */
1601
1602 sv->save_hdr.save_misc1 = 0; /* Assume no vector */
1603
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 */
1612
1613 sv->save_hdr.save_misc1 = (uint64_t)((uintptr_t)vsv); /* Chain in the floating point */
1614
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));
1618 }
1619
1620 return (void *)sv; /* Bye bye... */
1621 }
1622
1623
1624
1625 /*
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.
1630 *
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.
1633 *
1634 */
1635
1636 void act_thread_catt(void *ctx) {
1637
1638 struct savearea *sv, *osv, *psv;
1639 savearea_fpu *fsv, *ofsv, *pfsv;
1640 savearea_vec *vsv, *ovsv, *pvsv;
1641 unsigned int spc;
1642 thread_t thread;
1643
1644 sv = (struct savearea *)ctx; /* Make this easier for C */
1645
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 */
1648
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 */
1651 }
1652
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 */
1655 }
1656
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 */
1659 }
1660
1661 thread = current_thread();
1662
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 */
1667
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;
1671
1672 spc = (unsigned int)thread->map->pmap->space; /* Get the space we're in */
1673
1674 osv = thread->machine.pcb; /* Get the top general savearea */
1675 psv = NULL;
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 */
1680 }
1681
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 */
1685
1686 save_release(osv); /* Nope, release it */
1687
1688 }
1689
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 */
1693
1694 ovsv = thread->machine.curctx->VMXsave; /* Get the top vector savearea */
1695
1696 pvsv = NULL;
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 */
1701 }
1702
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 */
1706
1707 save_release((struct savearea *)ovsv); /* Nope, release it */
1708 }
1709
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 */
1712 else {
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 */
1715 }
1716
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;
1720 }
1721
1722 ofsv = thread->machine.curctx->FPUsave; /* Get the top float savearea */
1723
1724 pfsv = NULL;
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 */
1729 }
1730
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 */
1734
1735 save_release((struct savearea *)ofsv); /* Nope, release it */
1736 }
1737
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 */
1740 else {
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 */
1743 }
1744
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;
1748 }
1749
1750 }
1751
1752
1753
1754 /*
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.
1757 *
1758 */
1759
1760 void
1761 act_thread_cfree(void *ctx)
1762 {
1763
1764 struct savearea *sv;
1765 savearea_fpu *fsv;
1766 savearea_vec *vsv;
1767
1768 sv = (struct savearea *)ctx; /* Make this easier for C */
1769
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 */
1772
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 */
1775 }
1776
1777 save_release(sv); /* Toss the general savearea */
1778
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 */
1782 }
1783
1784 save_release((struct savearea *)fsv); /* Toss saved context */
1785 }
1786
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 */
1790 }
1791
1792 save_release((struct savearea *)vsv); /* Toss saved context */
1793 }
1794
1795 return;
1796 }
1797
1798 /*
1799 * thread_enable_fpe:
1800 *
1801 * enables or disables floating point exceptions for the thread.
1802 * returns old state
1803 */
1804 int thread_enable_fpe(
1805 thread_t thread,
1806 int onoff)
1807 {
1808 struct savearea *sv;
1809 uint64_t oldmsr;
1810
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 */
1813
1814 oldmsr = sv->save_srr1; /* Get the old msr */
1815
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 */
1818
1819 return ((oldmsr & (MASK(MSR_FE0) | MASK(MSR_FE1))) != 0); /* Return if it was enabled or not */
1820 }