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