]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/status.c
c71f35bcaecb01b947ec891e9e83fbd7aff4f71d
[apple/xnu.git] / osfmk / ppc / status.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * @OSF_COPYRIGHT@
25 *
26 */
27
28 #include <kern/thread.h>
29 #include <kern/misc_protos.h>
30 #include <mach/ppc/thread_status.h>
31 #include <ppc/proc_reg.h>
32 #include <ppc/cpu_internal.h>
33 #include <ppc/exception.h>
34 #include <ppc/misc_protos.h>
35 #include <ppc/savearea.h>
36 #include <ppc/thread.h>
37 #include <ppc/Firmware.h>
38
39 //#include <sys/time.h>
40 typedef unsigned int fixpt_t; /* XXX <sys/resource.h> not self contained */
41 #include <ppc/vmparam.h> /* USRSTACK, etc. */
42
43 #include <vm/vm_map.h>
44
45 extern unsigned int killprint;
46 extern double FloatInit;
47 extern unsigned long QNaNbarbarian[4];
48
49 #define USRSTACK 0xc0000000
50
51 kern_return_t
52 thread_userstack(
53 thread_t,
54 int,
55 thread_state_t,
56 unsigned int,
57 mach_vm_offset_t *,
58 int *
59 );
60
61 kern_return_t
62 thread_entrypoint(
63 thread_t,
64 int,
65 thread_state_t,
66 unsigned int,
67 mach_vm_offset_t *
68 );
69
70 unsigned int get_msr_exportmask(void);
71 unsigned int get_msr_nbits(void);
72 unsigned int get_msr_rbits(void);
73 void ppc_checkthreadstate(void *, int);
74 void thread_set_child(thread_t child, int pid);
75 void thread_set_parent(thread_t parent, int pid);
76 void save_release(struct savearea *save);
77
78 /*
79 * Maps state flavor to number of words in the state:
80 */
81 __private_extern__
82 unsigned int _MachineStateCount[] = {
83 /* FLAVOR_LIST */ 0,
84 PPC_THREAD_STATE_COUNT,
85 PPC_FLOAT_STATE_COUNT,
86 PPC_EXCEPTION_STATE_COUNT,
87 PPC_VECTOR_STATE_COUNT,
88 PPC_THREAD_STATE64_COUNT,
89 PPC_EXCEPTION_STATE64_COUNT,
90 };
91
92 /*
93 * thread_getstatus:
94 *
95 * Get the status of the specified thread.
96 */
97
98 kern_return_t
99 machine_thread_get_state(
100 thread_t thread,
101 thread_flavor_t flavor,
102 thread_state_t tstate,
103 mach_msg_type_number_t *count)
104 {
105
106 register struct savearea *sv; /* Pointer to the context savearea */
107 register savearea_fpu *fsv;
108 register savearea_vec *vsv;
109 savearea *genuser;
110 int i, j;
111 unsigned int vrvalidwrk;
112
113 register struct ppc_thread_state *ts;
114 register struct ppc_thread_state64 *xts;
115 register struct ppc_exception_state *es;
116 register struct ppc_exception_state64 *xes;
117 register struct ppc_float_state *fs;
118 register struct ppc_vector_state *vs;
119
120 genuser = find_user_regs(thread);
121
122 switch (flavor) {
123
124 case THREAD_STATE_FLAVOR_LIST:
125
126 if (*count < 6) {
127 return (KERN_INVALID_ARGUMENT);
128 }
129
130 tstate[0] = PPC_THREAD_STATE;
131 tstate[1] = PPC_FLOAT_STATE;
132 tstate[2] = PPC_EXCEPTION_STATE;
133 tstate[3] = PPC_VECTOR_STATE;
134 tstate[4] = PPC_THREAD_STATE64;
135 tstate[5] = PPC_EXCEPTION_STATE64;
136 *count = 6;
137
138 return KERN_SUCCESS;
139
140 case PPC_THREAD_STATE:
141
142 if (*count < PPC_THREAD_STATE_COUNT) { /* Is the count ok? */
143 return KERN_INVALID_ARGUMENT;
144 }
145
146 ts = (struct ppc_thread_state *) tstate;
147
148 sv = genuser; /* Copy this over */
149
150 if(sv) { /* Is there a save area yet? */
151 ts->r0 = (unsigned int)sv->save_r0;
152 ts->r1 = (unsigned int)sv->save_r1;
153 ts->r2 = (unsigned int)sv->save_r2;
154 ts->r3 = (unsigned int)sv->save_r3;
155 ts->r4 = (unsigned int)sv->save_r4;
156 ts->r5 = (unsigned int)sv->save_r5;
157 ts->r6 = (unsigned int)sv->save_r6;
158 ts->r7 = (unsigned int)sv->save_r7;
159 ts->r8 = (unsigned int)sv->save_r8;
160 ts->r9 = (unsigned int)sv->save_r9;
161 ts->r10 = (unsigned int)sv->save_r10;
162 ts->r11 = (unsigned int)sv->save_r11;
163 ts->r12 = (unsigned int)sv->save_r12;
164 ts->r13 = (unsigned int)sv->save_r13;
165 ts->r14 = (unsigned int)sv->save_r14;
166 ts->r15 = (unsigned int)sv->save_r15;
167 ts->r16 = (unsigned int)sv->save_r16;
168 ts->r17 = (unsigned int)sv->save_r17;
169 ts->r18 = (unsigned int)sv->save_r18;
170 ts->r19 = (unsigned int)sv->save_r19;
171 ts->r20 = (unsigned int)sv->save_r20;
172 ts->r21 = (unsigned int)sv->save_r21;
173 ts->r22 = (unsigned int)sv->save_r22;
174 ts->r23 = (unsigned int)sv->save_r23;
175 ts->r24 = (unsigned int)sv->save_r24;
176 ts->r25 = (unsigned int)sv->save_r25;
177 ts->r26 = (unsigned int)sv->save_r26;
178 ts->r27 = (unsigned int)sv->save_r27;
179 ts->r28 = (unsigned int)sv->save_r28;
180 ts->r29 = (unsigned int)sv->save_r29;
181 ts->r30 = (unsigned int)sv->save_r30;
182 ts->r31 = (unsigned int)sv->save_r31;
183 ts->cr = (unsigned int)sv->save_cr;
184 ts->xer = (unsigned int)sv->save_xer;
185 ts->lr = (unsigned int)sv->save_lr;
186 ts->ctr = (unsigned int)sv->save_ctr;
187 ts->srr0 = (unsigned int)sv->save_srr0;
188 ts->srr1 = (unsigned int)sv->save_srr1;
189 ts->mq = 0; /* MQ register (601 only) */
190 ts->vrsave = (unsigned int)sv->save_vrsave; /* VRSAVE register (Altivec only) */
191 }
192 else { /* No user state yet. Save seemingly random values. */
193
194 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
195 ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
196 ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
197 }
198 ts->cr = 0;
199 ts->xer = 0;
200 ts->lr = ((unsigned int *)&FloatInit)[0];
201 ts->ctr = ((unsigned int *)&FloatInit)[1];
202 ts->srr0 = ((unsigned int *)&FloatInit)[0];
203 ts->srr1 = MSR_EXPORT_MASK_SET;
204 ts->mq = 0;
205 ts->vrsave = 0; /* VRSAVE register (Altivec only) */
206 }
207
208 *count = PPC_THREAD_STATE_COUNT; /* Pass back the amount we actually copied */
209 return KERN_SUCCESS;
210
211
212 case PPC_THREAD_STATE64:
213
214 if (*count < PPC_THREAD_STATE64_COUNT) { /* Is the count ok? */
215 return KERN_INVALID_ARGUMENT;
216 }
217
218 xts = (struct ppc_thread_state64 *) tstate;
219
220 sv = genuser; /* Copy this over */
221
222 if(sv) { /* Is there a save area yet? */
223 xts->r0 = sv->save_r0;
224 xts->r1 = sv->save_r1;
225 xts->r2 = sv->save_r2;
226 xts->r3 = sv->save_r3;
227 xts->r4 = sv->save_r4;
228 xts->r5 = sv->save_r5;
229 xts->r6 = sv->save_r6;
230 xts->r7 = sv->save_r7;
231 xts->r8 = sv->save_r8;
232 xts->r9 = sv->save_r9;
233 xts->r10 = sv->save_r10;
234 xts->r11 = sv->save_r11;
235 xts->r12 = sv->save_r12;
236 xts->r13 = sv->save_r13;
237 xts->r14 = sv->save_r14;
238 xts->r15 = sv->save_r15;
239 xts->r16 = sv->save_r16;
240 xts->r17 = sv->save_r17;
241 xts->r18 = sv->save_r18;
242 xts->r19 = sv->save_r19;
243 xts->r20 = sv->save_r20;
244 xts->r21 = sv->save_r21;
245 xts->r22 = sv->save_r22;
246 xts->r23 = sv->save_r23;
247 xts->r24 = sv->save_r24;
248 xts->r25 = sv->save_r25;
249 xts->r26 = sv->save_r26;
250 xts->r27 = sv->save_r27;
251 xts->r28 = sv->save_r28;
252 xts->r29 = sv->save_r29;
253 xts->r30 = sv->save_r30;
254 xts->r31 = sv->save_r31;
255 xts->cr = sv->save_cr;
256 xts->xer = sv->save_xer;
257 xts->lr = sv->save_lr;
258 xts->ctr = sv->save_ctr;
259 xts->srr0 = sv->save_srr0;
260 xts->srr1 = sv->save_srr1;
261 xts->vrsave = sv->save_vrsave; /* VRSAVE register (Altivec only) */
262 }
263 else { /* No user state yet. Save seemingly random values. */
264
265 for(i=0; i < 32; i++) { /* Fill up with defaults */
266 ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
267 }
268 xts->cr = 0;
269 xts->xer = 0;
270 xts->lr = ((unsigned long long *)&FloatInit)[0];
271 xts->ctr = ((unsigned long long *)&FloatInit)[0];
272 xts->srr0 = ((unsigned long long *)&FloatInit)[0];
273 xts->srr1 = MSR_EXPORT_MASK_SET;
274 if(task_has_64BitAddr(thread->task))
275 xts->srr1 |= (uint64_t)MASK32(MSR_SF) << 32; /* If 64-bit task, force 64-bit mode */
276 xts->vrsave = 0; /* VRSAVE register (Altivec only) */
277 }
278
279 *count = PPC_THREAD_STATE64_COUNT; /* Pass back the amount we actually copied */
280 return KERN_SUCCESS;
281
282 case PPC_EXCEPTION_STATE:
283
284 if (*count < PPC_EXCEPTION_STATE_COUNT) {
285 return KERN_INVALID_ARGUMENT;
286 }
287
288 es = (struct ppc_exception_state *) tstate;
289 sv = genuser; /* Copy this over */
290
291 if(sv) { /* See if valid state yet */
292 es->dar = (unsigned int)sv->save_dar;
293 es->dsisr = sv->save_dsisr;
294 es->exception = sv->save_exception;
295 }
296 else { /* Nope, not yet */
297 es->dar = 0;
298 es->dsisr = 0;
299 es->exception = ((unsigned int *)&FloatInit)[0];
300 }
301
302 *count = PPC_EXCEPTION_STATE_COUNT;
303 return KERN_SUCCESS;
304
305 case PPC_EXCEPTION_STATE64:
306
307 if (*count < PPC_EXCEPTION_STATE64_COUNT) {
308 return KERN_INVALID_ARGUMENT;
309 }
310
311 xes = (struct ppc_exception_state64 *) tstate;
312 sv = genuser; /* Copy this over */
313
314 if(sv) { /* See if valid state yet */
315 xes->dar = sv->save_dar;
316 xes->dsisr = sv->save_dsisr;
317 xes->exception = sv->save_exception;
318 }
319 else { /* Nope, not yet */
320 xes->dar = 0;
321 xes->dsisr = 0;
322 xes->exception = ((unsigned int *)&FloatInit)[0];
323 }
324
325 *count = PPC_EXCEPTION_STATE64_COUNT;
326 return KERN_SUCCESS;
327
328 case PPC_FLOAT_STATE:
329
330 if (*count < PPC_FLOAT_STATE_COUNT) {
331 return KERN_INVALID_ARGUMENT;
332 }
333
334 fpu_save(thread->machine.curctx); /* Just in case it's live, save it */
335
336 fs = (struct ppc_float_state *) tstate; /* Point to destination */
337
338 fsv = find_user_fpu(thread); /* Get the user's fpu savearea */
339
340 if(fsv) { /* See if we have any */
341 bcopy((char *)&fsv->save_fp0, (char *)fs, 32*8); /* 32 registers */
342 fs->fpscr_pad = 0; /* Be clean and tidy */
343 if(genuser) fs->fpscr = genuser->save_fpscr; /* Set the fpscr value to general */
344 else fs->fpscr = 0; /* If no user, initialize this */
345 }
346 else { /* No floating point yet */
347
348 for(i=0; i < 32; i++) { /* Initialize floating points */
349 fs->fpregs[i] = FloatInit; /* Initial value */
350 }
351 fs->fpscr_pad = 0; /* Initial value */
352 fs->fpscr = 0; /* Initial value */
353 }
354
355 *count = PPC_FLOAT_STATE_COUNT;
356
357 return KERN_SUCCESS;
358
359 case PPC_VECTOR_STATE:
360
361 if (*count < PPC_VECTOR_STATE_COUNT) {
362 return KERN_INVALID_ARGUMENT;
363 }
364
365 vec_save(thread->machine.curctx); /* Just in case it's live, save it */
366
367 vs = (struct ppc_vector_state *) tstate; /* Point to destination */
368
369 vsv = find_user_vec(thread); /* Find the vector savearea */
370
371 if(vsv) { /* See if we have any */
372
373 vrvalidwrk = vsv->save_vrvalid; /* Get the valid flags */
374 vs->save_vrvalid = vsv->save_vrvalid; /* Set the valid flags */
375 if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j]; /* Set value for vscr */
376 else {
377 vs->save_vscr[0] = 0; /* Set an initial value if no general user yet */
378 vs->save_vscr[1] = 0;
379 vs->save_vscr[2] = 0;
380 vs->save_vscr[3] = 0x00010000; /* Always start with Java mode off */
381 }
382 for(i=0; i < 32; i++) { /* Copy the saved registers and invalidate the others */
383 for(j=0; j < 4; j++) {
384 if(vrvalidwrk & 0x80000000) (vs->save_vr)[i][j] =
385 ((unsigned int *)&(vsv->save_vr0))[(i * 4) + j]; /* We have this register saved */
386 else vs->save_vr[i][j] = QNaNbarbarian[j]; /* Set invalid value */
387 }
388 vrvalidwrk = vrvalidwrk << 1; /* Shift over to the next */
389 }
390 }
391 else { /* No vector yet */
392
393 for(i=0; i < 32; i++) { /* Initialize vector registers */
394 for(j=0; j < 4; j++) vs->save_vr[i][j] = QNaNbarbarian[j]; /* Initial value */
395 }
396
397 if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j]; /* Set value for vscr */
398 else {
399 vs->save_vscr[0] = 0; /* Set an initial value if no general user yet */
400 vs->save_vscr[1] = 0;
401 vs->save_vscr[2] = 0;
402 vs->save_vscr[3] = 0x00010000; /* Always start with Java mode off */
403 }
404 vs->save_vrvalid = 0; /* Clear the valid flags */
405 }
406
407 for (i=0; i < 4; i++) vs->save_pad5[i] = 0; /* Clear cruft */
408 for (i=0; i < 7; i++) vs->save_pad6[i] = 0; /* Clear cruft */
409
410 *count = PPC_VECTOR_STATE_COUNT;
411 return KERN_SUCCESS;
412
413 default:
414 return KERN_INVALID_ARGUMENT;
415 }
416 }
417 /* Close cousin of machine_thread_get_state().
418 * This function is currently incomplete since we don't really need vector
419 * or FP for the core dump (the save area can be accessed directly if the
420 * user is so inclined). Also the function name is something of a misnomer,
421 * see the comment above find_kern_regs().
422 */
423
424 kern_return_t
425 machine_thread_get_kern_state(
426 thread_t thread,
427 thread_flavor_t flavor,
428 thread_state_t tstate,
429 mach_msg_type_number_t *count)
430 {
431
432 register struct savearea *sv; /* Pointer to the context savearea */
433 savearea *genkern;
434 int i;
435
436 register struct ppc_thread_state *ts;
437 register struct ppc_thread_state64 *xts;
438 register struct ppc_exception_state *es;
439 register struct ppc_exception_state64 *xes;
440
441 genkern = find_kern_regs(thread);
442
443 switch (flavor) {
444
445 case THREAD_STATE_FLAVOR_LIST:
446
447 if (*count < 6) {
448 return (KERN_INVALID_ARGUMENT);
449 }
450
451 tstate[0] = PPC_THREAD_STATE;
452 tstate[1] = PPC_FLOAT_STATE;
453 tstate[2] = PPC_EXCEPTION_STATE;
454 tstate[3] = PPC_VECTOR_STATE;
455 tstate[4] = PPC_THREAD_STATE64;
456 tstate[5] = PPC_EXCEPTION_STATE64;
457 *count = 6;
458
459 return KERN_SUCCESS;
460
461 case PPC_THREAD_STATE:
462
463 if (*count < PPC_THREAD_STATE_COUNT) { /* Is the count ok? */
464 return KERN_INVALID_ARGUMENT;
465 }
466
467 ts = (struct ppc_thread_state *) tstate;
468
469 sv = genkern; /* Copy this over */
470
471 if(sv) { /* Is there a save area yet? */
472 ts->r0 = (unsigned int)sv->save_r0;
473 ts->r1 = (unsigned int)sv->save_r1;
474 ts->r2 = (unsigned int)sv->save_r2;
475 ts->r3 = (unsigned int)sv->save_r3;
476 ts->r4 = (unsigned int)sv->save_r4;
477 ts->r5 = (unsigned int)sv->save_r5;
478 ts->r6 = (unsigned int)sv->save_r6;
479 ts->r7 = (unsigned int)sv->save_r7;
480 ts->r8 = (unsigned int)sv->save_r8;
481 ts->r9 = (unsigned int)sv->save_r9;
482 ts->r10 = (unsigned int)sv->save_r10;
483 ts->r11 = (unsigned int)sv->save_r11;
484 ts->r12 = (unsigned int)sv->save_r12;
485 ts->r13 = (unsigned int)sv->save_r13;
486 ts->r14 = (unsigned int)sv->save_r14;
487 ts->r15 = (unsigned int)sv->save_r15;
488 ts->r16 = (unsigned int)sv->save_r16;
489 ts->r17 = (unsigned int)sv->save_r17;
490 ts->r18 = (unsigned int)sv->save_r18;
491 ts->r19 = (unsigned int)sv->save_r19;
492 ts->r20 = (unsigned int)sv->save_r20;
493 ts->r21 = (unsigned int)sv->save_r21;
494 ts->r22 = (unsigned int)sv->save_r22;
495 ts->r23 = (unsigned int)sv->save_r23;
496 ts->r24 = (unsigned int)sv->save_r24;
497 ts->r25 = (unsigned int)sv->save_r25;
498 ts->r26 = (unsigned int)sv->save_r26;
499 ts->r27 = (unsigned int)sv->save_r27;
500 ts->r28 = (unsigned int)sv->save_r28;
501 ts->r29 = (unsigned int)sv->save_r29;
502 ts->r30 = (unsigned int)sv->save_r30;
503 ts->r31 = (unsigned int)sv->save_r31;
504 ts->cr = (unsigned int)sv->save_cr;
505 ts->xer = (unsigned int)sv->save_xer;
506 ts->lr = (unsigned int)sv->save_lr;
507 ts->ctr = (unsigned int)sv->save_ctr;
508 ts->srr0 = (unsigned int)sv->save_srr0;
509 ts->srr1 = (unsigned int)sv->save_srr1;
510 ts->mq = 0; /* MQ register (601 only) */
511 ts->vrsave = (unsigned int)sv->save_vrsave; /* VRSAVE register (Altivec only) */
512 }
513 else { /* No state yet. Save seemingly random values. */
514
515 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
516 ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
517 ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
518 }
519 ts->cr = 0;
520 ts->xer = 0;
521 ts->lr = ((unsigned int *)&FloatInit)[0];
522 ts->ctr = ((unsigned int *)&FloatInit)[1];
523 ts->srr0 = ((unsigned int *)&FloatInit)[0];
524 ts->srr1 = MSR_EXPORT_MASK_SET;
525 ts->mq = 0;
526 ts->vrsave = 0; /* VRSAVE register (Altivec only) */
527 }
528
529 *count = PPC_THREAD_STATE_COUNT; /* Pass back the amount we actually copied */
530 return KERN_SUCCESS;
531
532
533 case PPC_THREAD_STATE64:
534
535 if (*count < PPC_THREAD_STATE64_COUNT) { /* Is the count ok? */
536 return KERN_INVALID_ARGUMENT;
537 }
538
539 xts = (struct ppc_thread_state64 *) tstate;
540
541 sv = genkern; /* Copy this over */
542
543 if(sv) { /* Is there a save area yet? */
544 xts->r0 = sv->save_r0;
545 xts->r1 = sv->save_r1;
546 xts->r2 = sv->save_r2;
547 xts->r3 = sv->save_r3;
548 xts->r4 = sv->save_r4;
549 xts->r5 = sv->save_r5;
550 xts->r6 = sv->save_r6;
551 xts->r7 = sv->save_r7;
552 xts->r8 = sv->save_r8;
553 xts->r9 = sv->save_r9;
554 xts->r10 = sv->save_r10;
555 xts->r11 = sv->save_r11;
556 xts->r12 = sv->save_r12;
557 xts->r13 = sv->save_r13;
558 xts->r14 = sv->save_r14;
559 xts->r15 = sv->save_r15;
560 xts->r16 = sv->save_r16;
561 xts->r17 = sv->save_r17;
562 xts->r18 = sv->save_r18;
563 xts->r19 = sv->save_r19;
564 xts->r20 = sv->save_r20;
565 xts->r21 = sv->save_r21;
566 xts->r22 = sv->save_r22;
567 xts->r23 = sv->save_r23;
568 xts->r24 = sv->save_r24;
569 xts->r25 = sv->save_r25;
570 xts->r26 = sv->save_r26;
571 xts->r27 = sv->save_r27;
572 xts->r28 = sv->save_r28;
573 xts->r29 = sv->save_r29;
574 xts->r30 = sv->save_r30;
575 xts->r31 = sv->save_r31;
576 xts->cr = sv->save_cr;
577 xts->xer = sv->save_xer;
578 xts->lr = sv->save_lr;
579 xts->ctr = sv->save_ctr;
580 xts->srr0 = sv->save_srr0;
581 xts->srr1 = sv->save_srr1;
582 xts->vrsave = sv->save_vrsave; /* VRSAVE register (Altivec only) */
583 }
584 else { /* No user state yet. Save seemingly random values. */
585
586 for(i=0; i < 32; i++) { /* Fill up with defaults */
587 ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
588 }
589 xts->cr = 0;
590 xts->xer = 0;
591 xts->lr = ((unsigned long long *)&FloatInit)[0];
592 xts->ctr = ((unsigned long long *)&FloatInit)[0];
593 xts->srr0 = ((unsigned long long *)&FloatInit)[0];
594 xts->srr1 = MSR_EXPORT_MASK_SET;
595 xts->vrsave = 0; /* VRSAVE register (Altivec only) */
596 }
597
598 *count = PPC_THREAD_STATE64_COUNT; /* Pass back the amount we actually copied */
599 return KERN_SUCCESS;
600
601 case PPC_EXCEPTION_STATE:
602
603 if (*count < PPC_EXCEPTION_STATE_COUNT) {
604 return KERN_INVALID_ARGUMENT;
605 }
606
607 es = (struct ppc_exception_state *) tstate;
608 sv = genkern; /* Copy this over */
609
610 if(sv) { /* See if valid state yet */
611 es->dar = (unsigned int)sv->save_dar;
612 es->dsisr = sv->save_dsisr;
613 es->exception = sv->save_exception;
614 }
615 else { /* Nope, not yet */
616 es->dar = 0;
617 es->dsisr = 0;
618 es->exception = ((unsigned int *)&FloatInit)[0];
619 }
620
621 *count = PPC_EXCEPTION_STATE_COUNT;
622 return KERN_SUCCESS;
623
624 case PPC_EXCEPTION_STATE64:
625
626 if (*count < PPC_EXCEPTION_STATE64_COUNT) {
627 return KERN_INVALID_ARGUMENT;
628 }
629
630 xes = (struct ppc_exception_state64 *) tstate;
631 sv = genkern; /* Copy this over */
632
633 if(sv) { /* See if valid state yet */
634 xes->dar = sv->save_dar;
635 xes->dsisr = sv->save_dsisr;
636 xes->exception = sv->save_exception;
637 }
638 else { /* Nope, not yet */
639 xes->dar = 0;
640 xes->dsisr = 0;
641 xes->exception = ((unsigned int *)&FloatInit)[0];
642 }
643
644 *count = PPC_EXCEPTION_STATE64_COUNT;
645 return KERN_SUCCESS;
646
647 default:
648 return KERN_INVALID_ARGUMENT;
649 }
650 }
651
652
653 /*
654 * thread_setstatus:
655 *
656 * Set the status of the specified thread.
657 */
658 kern_return_t
659 machine_thread_set_state(
660 thread_t thread,
661 thread_flavor_t flavor,
662 thread_state_t tstate,
663 mach_msg_type_number_t count)
664 {
665
666 savearea *genuser;
667 savearea_fpu *fsv, *fsvn, *fsvo;
668 savearea_vec *vsv, *vsvn, *vsvo;
669 unsigned int i;
670 unsigned int clgn;
671 register struct ppc_thread_state *ts;
672 register struct ppc_thread_state64 *xts;
673 register struct ppc_exception_state *es;
674 register struct ppc_exception_state *xes;
675 register struct ppc_float_state *fs;
676 register struct ppc_vector_state *vs;
677
678 // dbgTrace((unsigned int)thr_act, (unsigned int)0 /*sv: was never set*/, flavor); /* (TEST/DEBUG) */
679
680 clgn = count; /* Get the count */
681
682 switch (flavor) { /* Validate the count before we do anything else */
683 case PPC_THREAD_STATE:
684
685 if (clgn < PPC_THREAD_STATE_COUNT) { /* Is it too short? */
686 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
687 }
688 break;
689
690 case PPC_THREAD_STATE64:
691
692 if (clgn < PPC_THREAD_STATE64_COUNT) { /* Is it too short? */
693 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
694 }
695 break;
696
697 case PPC_EXCEPTION_STATE:
698
699 if (clgn < PPC_EXCEPTION_STATE_COUNT) { /* Is it too short? */
700 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
701 }
702
703 case PPC_EXCEPTION_STATE64:
704
705 if (clgn < PPC_EXCEPTION_STATE64_COUNT) { /* Is it too short? */
706 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
707 }
708
709 break;
710
711 case PPC_FLOAT_STATE:
712
713 if (clgn < PPC_FLOAT_STATE_COUNT) { /* Is it too short? */
714 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
715 }
716
717 break;
718
719
720 case PPC_VECTOR_STATE:
721
722 if (clgn < PPC_VECTOR_STATE_COUNT) { /* Is it too short? */
723 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
724 }
725
726 break;
727
728 default:
729 return KERN_INVALID_ARGUMENT;
730 }
731
732 genuser = get_user_regs(thread); /* Find or allocate and initialize one */
733
734 switch (flavor) {
735
736 case PPC_THREAD_STATE:
737
738 ts = (struct ppc_thread_state *)tstate;
739
740 genuser->save_r0 = (uint64_t)ts->r0;
741 genuser->save_r1 = (uint64_t)ts->r1;
742 genuser->save_r2 = (uint64_t)ts->r2;
743 genuser->save_r3 = (uint64_t)ts->r3;
744 genuser->save_r4 = (uint64_t)ts->r4;
745 genuser->save_r5 = (uint64_t)ts->r5;
746 genuser->save_r6 = (uint64_t)ts->r6;
747 genuser->save_r7 = (uint64_t)ts->r7;
748 genuser->save_r8 = (uint64_t)ts->r8;
749 genuser->save_r9 = (uint64_t)ts->r9;
750 genuser->save_r10 = (uint64_t)ts->r10;
751 genuser->save_r11 = (uint64_t)ts->r11;
752 genuser->save_r12 = (uint64_t)ts->r12;
753 genuser->save_r13 = (uint64_t)ts->r13;
754 genuser->save_r14 = (uint64_t)ts->r14;
755 genuser->save_r15 = (uint64_t)ts->r15;
756 genuser->save_r16 = (uint64_t)ts->r16;
757 genuser->save_r17 = (uint64_t)ts->r17;
758 genuser->save_r18 = (uint64_t)ts->r18;
759 genuser->save_r19 = (uint64_t)ts->r19;
760 genuser->save_r20 = (uint64_t)ts->r20;
761 genuser->save_r21 = (uint64_t)ts->r21;
762 genuser->save_r22 = (uint64_t)ts->r22;
763 genuser->save_r23 = (uint64_t)ts->r23;
764 genuser->save_r24 = (uint64_t)ts->r24;
765 genuser->save_r25 = (uint64_t)ts->r25;
766 genuser->save_r26 = (uint64_t)ts->r26;
767 genuser->save_r27 = (uint64_t)ts->r27;
768 genuser->save_r28 = (uint64_t)ts->r28;
769 genuser->save_r29 = (uint64_t)ts->r29;
770 genuser->save_r30 = (uint64_t)ts->r30;
771 genuser->save_r31 = (uint64_t)ts->r31;
772
773 genuser->save_cr = ts->cr;
774 genuser->save_xer = (uint64_t)ts->xer;
775 genuser->save_lr = (uint64_t)ts->lr;
776 genuser->save_ctr = (uint64_t)ts->ctr;
777 genuser->save_srr0 = (uint64_t)ts->srr0;
778 genuser->save_vrsave = ts->vrsave; /* VRSAVE register (Altivec only) */
779
780 genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, ts->srr1); /* Set the bits we can change */
781
782 genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
783
784 genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make sure we don't enable the floating point unit */
785
786 if(task_has_64BitAddr(thread->task))
787 genuser->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32; /* If 64-bit task, force 64-bit mode */
788 else
789 genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32); /* else 32-bit mode */
790
791 return KERN_SUCCESS;
792
793
794 case PPC_THREAD_STATE64:
795
796 xts = (struct ppc_thread_state64 *)tstate;
797
798 genuser->save_r0 = xts->r0;
799 genuser->save_r1 = xts->r1;
800 genuser->save_r2 = xts->r2;
801 genuser->save_r3 = xts->r3;
802 genuser->save_r4 = xts->r4;
803 genuser->save_r5 = xts->r5;
804 genuser->save_r6 = xts->r6;
805 genuser->save_r7 = xts->r7;
806 genuser->save_r8 = xts->r8;
807 genuser->save_r9 = xts->r9;
808 genuser->save_r10 = xts->r10;
809 genuser->save_r11 = xts->r11;
810 genuser->save_r12 = xts->r12;
811 genuser->save_r13 = xts->r13;
812 genuser->save_r14 = xts->r14;
813 genuser->save_r15 = xts->r15;
814 genuser->save_r16 = xts->r16;
815 genuser->save_r17 = xts->r17;
816 genuser->save_r18 = xts->r18;
817 genuser->save_r19 = xts->r19;
818 genuser->save_r20 = xts->r20;
819 genuser->save_r21 = xts->r21;
820 genuser->save_r22 = xts->r22;
821 genuser->save_r23 = xts->r23;
822 genuser->save_r24 = xts->r24;
823 genuser->save_r25 = xts->r25;
824 genuser->save_r26 = xts->r26;
825 genuser->save_r27 = xts->r27;
826 genuser->save_r28 = xts->r28;
827 genuser->save_r29 = xts->r29;
828 genuser->save_r30 = xts->r30;
829 genuser->save_r31 = xts->r31;
830
831 genuser->save_cr = xts->cr;
832 genuser->save_xer = xts->xer;
833 genuser->save_lr = xts->lr;
834 genuser->save_ctr = xts->ctr;
835 genuser->save_srr0 = xts->srr0;
836 genuser->save_vrsave = xts->vrsave; /* VRSAVE register (Altivec only) */
837
838 genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, xts->srr1); /* Set the bits we can change */
839
840 genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
841
842 genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make sure we don't enable the floating point unit */
843
844 if(task_has_64BitAddr(thread->task))
845 genuser->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32; /* If 64-bit task, force 64-bit mode */
846 else
847 genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32); /* else 32-bit mode */
848
849 return KERN_SUCCESS;
850
851
852 case PPC_EXCEPTION_STATE:
853
854 es = (struct ppc_exception_state *) tstate;
855
856 genuser->save_dar = (uint64_t)es->dar;
857 genuser->save_dsisr = es->dsisr;
858 genuser->save_exception = es->exception;
859
860 return KERN_SUCCESS;
861
862 /*
863 * It's pretty worthless to try to change this stuff, but we'll do it anyway.
864 */
865
866 case PPC_EXCEPTION_STATE64:
867
868 xes = (struct ppc_exception_state *) tstate;
869
870 genuser->save_dar = xes->dar;
871 genuser->save_dsisr = xes->dsisr;
872 genuser->save_exception = xes->exception;
873
874 return KERN_SUCCESS;
875
876 case PPC_FLOAT_STATE:
877
878 toss_live_fpu(thread->machine.curctx); /* Toss my floating point if live anywhere */
879
880 fsv = find_user_fpu(thread); /* Get the user's floating point context */
881
882 if(!fsv) { /* Do we have one yet? */
883 fsv = (savearea_fpu *)save_alloc(); /* If we still don't have one, get a new one */
884 fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft); /* Mark as in use as float */
885 fsv->save_hdr.save_act = thread;
886 fsv->save_hdr.save_prev = 0; /* Mark no more */
887 fsv->save_hdr.save_level = 0; /* Mark user state */
888
889 if(!thread->machine.curctx->FPUsave) thread->machine.curctx->FPUsave = fsv; /* If no floating point, chain us first */
890 else {
891
892 fsvn = fsvo = thread->machine.curctx->FPUsave; /* Remember first one */
893
894 while (fsvn) { /* Go until we hit the end */
895 fsvo = fsvn; /* Remember the previous one */
896 fsvn = CAST_DOWN(savearea_fpu *, fsvo->save_hdr.save_prev); /* Skip on to the next */
897 }
898
899 fsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv); /* Queue us on in */
900 }
901
902 }
903
904 fs = (struct ppc_float_state *) tstate; /* Point to source */
905
906
907 bcopy((char *)fs, (char *)&fsv->save_fp0, 32*8); /* Move in the 32 registers */
908
909 genuser->save_fpscr = fs->fpscr; /* Copy the fpscr value to normal */
910
911 return KERN_SUCCESS;
912
913
914 case PPC_VECTOR_STATE:
915
916 toss_live_vec(thread->machine.curctx); /* Toss my vector if live anywhere */
917
918 vsv = find_user_vec(thread); /* Get the user's vector context */
919
920 if(!vsv) { /* Do we have one yet? */
921 vsv = (savearea_vec *)save_alloc(); /* If we still don't have one, get a new one */
922 vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft); /* Mark as in use as vector */
923 vsv->save_hdr.save_act = thread;
924 vsv->save_hdr.save_prev = 0; /* Mark no more */
925 vsv->save_hdr.save_level = 0; /* Mark user state */
926
927 if(!thread->machine.curctx->VMXsave) thread->machine.curctx->VMXsave = vsv; /* If no vector, chain us first */
928 else {
929
930 vsvn = vsvo = thread->machine.curctx->VMXsave; /* Remember first one */
931
932 while (vsvn) { /* Go until we hit the end */
933 vsvo = vsvn; /* Remember the previous one */
934 vsvn = CAST_DOWN(savearea_vec *, vsvo->save_hdr.save_prev); /* Skip on to the next */
935 }
936
937 vsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv); /* Queue us on in */
938 }
939
940 }
941
942 vs = (struct ppc_vector_state *) tstate; /* Point to source */
943
944 bcopy((char *)vs, (char *)&vsv->save_vr0, 32*16); /* 32 registers plus status and validity and pad */
945 vsv->save_vrvalid = vs->save_vrvalid; /* Set validity bits */
946
947
948 for(i = 0; i < 4; i++) genuser->save_vscr[i] = vs->save_vscr[i]; /* Set value for vscr */
949
950 return KERN_SUCCESS;
951
952
953 default:
954 return KERN_INVALID_ARGUMENT;
955 }
956 }
957
958
959 /*
960 * This is where registers that are not normally specified by the mach-o
961 * file on an execve should be nullified, perhaps to avoid a covert channel.
962 * We've never bothered to clear FPRs or VRs, but it is important to clear
963 * the FPSCR, which is kept in the general state but not set by the general
964 * flavor (ie, PPC_THREAD_STATE or PPC_THREAD_STATE64.)
965 */
966 kern_return_t
967 machine_thread_state_initialize(
968 thread_t thread)
969 {
970 savearea *sv;
971
972 sv = get_user_regs(thread); /* Find or allocate and initialize one */
973
974 sv->save_fpscr = 0; /* Clear all floating point exceptions */
975 sv->save_vrsave = 0; /* Set the vector save state */
976 sv->save_vscr[0] = 0x00000000;
977 sv->save_vscr[1] = 0x00000000;
978 sv->save_vscr[2] = 0x00000000;
979 sv->save_vscr[3] = 0x00010000; /* Disable java mode and clear saturated */
980
981 return KERN_SUCCESS;
982 }
983
984
985 /*
986 * Duplicates the context of one thread into a new one.
987 * The new thread is assumed to be new and have no user state contexts except maybe a general one.
988 * We also assume that the old thread can't be running anywhere.
989 *
990 * We're only going to be duplicating user context here. That means that we will have to
991 * eliminate any floating point or vector kernel contexts and carry across the user state ones.
992 */
993
994 kern_return_t
995 machine_thread_dup(
996 thread_t self,
997 thread_t target)
998 {
999 savearea *sv, *osv;
1000 savearea_fpu *fsv, *fsvn;
1001 savearea_vec *vsv, *vsvn;
1002
1003 fpu_save(self->machine.curctx); /* Make certain floating point state is all saved */
1004 vec_save(self->machine.curctx); /* Make certain the vector state is all saved */
1005
1006 sv = get_user_regs(target); /* Allocate and initialze context in the new activation */
1007
1008 osv = find_user_regs(self); /* Find the original context */
1009 if(!osv)
1010 return (KERN_FAILURE);
1011
1012 bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)), /* Copy everything but the headers */
1013 (char *)((unsigned int)sv + sizeof(savearea_comm)),
1014 sizeof(struct savearea) - sizeof(savearea_comm));
1015
1016 sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC))); /* Make certain that floating point and vector are turned off */
1017
1018 fsv = find_user_fpu(self); /* Get any user floating point */
1019
1020 target->machine.curctx->FPUsave = 0; /* Assume no floating point */
1021
1022 if(fsv) { /* Did we find one? */
1023 fsvn = (savearea_fpu *)save_alloc(); /* If we still don't have one, get a new one */
1024 fsvn->save_hdr.save_flags = (fsvn->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft); /* Mark as in use as float */
1025 fsvn->save_hdr.save_act = target;
1026 fsvn->save_hdr.save_prev = 0; /* Mark no more */
1027 fsvn->save_hdr.save_level = 0; /* Mark user state */
1028
1029 target->machine.curctx->FPUsave = fsvn; /* Chain in the floating point */
1030
1031 bcopy((char *)((unsigned int)fsv + sizeof(savearea_comm)), /* Copy everything but the headers */
1032 (char *)((unsigned int)fsvn + sizeof(savearea_comm)),
1033 sizeof(struct savearea) - sizeof(savearea_comm));
1034 }
1035
1036 vsv = find_user_vec(self); /* Get any user vector */
1037
1038 target->machine.curctx->VMXsave = 0; /* Assume no vector */
1039
1040 if(vsv) { /* Did we find one? */
1041 vsvn = (savearea_vec *)save_alloc(); /* If we still don't have one, get a new one */
1042 vsvn->save_hdr.save_flags = (vsvn->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft); /* Mark as in use as float */
1043 vsvn->save_hdr.save_act = target;
1044 vsvn->save_hdr.save_prev = 0; /* Mark no more */
1045 vsvn->save_hdr.save_level = 0; /* Mark user state */
1046
1047 target->machine.curctx->VMXsave = vsvn; /* Chain in the floating point */
1048
1049 bcopy((char *)((unsigned int)vsv + sizeof(savearea_comm)), /* Copy everything but the headers */
1050 (char *)((unsigned int)vsvn + sizeof(savearea_comm)),
1051 sizeof(struct savearea) - sizeof(savearea_comm));
1052 }
1053
1054 return (KERN_SUCCESS);
1055 }
1056
1057 /*
1058 * Initializes a fresh set of user state values. If there is no user state context,
1059 * one is created. Floats and VMX are not created.
1060 *
1061 * We only set initial values if there was no context found.
1062 */
1063
1064 savearea *
1065 get_user_regs(
1066 thread_t thread)
1067 {
1068 savearea *sv, *osv;
1069 unsigned int i;
1070
1071 if (thread->machine.upcb)
1072 return thread->machine.upcb;
1073
1074 sv = thread->machine.pcb; /* Get the top savearea on the stack */
1075 osv = 0; /* Set no user savearea yet */
1076
1077 while(sv) { /* Find the user context */
1078 osv = sv; /* Save the last one */
1079 sv = CAST_DOWN(savearea *, sv->save_hdr.save_prev); /* Get the previous context */
1080 }
1081
1082 sv = save_alloc(); /* Get one */
1083 sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft); /* Mark as in use as general */
1084 sv->save_hdr.save_act = thread;
1085 sv->save_hdr.save_prev = 0; /* Mark no more */
1086 sv->save_hdr.save_level = 0; /* Mark user state */
1087
1088 if(osv) { /* Did we already have one? */
1089 osv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv); /* Chain us on the end */
1090 }
1091 else { /* We are the first */
1092 thread->machine.pcb = sv; /* Put it there */
1093 }
1094 thread->machine.upcb = sv; /* Set user pcb */
1095
1096 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
1097 ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
1098 ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
1099 }
1100 sv->save_cr = 0;
1101 sv->save_xer = 0;
1102 sv->save_lr = (uint64_t)FloatInit;
1103 sv->save_ctr = (uint64_t)FloatInit;
1104 sv->save_srr0 = (uint64_t)FloatInit;
1105 sv->save_srr1 = (uint64_t)MSR_EXPORT_MASK_SET;
1106 if(task_has_64BitAddr(thread->task))
1107 sv->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32; /* If 64-bit task, force 64-bit mode */
1108
1109 sv->save_fpscr = 0; /* Clear all floating point exceptions */
1110
1111 sv->save_vrsave = 0; /* Set the vector save state */
1112 sv->save_vscr[0] = 0x00000000;
1113 sv->save_vscr[1] = 0x00000000;
1114 sv->save_vscr[2] = 0x00000000;
1115 sv->save_vscr[3] = 0x00010000; /* Disable java mode and clear saturated */
1116
1117 return sv; /* Bye bye... */
1118 }
1119
1120 /*
1121 * Find the user state context. If there is no user state context,
1122 * we just return a 0.
1123 */
1124
1125 savearea *
1126 find_user_regs(
1127 thread_t thread)
1128 {
1129 return thread->machine.upcb;
1130 }
1131
1132 /* The name of this call is something of a misnomer since the mact.pcb can
1133 * contain chained saveareas, but it will do for now..
1134 */
1135 savearea *
1136 find_kern_regs(
1137 thread_t thread)
1138 {
1139 return thread->machine.pcb;
1140 }
1141
1142 /*
1143 * Find the user state floating point context. If there is no user state context,
1144 * we just return a 0.
1145 */
1146
1147 savearea_fpu *
1148 find_user_fpu(
1149 thread_t thread)
1150 {
1151 savearea_fpu *fsv;
1152 boolean_t intr;
1153
1154 intr = ml_set_interrupts_enabled(FALSE);
1155 fsv = thread->machine.curctx->FPUsave; /* Get the start of the floating point chain */
1156
1157 while(fsv) { /* Look until the end or we find it */
1158 if(!(fsv->save_hdr.save_level)) break; /* Is the the user state stuff? (the level is 0 if so) */
1159 fsv = CAST_DOWN(savearea_fpu *, fsv->save_hdr.save_prev); /* Try the previous one */
1160 }
1161 (void) ml_set_interrupts_enabled(intr);
1162
1163 return fsv; /* Bye bye... */
1164 }
1165
1166 /*
1167 * Find the user state vector context. If there is no user state context,
1168 * we just return a 0.
1169 */
1170
1171 savearea_vec *
1172 find_user_vec(
1173 thread_t thread)
1174 {
1175 savearea_vec *vsv;
1176 boolean_t intr;
1177
1178 intr = ml_set_interrupts_enabled(FALSE);
1179 vsv = thread->machine.curctx->VMXsave; /* Get the start of the vector chain */
1180
1181 while(vsv) { /* Look until the end or we find it */
1182 if(!(vsv->save_hdr.save_level)) break; /* Is the the user state stuff? (the level is 0 if so) */
1183 vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev); /* Try the previous one */
1184 }
1185 (void) ml_set_interrupts_enabled(intr);
1186
1187 return vsv; /* Bye bye... */
1188 }
1189 /*
1190 * Find the user state vector context for the current thread. If there is no user state context,
1191 * we just return a 0.
1192 */
1193
1194 savearea_vec *find_user_vec_curr(void) {
1195
1196 savearea_vec *vsv;
1197 thread_t thread = current_thread();
1198 boolean_t intr;
1199
1200 vec_save(thread->machine.curctx); /* Force save if live */
1201
1202 intr = ml_set_interrupts_enabled(FALSE);
1203 vsv = thread->machine.curctx->VMXsave; /* Get the start of the vector chain */
1204
1205 while(vsv) { /* Look until the end or we find it */
1206 if(!(vsv->save_hdr.save_level)) break; /* Is the the user state stuff? (the level is 0 if so) */
1207 vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev); /* Try the previous one */
1208 }
1209 (void) ml_set_interrupts_enabled(intr);
1210
1211 return vsv; /* Bye bye... */
1212 }
1213
1214 /*
1215 * thread_userstack:
1216 *
1217 * Return the user stack pointer from the machine
1218 * dependent thread state info.
1219 */
1220 kern_return_t
1221 thread_userstack(
1222 __unused thread_t thread,
1223 int flavor,
1224 thread_state_t tstate,
1225 unsigned int count,
1226 mach_vm_offset_t *user_stack,
1227 int *customstack
1228 )
1229 {
1230 /*
1231 * Set a default.
1232 */
1233
1234 switch (flavor) {
1235 case PPC_THREAD_STATE:
1236 {
1237 struct ppc_thread_state *state;
1238
1239 if (count < PPC_THREAD_STATE_COUNT)
1240 return (KERN_INVALID_ARGUMENT);
1241
1242 state = (struct ppc_thread_state *) tstate;
1243
1244 /*
1245 * If a valid user stack is specified, use it.
1246 */
1247 if (state->r1) {
1248 *user_stack = CAST_USER_ADDR_T(state->r1);
1249 if (customstack)
1250 *customstack = 1;
1251 } else {
1252 *user_stack = CAST_USER_ADDR_T(USRSTACK);
1253 if (customstack)
1254 *customstack = 0;
1255 }
1256 }
1257 break;
1258
1259 case PPC_THREAD_STATE64:
1260 {
1261 struct ppc_thread_state64 *state64;
1262
1263 if (count < PPC_THREAD_STATE64_COUNT)
1264 return (KERN_INVALID_ARGUMENT);
1265
1266 state64 = (struct ppc_thread_state64 *)tstate;
1267
1268 /*
1269 * If a valid user stack is specified, use it.
1270 */
1271 if (state64->r1 != MACH_VM_MIN_ADDRESS) {
1272 *user_stack = state64->r1;
1273 if (customstack)
1274 *customstack = 1;
1275 } else {
1276 *user_stack = USRSTACK64;
1277 if (customstack)
1278 *customstack = 0;
1279 }
1280 }
1281 break;
1282
1283 default :
1284 return (KERN_INVALID_ARGUMENT);
1285 }
1286
1287 return (KERN_SUCCESS);
1288 }
1289
1290
1291 /*
1292 * thread_setuserstack:
1293 *
1294 * Sets the user stack pointer into the machine
1295 * dependent thread state info.
1296 */
1297 void
1298 thread_setuserstack(thread_t thread, mach_vm_address_t user_stack)
1299 {
1300 savearea *sv;
1301
1302 sv = get_user_regs(thread); /* Get the user state registers */
1303
1304 sv->save_r1 = user_stack;
1305
1306 return;
1307 }
1308
1309 /*
1310 * thread_adjuserstack:
1311 *
1312 * Returns the adjusted user stack pointer from the machine
1313 * dependent thread state info. Usef for small (<2G) deltas.
1314 */
1315 uint64_t
1316 thread_adjuserstack(thread_t thread, int adjust)
1317 {
1318 savearea *sv;
1319
1320 sv = get_user_regs(thread); /* Get the user state registers */
1321
1322 sv->save_r1 += adjust; /* Adjust the stack */
1323
1324 return sv->save_r1; /* Return the adjusted stack */
1325
1326 }
1327
1328 /*
1329 * thread_setentrypoint:
1330 *
1331 * Sets the user PC into the machine
1332 * dependent thread state info.
1333 */
1334
1335 void
1336 thread_setentrypoint(thread_t thread, uint64_t entry)
1337 {
1338 savearea *sv;
1339
1340 sv = get_user_regs(thread); /* Get the user state registers */
1341
1342 sv->save_srr0 = entry;
1343
1344 return;
1345 }
1346
1347 kern_return_t
1348 thread_entrypoint(
1349 __unused thread_t thread,
1350 int flavor,
1351 thread_state_t tstate,
1352 unsigned int count,
1353 mach_vm_offset_t *entry_point
1354 )
1355 {
1356 #if 0
1357 /* Silly code: "if *entry_point is 0, make it 0" */
1358 /*
1359 * Set a default.
1360 */
1361 if (*entry_point == 0ULL)
1362 *entry_point = MACH_VM_MIN_ADDRESS;
1363 #endif
1364
1365 switch (flavor) {
1366 case PPC_THREAD_STATE:
1367 {
1368 struct ppc_thread_state *state;
1369
1370 if (count < PPC_THREAD_STATE_COUNT)
1371 return (KERN_INVALID_ARGUMENT);
1372
1373 state = (struct ppc_thread_state *) tstate;
1374
1375 /*
1376 * If a valid entry point is specified, use it.
1377 */
1378 if (state->srr0) {
1379 *entry_point = CAST_USER_ADDR_T(state->srr0);
1380 } else {
1381 *entry_point = CAST_USER_ADDR_T(VM_MIN_ADDRESS);
1382 }
1383 }
1384 break;
1385
1386 case PPC_THREAD_STATE64:
1387 {
1388 struct ppc_thread_state64 *state64;
1389
1390 if (count < PPC_THREAD_STATE_COUNT)
1391 return (KERN_INVALID_ARGUMENT);
1392
1393 state64 = (struct ppc_thread_state64 *)tstate;
1394
1395 /*
1396 * If a valid entry point is specified, use it.
1397 */
1398 if (state64->srr0) {
1399 *entry_point = state64->srr0;
1400 } else {
1401 *entry_point = MACH_VM_MIN_ADDRESS;
1402 }
1403 }
1404 break;
1405
1406 default:
1407 return (KERN_INVALID_ARGUMENT);
1408 }
1409
1410 return (KERN_SUCCESS);
1411 }
1412
1413 unsigned int get_msr_exportmask(void)
1414 {
1415 return (MSR_EXPORT_MASK_SET);
1416 }
1417
1418 unsigned int get_msr_nbits(void)
1419 {
1420 return (MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1421 }
1422 unsigned int get_msr_rbits(void)
1423 {
1424 return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1425 }
1426
1427 void ppc_checkthreadstate(void * tsptr, int flavor)
1428 {
1429 if (flavor == PPC_THREAD_STATE64) {
1430 struct ppc_thread_state64 *ts64 =(struct ppc_thread_state64 *)tsptr;
1431
1432 /* Make sure naughty bits are off and necessary bits are on */
1433 ts64->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1434 ts64->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1435 } else {
1436 struct ppc_thread_state *ts =(struct ppc_thread_state *)tsptr;
1437
1438 /* Make sure naughty bits are off and necessary bits are on */
1439 ts->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1440 ts->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1441 }
1442 return;
1443 }
1444
1445 void
1446 thread_set_child(
1447 thread_t child,
1448 int pid)
1449 {
1450 struct savearea *child_state;
1451
1452 child_state = get_user_regs(child);
1453
1454 child_state->save_r3 = (uint_t)pid;
1455 child_state->save_r4 = 1ULL;
1456 }
1457 void
1458 thread_set_parent(
1459 thread_t parent,
1460 int pid)
1461 {
1462 struct savearea *parent_state;
1463
1464 parent_state = get_user_regs(parent);
1465
1466 parent_state->save_r3 = (uint64_t)pid;
1467 parent_state->save_r4 = 0;
1468 }
1469
1470 /*
1471 * Saves the complete context (general, floating point, and vector) of the current activation.
1472 * We will collect everything into an opaque block of 1 to 3 saveareas and pass back a
1473 * pointer to that.
1474 *
1475 * The savearea is made to look like it belongs to the source activation. This needs to
1476 * be adjusted when these contexts are attached to a new activation.
1477 *
1478 */
1479
1480 void *act_thread_csave(void) {
1481
1482 savearea *sv, *osv;
1483 savearea_fpu *fsv, *ofsv;
1484 savearea_vec *vsv, *ovsv;
1485
1486 thread_t thread;
1487
1488 thread = current_thread();
1489
1490 fpu_save(thread->machine.curctx); /* Make certain floating point state is all saved */
1491 vec_save(thread->machine.curctx); /* Make certain the vector state is all saved */
1492
1493 osv = find_user_regs(thread); /* Get our savearea */
1494
1495 if(!osv) {
1496 panic("act_thread_csave: attempting to preserve the context of an activation with none (%08X)\n", thread);
1497 }
1498
1499 sv = save_alloc(); /* Get a fresh save area to save into */
1500 sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft); /* Mark as in use as general */
1501 sv->save_hdr.save_act = thread;
1502 sv->save_hdr.save_prev = 0; /* Mark no more */
1503 sv->save_hdr.save_level = 0; /* Mark user state */
1504
1505
1506 bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)), /* Copy everything but the headers */
1507 (char *)((unsigned int)sv + sizeof(savearea_comm)),
1508 sizeof(struct savearea) - sizeof(savearea_comm));
1509
1510 sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC))); /* Make certain that floating point and vector are turned off */
1511
1512 sv->save_hdr.save_misc2 = 0xDEBB1ED0; /* Eye catcher for debug */
1513 sv->save_hdr.save_misc3 = 0xE5DA11A5; /* Eye catcher for debug */
1514
1515
1516 ofsv = find_user_fpu(thread); /* Get any user floating point */
1517
1518 sv->save_hdr.save_misc0 = 0; /* Assume no floating point */
1519
1520 if(ofsv) { /* Did we find one? */
1521 fsv = (savearea_fpu *)save_alloc(); /* If we still don't have one, get a new one */
1522 fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft); /* Mark as in use as float */
1523 fsv->save_hdr.save_act = thread;
1524 fsv->save_hdr.save_prev = 0; /* Mark no more */
1525 fsv->save_hdr.save_level = 0; /* Mark user state */
1526 fsv->save_hdr.save_misc2 = 0xDEBB1ED0; /* Eye catcher for debug */
1527 fsv->save_hdr.save_misc3 = 0xE5DA11A5; /* Eye catcher for debug */
1528
1529 sv->save_hdr.save_misc0 = (uint64_t)((uintptr_t)fsv); /* Remember this one */
1530
1531 bcopy((char *)((unsigned int)ofsv + sizeof(savearea_comm)), /* Copy everything but the headers */
1532 (char *)((unsigned int)fsv + sizeof(savearea_comm)),
1533 sizeof(struct savearea) - sizeof(savearea_comm));
1534 }
1535
1536 ovsv = find_user_vec(thread); /* Get any user vector */
1537
1538 sv->save_hdr.save_misc1 = 0; /* Assume no vector */
1539
1540 if(ovsv) { /* Did we find one? */
1541 vsv = (savearea_vec *)save_alloc(); /* If we still don't have one, get a new one */
1542 vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft); /* Mark as in use as float */
1543 vsv->save_hdr.save_act = thread;
1544 vsv->save_hdr.save_prev = 0; /* Mark no more */
1545 vsv->save_hdr.save_level = 0; /* Mark user state */
1546 vsv->save_hdr.save_misc2 = 0xDEBB1ED0; /* Eye catcher for debug */
1547 vsv->save_hdr.save_misc3 = 0xE5DA11A5; /* Eye catcher for debug */
1548
1549 sv->save_hdr.save_misc1 = (uint64_t)((uintptr_t)vsv); /* Chain in the floating point */
1550
1551 bcopy((char *)((unsigned int)ovsv + sizeof(savearea_comm)), /* Copy everything but the headers */
1552 (char *)((unsigned int)vsv + sizeof(savearea_comm)),
1553 sizeof(struct savearea) - sizeof(savearea_comm));
1554 }
1555
1556 return (void *)sv; /* Bye bye... */
1557 }
1558
1559
1560
1561 /*
1562 * Attaches saved user state context to an activation. We will replace any
1563 * user state context with what is passed in. The saved context consists of a
1564 * savearea that was setup by
1565 * We will collect everything into one savearea and pass that back.
1566 *
1567 * The savearea is made to look like it belongs to the source activation. This needs to
1568 * be adjusted when these contexts are attached to a new activation.
1569 *
1570 */
1571
1572 void act_thread_catt(void *ctx) {
1573
1574 savearea *sv, *osv, *psv;
1575 savearea_fpu *fsv, *ofsv, *pfsv;
1576 savearea_vec *vsv, *ovsv, *pvsv;
1577 unsigned int spc;
1578 thread_t thread;
1579
1580 sv = (savearea *)ctx; /* Make this easier for C */
1581
1582 fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0); /* Get a possible floating point savearea */
1583 vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1); /* Get a possible vector savearea */
1584
1585 if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1586 panic("act_thread_catt: attempt to attach invalid general context savearea - %08X\n", sv); /* Die */
1587 }
1588
1589 if(fsv && ((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5))) { /* See if valid savearea */
1590 panic("act_thread_catt: attempt to attach invalid float context savearea - %08X\n", fsv); /* Die */
1591 }
1592
1593 if(vsv && ((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5))) { /* See if valid savearea */
1594 panic("act_thread_catt: attempt to attach invalid vector context savearea - %08X\n", vsv); /* Die */
1595 }
1596
1597 thread = current_thread();
1598
1599 act_machine_sv_free(thread); /* Blow away any current kernel FP or vector.
1600 We do not support those across a vfork */
1601 toss_live_fpu(thread->machine.curctx); /* Toss my floating point if live anywhere */
1602 toss_live_vec(thread->machine.curctx); /* Toss my vector if live anywhere */
1603
1604 sv->save_hdr.save_misc2 = 0; /* Eye catcher for debug */
1605 sv->save_hdr.save_misc3 = 0; /* Eye catcher for debug */
1606 sv->save_hdr.save_act = thread;
1607
1608 spc = (unsigned int)thread->map->pmap->space; /* Get the space we're in */
1609
1610 osv = thread->machine.pcb; /* Get the top general savearea */
1611 psv = 0;
1612 while(osv) { /* Any saved state? */
1613 if(osv->save_srr1 & MASK(MSR_PR)) break; /* Leave if this is user state */
1614 psv = osv; /* Save previous savearea address */
1615 osv = CAST_DOWN(savearea *, osv->save_hdr.save_prev); /* Get one underneath our's */
1616 }
1617
1618 if(osv) { /* Did we find one? */
1619 if(psv) psv->save_hdr.save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */
1620 else thread->machine.pcb = 0; /* to the start if the only one */
1621
1622 save_release(osv); /* Nope, release it */
1623
1624 }
1625
1626 if(psv) psv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv); /* Chain us to the end or */
1627 else thread->machine.pcb = (pcb_t)sv; /* to the start if the only one */
1628 thread->machine.upcb = (pcb_t)sv; /* Set the user pcb */
1629
1630 ovsv = thread->machine.curctx->VMXsave; /* Get the top vector savearea */
1631
1632 pvsv = 0;
1633 while(ovsv) { /* Any VMX saved state? */
1634 if(!(ovsv->save_hdr.save_level)) break; /* Leave if this is user state */
1635 pvsv = ovsv; /* Save previous savearea address */
1636 ovsv = CAST_DOWN(savearea_vec *, ovsv->save_hdr.save_prev); /* Get one underneath our's */
1637 }
1638
1639 if(ovsv) { /* Did we find one? */
1640 if(pvsv) pvsv->save_hdr.save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */
1641 else thread->machine.curctx->VMXsave = 0; /* to the start if the only one */
1642
1643 save_release((savearea *)ovsv); /* Nope, release it */
1644 }
1645
1646 if(vsv) { /* Are we sticking any vector on this one? */
1647 if(pvsv) pvsv->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv); /* Yes, chain us to the end or */
1648 else {
1649 thread->machine.curctx->VMXsave = vsv; /* to the start if the only one */
1650 thread->machine.curctx->VMXlevel = 0; /* Insure that we don't have a leftover level */
1651 }
1652
1653 vsv->save_hdr.save_misc2 = 0; /* Eye catcher for debug */
1654 vsv->save_hdr.save_misc3 = 0; /* Eye catcher for debug */
1655 vsv->save_hdr.save_act = thread;
1656 }
1657
1658 ofsv = thread->machine.curctx->FPUsave; /* Get the top float savearea */
1659
1660 pfsv = 0;
1661 while(ofsv) { /* Any float saved state? */
1662 if(!(ofsv->save_hdr.save_level)) break; /* Leave if this is user state */
1663 pfsv = ofsv; /* Save previous savearea address */
1664 ofsv = CAST_DOWN(savearea_fpu *, ofsv->save_hdr.save_prev); /* Get one underneath our's */
1665 }
1666
1667 if(ofsv) { /* Did we find one? */
1668 if(pfsv) pfsv->save_hdr.save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */
1669 else thread->machine.curctx->FPUsave = 0; /* to the start if the only one */
1670
1671 save_release((savearea *)ofsv); /* Nope, release it */
1672 }
1673
1674 if(fsv) { /* Are we sticking any vector on this one? */
1675 if(pfsv) pfsv->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv); /* Yes, chain us to the end or */
1676 else {
1677 thread->machine.curctx->FPUsave = fsv; /* to the start if the only one */
1678 thread->machine.curctx->FPUlevel = 0; /* Insure that we don't have a leftover level */
1679 }
1680
1681 fsv->save_hdr.save_misc2 = 0; /* Eye catcher for debug */
1682 fsv->save_hdr.save_misc3 = 0; /* Eye catcher for debug */
1683 fsv->save_hdr.save_act = thread;
1684 }
1685
1686 }
1687
1688
1689
1690 /*
1691 * Releases saved context. We need this because the saved context is opague.
1692 * be adjusted when these contexts are attached to a new activation.
1693 *
1694 */
1695
1696 void
1697 act_thread_cfree(void *ctx)
1698 {
1699
1700 savearea *sv;
1701 savearea_fpu *fsv;
1702 savearea_vec *vsv;
1703
1704 sv = (savearea *)ctx; /* Make this easier for C */
1705
1706 fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0); /* Get a possible floating point savearea */
1707 vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1); /* Get a possible vector savearea */
1708
1709 if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1710 panic("act_thread_cfree: attempt to detatch invalid general context savearea - %08X\n", sv); /* Die */
1711 }
1712
1713 save_release(sv); /* Toss the general savearea */
1714
1715 if(fsv) { /* See if there is any saved floating point */
1716 if((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1717 panic("act_thread_cfree: attempt to detatch invalid float context savearea - %08X\n", fsv); /* Die */
1718 }
1719
1720 save_release((savearea *)fsv); /* Toss saved context */
1721 }
1722
1723 if(vsv) { /* See if there is any saved floating point */
1724 if((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1725 panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %08X\n", vsv); /* Die */
1726 }
1727
1728 save_release((savearea *)vsv); /* Toss saved context */
1729 }
1730
1731 return;
1732 }
1733
1734 /*
1735 * thread_enable_fpe:
1736 *
1737 * enables or disables floating point exceptions for the thread.
1738 * returns old state
1739 */
1740 int thread_enable_fpe(
1741 thread_t thread,
1742 int onoff)
1743 {
1744 savearea *sv;
1745 uint64_t oldmsr;
1746
1747 sv = find_user_regs(thread); /* Find the user registers */
1748 if(!sv) sv = get_user_regs(thread); /* Didn't find any, allocate and initialize one */
1749
1750 oldmsr = sv->save_srr1; /* Get the old msr */
1751
1752 if(onoff) sv->save_srr1 = oldmsr | (uint64_t)(MASK(MSR_FE0) | MASK(MSR_FE1)); /* Flip on precise FP exceptions */
1753 else sv->save_srr1 = oldmsr & (uint64_t)(~(MASK(MSR_FE0) | MASK(MSR_FE1))); /* Flip on precise FP exceptions */
1754
1755 return ((oldmsr & (MASK(MSR_FE0) | MASK(MSR_FE1))) != 0); /* Return if it was enabled or not */
1756 }