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