]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/status.c
xnu-792.2.4.tar.gz
[apple/xnu.git] / osfmk / ppc / status.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
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.
1c79356b 11 *
e5568f75
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
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.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 *
25 */
26
27#include <kern/thread.h>
1c79356b
A
28#include <kern/misc_protos.h>
29#include <mach/ppc/thread_status.h>
30#include <ppc/proc_reg.h>
91447636 31#include <ppc/cpu_internal.h>
1c79356b 32#include <ppc/exception.h>
1c79356b
A
33#include <ppc/misc_protos.h>
34#include <ppc/savearea.h>
91447636 35#include <ppc/thread.h>
1c79356b
A
36#include <ppc/Firmware.h>
37
91447636
A
38//#include <sys/time.h>
39typedef unsigned int fixpt_t; /* XXX <sys/resource.h> not self contained */
40#include <ppc/vmparam.h> /* USRSTACK, etc. */
41
1c79356b
A
42#include <vm/vm_map.h>
43
44extern unsigned int killprint;
45extern double FloatInit;
46extern unsigned long QNaNbarbarian[4];
1c79356b 47
55e303ae
A
48#define USRSTACK 0xc0000000
49
1c79356b
A
50kern_return_t
51thread_userstack(
52 thread_t,
53 int,
54 thread_state_t,
55 unsigned int,
91447636 56 mach_vm_offset_t *,
0b4e3aa0 57 int *
1c79356b
A
58);
59
60kern_return_t
61thread_entrypoint(
62 thread_t,
63 int,
64 thread_state_t,
65 unsigned int,
91447636 66 mach_vm_offset_t *
1c79356b
A
67);
68
69unsigned int get_msr_exportmask(void);
70unsigned int get_msr_nbits(void);
71unsigned int get_msr_rbits(void);
55e303ae 72void ppc_checkthreadstate(void *, int);
91447636
A
73void thread_set_child(thread_t child, int pid);
74void thread_set_parent(thread_t parent, int pid);
75void save_release(struct savearea *save);
1c79356b
A
76
77/*
78 * Maps state flavor to number of words in the state:
79 */
91447636
A
80__private_extern__
81unsigned int _MachineStateCount[] = {
1c79356b
A
82 /* FLAVOR_LIST */ 0,
83 PPC_THREAD_STATE_COUNT,
84 PPC_FLOAT_STATE_COUNT,
85 PPC_EXCEPTION_STATE_COUNT,
55e303ae
A
86 PPC_VECTOR_STATE_COUNT,
87 PPC_THREAD_STATE64_COUNT,
88 PPC_EXCEPTION_STATE64_COUNT,
1c79356b
A
89};
90
91/*
92 * thread_getstatus:
93 *
94 * Get the status of the specified thread.
95 */
96
97kern_return_t
55e303ae 98machine_thread_get_state(
91447636
A
99 thread_t thread,
100 thread_flavor_t flavor,
101 thread_state_t tstate,
102 mach_msg_type_number_t *count)
1c79356b
A
103{
104
105 register struct savearea *sv; /* Pointer to the context savearea */
9bccf70c
A
106 register savearea_fpu *fsv;
107 register savearea_vec *vsv;
108 savearea *genuser;
1c79356b
A
109 int i, j;
110 unsigned int vrvalidwrk;
111
112 register struct ppc_thread_state *ts;
55e303ae 113 register struct ppc_thread_state64 *xts;
1c79356b 114 register struct ppc_exception_state *es;
55e303ae 115 register struct ppc_exception_state64 *xes;
1c79356b
A
116 register struct ppc_float_state *fs;
117 register struct ppc_vector_state *vs;
118
91447636 119 genuser = find_user_regs(thread);
1c79356b
A
120
121 switch (flavor) {
122
123 case THREAD_STATE_FLAVOR_LIST:
124
55e303ae 125 if (*count < 6) {
1c79356b
A
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;
55e303ae
A
132 tstate[3] = PPC_VECTOR_STATE;
133 tstate[4] = PPC_THREAD_STATE64;
134 tstate[5] = PPC_EXCEPTION_STATE64;
135 *count = 6;
1c79356b
A
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
9bccf70c
A
147 sv = genuser; /* Copy this over */
148
1c79356b 149 if(sv) { /* Is there a save area yet? */
55e303ae
A
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;
9bccf70c 188 ts->mq = 0; /* MQ register (601 only) */
55e303ae 189 ts->vrsave = (unsigned int)sv->save_vrsave; /* VRSAVE register (Altivec only) */
1c79356b 190 }
9bccf70c 191 else { /* No user state yet. Save seemingly random values. */
1c79356b 192
9bccf70c 193 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
1c79356b
A
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;
9bccf70c 204 ts->vrsave = 0; /* VRSAVE register (Altivec only) */
1c79356b
A
205 }
206
9bccf70c 207 *count = PPC_THREAD_STATE_COUNT; /* Pass back the amount we actually copied */
1c79356b
A
208 return KERN_SUCCESS;
209
55e303ae
A
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;
91447636
A
273 if(task_has_64BitAddr(thread->task))
274 xts->srr1 |= (uint64_t)MASK32(MSR_SF) << 32; /* If 64-bit task, force 64-bit mode */
55e303ae
A
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
1c79356b
A
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;
55e303ae 288 sv = genuser; /* Copy this over */
1c79356b 289
1c79356b 290 if(sv) { /* See if valid state yet */
55e303ae 291 es->dar = (unsigned int)sv->save_dar;
1c79356b
A
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
55e303ae
A
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
1c79356b
A
327 case PPC_FLOAT_STATE:
328
329 if (*count < PPC_FLOAT_STATE_COUNT) {
330 return KERN_INVALID_ARGUMENT;
331 }
332
91447636 333 fpu_save(thread->machine.curctx); /* Just in case it's live, save it */
1c79356b
A
334
335 fs = (struct ppc_float_state *) tstate; /* Point to destination */
336
91447636 337 fsv = find_user_fpu(thread); /* Get the user's fpu savearea */
1c79356b 338
9bccf70c
A
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 */
1c79356b
A
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
91447636 364 vec_save(thread->machine.curctx); /* Just in case it's live, save it */
1c79356b
A
365
366 vs = (struct ppc_vector_state *) tstate; /* Point to destination */
367
91447636 368 vsv = find_user_vec(thread); /* Find the vector savearea */
1c79356b 369
9bccf70c 370 if(vsv) { /* See if we have any */
1c79356b 371
9bccf70c
A
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;
55e303ae 379 vs->save_vscr[3] = 0x00010000; /* Always start with Java mode off */
9bccf70c 380 }
1c79356b
A
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] =
9bccf70c 384 ((unsigned int *)&(vsv->save_vr0))[(i * 4) + j]; /* We have this register saved */
1c79356b
A
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 }
9bccf70c
A
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;
55e303ae 401 vs->save_vscr[3] = 0x00010000; /* Always start with Java mode off */
9bccf70c 402 }
1c79356b
A
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}
55e303ae
A
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
423kern_return_t
424machine_thread_get_kern_state(
91447636
A
425 thread_t thread,
426 thread_flavor_t flavor,
427 thread_state_t tstate,
428 mach_msg_type_number_t *count)
55e303ae
A
429{
430
431 register struct savearea *sv; /* Pointer to the context savearea */
432 savearea *genkern;
91447636 433 int i;
55e303ae
A
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
91447636 440 genkern = find_kern_regs(thread);
55e303ae
A
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}
1c79356b
A
650
651
652/*
653 * thread_setstatus:
654 *
655 * Set the status of the specified thread.
656 */
657kern_return_t
55e303ae 658machine_thread_set_state(
91447636
A
659 thread_t thread,
660 thread_flavor_t flavor,
661 thread_state_t tstate,
662 mach_msg_type_number_t count)
1c79356b
A
663{
664
91447636 665 savearea *genuser;
9bccf70c
A
666 savearea_fpu *fsv, *fsvn, *fsvo;
667 savearea_vec *vsv, *vsvn, *vsvo;
668 unsigned int i;
91447636 669 unsigned int clgn;
1c79356b 670 register struct ppc_thread_state *ts;
55e303ae 671 register struct ppc_thread_state64 *xts;
1c79356b 672 register struct ppc_exception_state *es;
55e303ae 673 register struct ppc_exception_state *xes;
1c79356b
A
674 register struct ppc_float_state *fs;
675 register struct ppc_vector_state *vs;
1c79356b 676
91447636 677// dbgTrace((unsigned int)thr_act, (unsigned int)0 /*sv: was never set*/, flavor); /* (TEST/DEBUG) */
1c79356b
A
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 }
1c79356b 687 break;
55e303ae
A
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;
1c79356b
A
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
55e303ae
A
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
1c79356b
A
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
1c79356b
A
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
1c79356b
A
725 break;
726
727 default:
728 return KERN_INVALID_ARGUMENT;
729 }
1c79356b 730
91447636 731 genuser = get_user_regs(thread); /* Find or allocate and initialize one */
9bccf70c 732
1c79356b
A
733 switch (flavor) {
734
735 case PPC_THREAD_STATE:
1c79356b
A
736
737 ts = (struct ppc_thread_state *)tstate;
1c79356b 738
55e303ae
A
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 */
91447636
A
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 */
55e303ae
A
789
790 return KERN_SUCCESS;
791
792
793 case PPC_THREAD_STATE64:
9bccf70c 794
55e303ae
A
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 */
d7e50217 838
55e303ae
A
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 */
91447636
A
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 */
55e303ae
A
847
848 return KERN_SUCCESS;
849
850
851 case PPC_EXCEPTION_STATE:
852
1c79356b
A
853 es = (struct ppc_exception_state *) tstate;
854
55e303ae 855 genuser->save_dar = (uint64_t)es->dar;
9bccf70c
A
856 genuser->save_dsisr = es->dsisr;
857 genuser->save_exception = es->exception;
1c79356b
A
858
859 return KERN_SUCCESS;
860
55e303ae
A
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
1c79356b
A
875 case PPC_FLOAT_STATE:
876
91447636 877 toss_live_fpu(thread->machine.curctx); /* Toss my floating point if live anywhere */
1c79356b 878
91447636 879 fsv = find_user_fpu(thread); /* Get the user's floating point context */
9bccf70c
A
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 */
91447636 884 fsv->save_hdr.save_act = thread;
9bccf70c
A
885 fsv->save_hdr.save_prev = 0; /* Mark no more */
886 fsv->save_hdr.save_level = 0; /* Mark user state */
1c79356b 887
91447636 888 if(!thread->machine.curctx->FPUsave) thread->machine.curctx->FPUsave = fsv; /* If no floating point, chain us first */
9bccf70c
A
889 else {
890
91447636 891 fsvn = fsvo = thread->machine.curctx->FPUsave; /* Remember first one */
1c79356b 892
9bccf70c
A
893 while (fsvn) { /* Go until we hit the end */
894 fsvo = fsvn; /* Remember the previous one */
55e303ae 895 fsvn = CAST_DOWN(savearea_fpu *, fsvo->save_hdr.save_prev); /* Skip on to the next */
1c79356b
A
896 }
897
55e303ae 898 fsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv); /* Queue us on in */
1c79356b 899 }
9bccf70c 900
1c79356b
A
901 }
902
903 fs = (struct ppc_float_state *) tstate; /* Point to source */
904
905
9bccf70c 906 bcopy((char *)fs, (char *)&fsv->save_fp0, 32*8); /* Move in the 32 registers */
1c79356b 907
9bccf70c 908 genuser->save_fpscr = fs->fpscr; /* Copy the fpscr value to normal */
1c79356b 909
1c79356b
A
910 return KERN_SUCCESS;
911
912
913 case PPC_VECTOR_STATE:
914
91447636 915 toss_live_vec(thread->machine.curctx); /* Toss my vector if live anywhere */
1c79356b 916
91447636 917 vsv = find_user_vec(thread); /* Get the user's vector context */
9bccf70c
A
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 */
91447636 922 vsv->save_hdr.save_act = thread;
9bccf70c
A
923 vsv->save_hdr.save_prev = 0; /* Mark no more */
924 vsv->save_hdr.save_level = 0; /* Mark user state */
1c79356b 925
91447636 926 if(!thread->machine.curctx->VMXsave) thread->machine.curctx->VMXsave = vsv; /* If no vector, chain us first */
9bccf70c
A
927 else {
928
91447636 929 vsvn = vsvo = thread->machine.curctx->VMXsave; /* Remember first one */
1c79356b 930
9bccf70c
A
931 while (vsvn) { /* Go until we hit the end */
932 vsvo = vsvn; /* Remember the previous one */
55e303ae 933 vsvn = CAST_DOWN(savearea_vec *, vsvo->save_hdr.save_prev); /* Skip on to the next */
1c79356b
A
934 }
935
55e303ae 936 vsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv); /* Queue us on in */
1c79356b 937 }
9bccf70c 938
1c79356b 939 }
1c79356b
A
940
941 vs = (struct ppc_vector_state *) tstate; /* Point to source */
942
9bccf70c
A
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 */
1c79356b
A
948
949 return KERN_SUCCESS;
950
951
952 default:
953 return KERN_INVALID_ARGUMENT;
954 }
955}
956
91447636
A
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 */
965kern_return_t
966machine_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
1c79356b
A
984/*
985 * Duplicates the context of one thread into a new one.
9bccf70c 986 * The new thread is assumed to be new and have no user state contexts except maybe a general one.
1c79356b
A
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.
1c79356b
A
991 */
992
91447636
A
993kern_return_t
994machine_thread_dup(
995 thread_t self,
996 thread_t target)
997{
9bccf70c
A
998 savearea *sv, *osv;
999 savearea_fpu *fsv, *fsvn;
1000 savearea_vec *vsv, *vsvn;
1c79356b 1001
91447636
A
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 */
1c79356b 1004
55e303ae 1005 sv = get_user_regs(target); /* Allocate and initialze context in the new activation */
1c79356b 1006
55e303ae
A
1007 osv = find_user_regs(self); /* Find the original context */
1008 if(!osv)
1009 return (KERN_FAILURE);
1c79356b 1010
9bccf70c
A
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
91447636 1015 sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC))); /* Make certain that floating point and vector are turned off */
1c79356b 1016
55e303ae 1017 fsv = find_user_fpu(self); /* Get any user floating point */
1c79356b 1018
91447636 1019 target->machine.curctx->FPUsave = 0; /* Assume no floating point */
1c79356b 1020
9bccf70c
A
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 */
91447636 1024 fsvn->save_hdr.save_act = target;
9bccf70c
A
1025 fsvn->save_hdr.save_prev = 0; /* Mark no more */
1026 fsvn->save_hdr.save_level = 0; /* Mark user state */
1c79356b 1027
91447636 1028 target->machine.curctx->FPUsave = fsvn; /* Chain in the floating point */
9bccf70c
A
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));
1c79356b 1033 }
9bccf70c 1034
55e303ae 1035 vsv = find_user_vec(self); /* Get any user vector */
1c79356b 1036
91447636 1037 target->machine.curctx->VMXsave = 0; /* Assume no vector */
9bccf70c
A
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 */
91447636 1042 vsvn->save_hdr.save_act = target;
9bccf70c
A
1043 vsvn->save_hdr.save_prev = 0; /* Mark no more */
1044 vsvn->save_hdr.save_level = 0; /* Mark user state */
1045
91447636 1046 target->machine.curctx->VMXsave = vsvn; /* Chain in the floating point */
9bccf70c
A
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));
1c79356b
A
1051 }
1052
55e303ae 1053 return (KERN_SUCCESS);
1c79356b
A
1054}
1055
1056/*
1057 * Initializes a fresh set of user state values. If there is no user state context,
9bccf70c
A
1058 * one is created. Floats and VMX are not created.
1059 *
1060 * We only set initial values if there was no context found.
1c79356b
A
1061 */
1062
91447636
A
1063savearea *
1064get_user_regs(
1065 thread_t thread)
1066{
1c79356b 1067 savearea *sv, *osv;
91447636 1068 unsigned int i;
1c79356b 1069
91447636
A
1070 if (thread->machine.upcb)
1071 return thread->machine.upcb;
55e303ae 1072
91447636 1073 sv = thread->machine.pcb; /* Get the top savearea on the stack */
1c79356b
A
1074 osv = 0; /* Set no user savearea yet */
1075
1076 while(sv) { /* Find the user context */
1c79356b 1077 osv = sv; /* Save the last one */
55e303ae 1078 sv = CAST_DOWN(savearea *, sv->save_hdr.save_prev); /* Get the previous context */
1c79356b
A
1079 }
1080
9bccf70c
A
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 */
91447636 1083 sv->save_hdr.save_act = thread;
9bccf70c
A
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? */
55e303ae 1088 osv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv); /* Chain us on the end */
9bccf70c
A
1089 }
1090 else { /* We are the first */
91447636 1091 thread->machine.pcb = sv; /* Put it there */
1c79356b 1092 }
91447636 1093 thread->machine.upcb = sv; /* Set user pcb */
1c79356b
A
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;
55e303ae
A
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;
91447636
A
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 */
9bccf70c
A
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;
55e303ae 1114 sv->save_vscr[3] = 0x00010000; /* Disable java mode and clear saturated */
1c79356b 1115
9bccf70c 1116 return sv; /* Bye bye... */
1c79356b
A
1117}
1118
1119/*
1120 * Find the user state context. If there is no user state context,
1121 * we just return a 0.
1122 */
1123
91447636
A
1124savearea *
1125find_user_regs(
1126 thread_t thread)
1127{
1128 return thread->machine.upcb;
55e303ae 1129}
1c79356b 1130
55e303ae
A
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 */
91447636
A
1134savearea *
1135find_kern_regs(
1136 thread_t thread)
1137{
1138 return thread->machine.pcb;
1c79356b
A
1139}
1140
1141/*
9bccf70c 1142 * Find the user state floating point context. If there is no user state context,
1c79356b
A
1143 * we just return a 0.
1144 */
1145
91447636
A
1146savearea_fpu *
1147find_user_fpu(
1148 thread_t thread)
1149{
9bccf70c 1150 savearea_fpu *fsv;
91447636 1151 boolean_t intr;
1c79356b 1152
91447636
A
1153 intr = ml_set_interrupts_enabled(FALSE);
1154 fsv = thread->machine.curctx->FPUsave; /* Get the start of the floating point chain */
9bccf70c 1155
1c79356b 1156 while(fsv) { /* Look until the end or we find it */
9bccf70c 1157 if(!(fsv->save_hdr.save_level)) break; /* Is the the user state stuff? (the level is 0 if so) */
55e303ae 1158 fsv = CAST_DOWN(savearea_fpu *, fsv->save_hdr.save_prev); /* Try the previous one */
1c79356b 1159 }
5eebf738 1160 (void) ml_set_interrupts_enabled(intr);
1c79356b 1161
9bccf70c
A
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
91447636
A
1170savearea_vec *
1171find_user_vec(
1172 thread_t thread)
1173{
9bccf70c 1174 savearea_vec *vsv;
91447636 1175 boolean_t intr;
9bccf70c 1176
91447636
A
1177 intr = ml_set_interrupts_enabled(FALSE);
1178 vsv = thread->machine.curctx->VMXsave; /* Get the start of the vector chain */
9bccf70c
A
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) */
55e303ae
A
1182 vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev); /* Try the previous one */
1183 }
5eebf738 1184 (void) ml_set_interrupts_enabled(intr);
55e303ae
A
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
1193savearea_vec *find_user_vec_curr(void) {
1194
1195 savearea_vec *vsv;
91447636
A
1196 thread_t thread = current_thread();
1197 boolean_t intr;
55e303ae 1198
91447636 1199 vec_save(thread->machine.curctx); /* Force save if live */
55e303ae 1200
91447636
A
1201 intr = ml_set_interrupts_enabled(FALSE);
1202 vsv = thread->machine.curctx->VMXsave; /* Get the start of the vector chain */
55e303ae
A
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 */
9bccf70c 1207 }
5eebf738 1208 (void) ml_set_interrupts_enabled(intr);
9bccf70c
A
1209
1210 return vsv; /* Bye bye... */
1c79356b
A
1211}
1212
1213/*
1214 * thread_userstack:
1215 *
1216 * Return the user stack pointer from the machine
1217 * dependent thread state info.
1218 */
1219kern_return_t
1220thread_userstack(
91447636 1221 __unused thread_t thread,
1c79356b
A
1222 int flavor,
1223 thread_state_t tstate,
1224 unsigned int count,
91447636 1225 mach_vm_offset_t *user_stack,
0b4e3aa0 1226 int *customstack
1c79356b
A
1227)
1228{
55e303ae
A
1229 /*
1230 * Set a default.
1231 */
1c79356b
A
1232
1233 switch (flavor) {
1234 case PPC_THREAD_STATE:
91447636
A
1235 {
1236 struct ppc_thread_state *state;
1237
1c79356b
A
1238 if (count < PPC_THREAD_STATE_COUNT)
1239 return (KERN_INVALID_ARGUMENT);
1240
1241 state = (struct ppc_thread_state *) tstate;
1242
55e303ae
A
1243 /*
1244 * If a valid user stack is specified, use it.
1245 */
91447636
A
1246 if (state->r1) {
1247 *user_stack = CAST_USER_ADDR_T(state->r1);
1248 if (customstack)
55e303ae 1249 *customstack = 1;
91447636
A
1250 } else {
1251 *user_stack = CAST_USER_ADDR_T(USRSTACK);
1252 if (customstack)
1253 *customstack = 0;
1254 }
1255 }
1256 break;
55e303ae 1257
91447636
A
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 }
1c79356b 1280 break;
91447636 1281
1c79356b
A
1282 default :
1283 return (KERN_INVALID_ARGUMENT);
1284 }
1285
1286 return (KERN_SUCCESS);
1287}
1288
9bccf70c
A
1289
1290/*
1291 * thread_setuserstack:
1292 *
1293 * Sets the user stack pointer into the machine
1294 * dependent thread state info.
1295 */
91447636
A
1296void
1297thread_setuserstack(thread_t thread, mach_vm_address_t user_stack)
9bccf70c
A
1298{
1299 savearea *sv;
1300
91447636 1301 sv = get_user_regs(thread); /* Get the user state registers */
9bccf70c 1302
91447636 1303 sv->save_r1 = user_stack;
9bccf70c
A
1304
1305 return;
1306}
1307
1308/*
1309 * thread_adjuserstack:
1310 *
1311 * Returns the adjusted user stack pointer from the machine
91447636 1312 * dependent thread state info. Usef for small (<2G) deltas.
9bccf70c 1313 */
91447636
A
1314uint64_t
1315thread_adjuserstack(thread_t thread, int adjust)
9bccf70c
A
1316{
1317 savearea *sv;
1318
91447636 1319 sv = get_user_regs(thread); /* Get the user state registers */
9bccf70c 1320
91447636 1321 sv->save_r1 += adjust; /* Adjust the stack */
9bccf70c 1322
91447636 1323 return sv->save_r1; /* Return the adjusted stack */
9bccf70c
A
1324
1325}
1326
1327/*
1328 * thread_setentrypoint:
1329 *
1330 * Sets the user PC into the machine
1331 * dependent thread state info.
1332 */
1333
91447636
A
1334void
1335thread_setentrypoint(thread_t thread, uint64_t entry)
9bccf70c
A
1336{
1337 savearea *sv;
1338
91447636 1339 sv = get_user_regs(thread); /* Get the user state registers */
9bccf70c 1340
91447636 1341 sv->save_srr0 = entry;
9bccf70c
A
1342
1343 return;
1344}
1345
1c79356b
A
1346kern_return_t
1347thread_entrypoint(
91447636 1348 __unused thread_t thread,
1c79356b
A
1349 int flavor,
1350 thread_state_t tstate,
1351 unsigned int count,
91447636 1352 mach_vm_offset_t *entry_point
1c79356b
A
1353)
1354{
91447636
A
1355#if 0
1356 /* Silly code: "if *entry_point is 0, make it 0" */
1c79356b
A
1357 /*
1358 * Set a default.
1359 */
91447636
A
1360 if (*entry_point == 0ULL)
1361 *entry_point = MACH_VM_MIN_ADDRESS;
1362#endif
1c79356b
A
1363
1364 switch (flavor) {
1c79356b 1365 case PPC_THREAD_STATE:
91447636
A
1366 {
1367 struct ppc_thread_state *state;
1368
1c79356b
A
1369 if (count < PPC_THREAD_STATE_COUNT)
1370 return (KERN_INVALID_ARGUMENT);
1371
1372 state = (struct ppc_thread_state *) tstate;
1373
1374 /*
1375 * If a valid entry point is specified, use it.
1376 */
91447636
A
1377 if (state->srr0) {
1378 *entry_point = CAST_USER_ADDR_T(state->srr0);
1379 } else {
1380 *entry_point = CAST_USER_ADDR_T(VM_MIN_ADDRESS);
1381 }
1382 }
1383 break;
1384
1385 case PPC_THREAD_STATE64:
1386 {
1387 struct ppc_thread_state64 *state64;
1388
1389 if (count < PPC_THREAD_STATE_COUNT)
1390 return (KERN_INVALID_ARGUMENT);
1391
1392 state64 = (struct ppc_thread_state64 *)tstate;
1393
1394 /*
1395 * If a valid entry point is specified, use it.
1396 */
1397 if (state64->srr0) {
1398 *entry_point = state64->srr0;
1399 } else {
1400 *entry_point = MACH_VM_MIN_ADDRESS;
1401 }
1402 }
1c79356b 1403 break;
91447636 1404
1c79356b
A
1405 default:
1406 return (KERN_INVALID_ARGUMENT);
1407 }
1408
1409 return (KERN_SUCCESS);
1410}
1411
1412unsigned int get_msr_exportmask(void)
1413{
1414 return (MSR_EXPORT_MASK_SET);
1415}
1416
1417unsigned int get_msr_nbits(void)
1418{
1419 return (MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1420}
1421unsigned int get_msr_rbits(void)
1422{
1423 return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1424}
1425
55e303ae
A
1426void ppc_checkthreadstate(void * tsptr, int flavor)
1427{
1428 if (flavor == PPC_THREAD_STATE64) {
1429 struct ppc_thread_state64 *ts64 =(struct ppc_thread_state64 *)tsptr;
1430
1431 /* Make sure naughty bits are off and necessary bits are on */
1432 ts64->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1433 ts64->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1434 } else {
1435 struct ppc_thread_state *ts =(struct ppc_thread_state *)tsptr;
1436
1437 /* Make sure naughty bits are off and necessary bits are on */
1438 ts->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1439 ts->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1440 }
1441 return;
1442}
1443
91447636
A
1444void
1445thread_set_child(
1446 thread_t child,
1447 int pid)
1c79356b 1448{
9bccf70c 1449 struct savearea *child_state;
1c79356b 1450
9bccf70c 1451 child_state = get_user_regs(child);
1c79356b 1452
55e303ae
A
1453 child_state->save_r3 = (uint_t)pid;
1454 child_state->save_r4 = 1ULL;
1c79356b 1455}
91447636
A
1456void
1457thread_set_parent(
1458 thread_t parent,
1459 int pid)
0b4e3aa0 1460{
9bccf70c 1461 struct savearea *parent_state;
0b4e3aa0 1462
9bccf70c 1463 parent_state = get_user_regs(parent);
0b4e3aa0 1464
55e303ae 1465 parent_state->save_r3 = (uint64_t)pid;
9bccf70c 1466 parent_state->save_r4 = 0;
0b4e3aa0
A
1467}
1468
1469/*
1470 * Saves the complete context (general, floating point, and vector) of the current activation.
9bccf70c
A
1471 * We will collect everything into an opaque block of 1 to 3 saveareas and pass back a
1472 * pointer to that.
0b4e3aa0
A
1473 *
1474 * The savearea is made to look like it belongs to the source activation. This needs to
1475 * be adjusted when these contexts are attached to a new activation.
1476 *
1477 */
1478
1479void *act_thread_csave(void) {
1480
9bccf70c
A
1481 savearea *sv, *osv;
1482 savearea_fpu *fsv, *ofsv;
1483 savearea_vec *vsv, *ovsv;
0b4e3aa0 1484
91447636 1485 thread_t thread;
0b4e3aa0 1486
91447636 1487 thread = current_thread();
9bccf70c 1488
91447636
A
1489 fpu_save(thread->machine.curctx); /* Make certain floating point state is all saved */
1490 vec_save(thread->machine.curctx); /* Make certain the vector state is all saved */
0b4e3aa0 1491
91447636 1492 osv = find_user_regs(thread); /* Get our savearea */
0b4e3aa0 1493
9bccf70c 1494 if(!osv) {
91447636 1495 panic("act_thread_csave: attempting to preserve the context of an activation with none (%08X)\n", thread);
9bccf70c 1496 }
0b4e3aa0 1497
9bccf70c
A
1498 sv = save_alloc(); /* Get a fresh save area to save into */
1499 sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft); /* Mark as in use as general */
91447636 1500 sv->save_hdr.save_act = thread;
9bccf70c
A
1501 sv->save_hdr.save_prev = 0; /* Mark no more */
1502 sv->save_hdr.save_level = 0; /* Mark user state */
0b4e3aa0 1503
0b4e3aa0 1504
9bccf70c
A
1505 bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)), /* Copy everything but the headers */
1506 (char *)((unsigned int)sv + sizeof(savearea_comm)),
1507 sizeof(struct savearea) - sizeof(savearea_comm));
1508
91447636 1509 sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC))); /* Make certain that floating point and vector are turned off */
9bccf70c
A
1510
1511 sv->save_hdr.save_misc2 = 0xDEBB1ED0; /* Eye catcher for debug */
1512 sv->save_hdr.save_misc3 = 0xE5DA11A5; /* Eye catcher for debug */
0b4e3aa0 1513
0b4e3aa0 1514
91447636 1515 ofsv = find_user_fpu(thread); /* Get any user floating point */
0b4e3aa0 1516
9bccf70c 1517 sv->save_hdr.save_misc0 = 0; /* Assume no floating point */
0b4e3aa0 1518
9bccf70c
A
1519 if(ofsv) { /* Did we find one? */
1520 fsv = (savearea_fpu *)save_alloc(); /* If we still don't have one, get a new one */
1521 fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft); /* Mark as in use as float */
91447636 1522 fsv->save_hdr.save_act = thread;
9bccf70c
A
1523 fsv->save_hdr.save_prev = 0; /* Mark no more */
1524 fsv->save_hdr.save_level = 0; /* Mark user state */
1525 fsv->save_hdr.save_misc2 = 0xDEBB1ED0; /* Eye catcher for debug */
1526 fsv->save_hdr.save_misc3 = 0xE5DA11A5; /* Eye catcher for debug */
1527
55e303ae 1528 sv->save_hdr.save_misc0 = (uint64_t)((uintptr_t)fsv); /* Remember this one */
9bccf70c
A
1529
1530 bcopy((char *)((unsigned int)ofsv + sizeof(savearea_comm)), /* Copy everything but the headers */
1531 (char *)((unsigned int)fsv + sizeof(savearea_comm)),
1532 sizeof(struct savearea) - sizeof(savearea_comm));
0b4e3aa0 1533 }
9bccf70c 1534
91447636 1535 ovsv = find_user_vec(thread); /* Get any user vector */
0b4e3aa0 1536
9bccf70c
A
1537 sv->save_hdr.save_misc1 = 0; /* Assume no vector */
1538
1539 if(ovsv) { /* Did we find one? */
1540 vsv = (savearea_vec *)save_alloc(); /* If we still don't have one, get a new one */
1541 vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft); /* Mark as in use as float */
91447636 1542 vsv->save_hdr.save_act = thread;
9bccf70c
A
1543 vsv->save_hdr.save_prev = 0; /* Mark no more */
1544 vsv->save_hdr.save_level = 0; /* Mark user state */
1545 vsv->save_hdr.save_misc2 = 0xDEBB1ED0; /* Eye catcher for debug */
1546 vsv->save_hdr.save_misc3 = 0xE5DA11A5; /* Eye catcher for debug */
1547
55e303ae 1548 sv->save_hdr.save_misc1 = (uint64_t)((uintptr_t)vsv); /* Chain in the floating point */
9bccf70c
A
1549
1550 bcopy((char *)((unsigned int)ovsv + sizeof(savearea_comm)), /* Copy everything but the headers */
1551 (char *)((unsigned int)vsv + sizeof(savearea_comm)),
1552 sizeof(struct savearea) - sizeof(savearea_comm));
0b4e3aa0
A
1553 }
1554
1555 return (void *)sv; /* Bye bye... */
1556}
1557
1558
1559
1560/*
1561 * Attaches saved user state context to an activation. We will replace any
1562 * user state context with what is passed in. The saved context consists of a
1563 * savearea that was setup by
1564 * We will collect everything into one savearea and pass that back.
1565 *
1566 * The savearea is made to look like it belongs to the source activation. This needs to
1567 * be adjusted when these contexts are attached to a new activation.
1568 *
1569 */
1570
1571void act_thread_catt(void *ctx) {
1572
9bccf70c
A
1573 savearea *sv, *osv, *psv;
1574 savearea_fpu *fsv, *ofsv, *pfsv;
1575 savearea_vec *vsv, *ovsv, *pvsv;
91447636
A
1576 unsigned int spc;
1577 thread_t thread;
0b4e3aa0
A
1578
1579 sv = (savearea *)ctx; /* Make this easier for C */
1580
55e303ae
A
1581 fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0); /* Get a possible floating point savearea */
1582 vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1); /* Get a possible vector savearea */
9bccf70c
A
1583
1584 if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1585 panic("act_thread_catt: attempt to attach invalid general context savearea - %08X\n", sv); /* Die */
0b4e3aa0
A
1586 }
1587
9bccf70c
A
1588 if(fsv && ((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5))) { /* See if valid savearea */
1589 panic("act_thread_catt: attempt to attach invalid float context savearea - %08X\n", fsv); /* Die */
0b4e3aa0
A
1590 }
1591
9bccf70c
A
1592 if(vsv && ((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5))) { /* See if valid savearea */
1593 panic("act_thread_catt: attempt to attach invalid vector context savearea - %08X\n", vsv); /* Die */
1594 }
0b4e3aa0 1595
91447636 1596 thread = current_thread();
0b4e3aa0 1597
b36670ce
A
1598 act_machine_sv_free(thread); /* Blow away any current kernel FP or vector.
1599 We do not support those across a vfork */
1600 toss_live_fpu(thread->machine.curctx); /* Toss my floating point if live anywhere */
1601 toss_live_vec(thread->machine.curctx); /* Toss my vector if live anywhere */
9bccf70c
A
1602
1603 sv->save_hdr.save_misc2 = 0; /* Eye catcher for debug */
1604 sv->save_hdr.save_misc3 = 0; /* Eye catcher for debug */
91447636 1605 sv->save_hdr.save_act = thread;
0b4e3aa0 1606
b36670ce 1607 spc = (unsigned int)thread->map->pmap->space; /* Get the space we're in */
0b4e3aa0 1608
b36670ce 1609 osv = thread->machine.pcb; /* Get the top general savearea */
0b4e3aa0 1610 psv = 0;
9bccf70c
A
1611 while(osv) { /* Any saved state? */
1612 if(osv->save_srr1 & MASK(MSR_PR)) break; /* Leave if this is user state */
0b4e3aa0 1613 psv = osv; /* Save previous savearea address */
55e303ae 1614 osv = CAST_DOWN(savearea *, osv->save_hdr.save_prev); /* Get one underneath our's */
0b4e3aa0
A
1615 }
1616
1617 if(osv) { /* Did we find one? */
9bccf70c 1618 if(psv) psv->save_hdr.save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */
91447636 1619 else thread->machine.pcb = 0; /* to the start if the only one */
0b4e3aa0 1620
9bccf70c
A
1621 save_release(osv); /* Nope, release it */
1622
0b4e3aa0 1623 }
9bccf70c 1624
55e303ae 1625 if(psv) psv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv); /* Chain us to the end or */
91447636
A
1626 else thread->machine.pcb = (pcb_t)sv; /* to the start if the only one */
1627 thread->machine.upcb = (pcb_t)sv; /* Set the user pcb */
0b4e3aa0 1628
91447636 1629 ovsv = thread->machine.curctx->VMXsave; /* Get the top vector savearea */
0b4e3aa0 1630
9bccf70c
A
1631 pvsv = 0;
1632 while(ovsv) { /* Any VMX saved state? */
1633 if(!(ovsv->save_hdr.save_level)) break; /* Leave if this is user state */
1634 pvsv = ovsv; /* Save previous savearea address */
55e303ae 1635 ovsv = CAST_DOWN(savearea_vec *, ovsv->save_hdr.save_prev); /* Get one underneath our's */
0b4e3aa0 1636 }
9bccf70c
A
1637
1638 if(ovsv) { /* Did we find one? */
1639 if(pvsv) pvsv->save_hdr.save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */
b36670ce 1640 else thread->machine.curctx->VMXsave = 0; /* to the start if the only one */
0b4e3aa0 1641
9bccf70c 1642 save_release((savearea *)ovsv); /* Nope, release it */
0b4e3aa0
A
1643 }
1644
9bccf70c 1645 if(vsv) { /* Are we sticking any vector on this one? */
55e303ae 1646 if(pvsv) pvsv->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv); /* Yes, chain us to the end or */
b36670ce
A
1647 else {
1648 thread->machine.curctx->VMXsave = vsv; /* to the start if the only one */
1649 thread->machine.curctx->VMXlevel = 0; /* Insure that we don't have a leftover level */
1650 }
0b4e3aa0 1651
9bccf70c
A
1652 vsv->save_hdr.save_misc2 = 0; /* Eye catcher for debug */
1653 vsv->save_hdr.save_misc3 = 0; /* Eye catcher for debug */
91447636 1654 vsv->save_hdr.save_act = thread;
0b4e3aa0
A
1655 }
1656
b36670ce 1657 ofsv = thread->machine.curctx->FPUsave; /* Get the top float savearea */
0b4e3aa0 1658
9bccf70c
A
1659 pfsv = 0;
1660 while(ofsv) { /* Any float saved state? */
1661 if(!(ofsv->save_hdr.save_level)) break; /* Leave if this is user state */
1662 pfsv = ofsv; /* Save previous savearea address */
55e303ae 1663 ofsv = CAST_DOWN(savearea_fpu *, ofsv->save_hdr.save_prev); /* Get one underneath our's */
0b4e3aa0
A
1664 }
1665
9bccf70c
A
1666 if(ofsv) { /* Did we find one? */
1667 if(pfsv) pfsv->save_hdr.save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */
b36670ce 1668 else thread->machine.curctx->FPUsave = 0; /* to the start if the only one */
0b4e3aa0 1669
9bccf70c 1670 save_release((savearea *)ofsv); /* Nope, release it */
0b4e3aa0
A
1671 }
1672
9bccf70c 1673 if(fsv) { /* Are we sticking any vector on this one? */
55e303ae 1674 if(pfsv) pfsv->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv); /* Yes, chain us to the end or */
b36670ce
A
1675 else {
1676 thread->machine.curctx->FPUsave = fsv; /* to the start if the only one */
1677 thread->machine.curctx->FPUlevel = 0; /* Insure that we don't have a leftover level */
1678 }
0b4e3aa0 1679
9bccf70c
A
1680 fsv->save_hdr.save_misc2 = 0; /* Eye catcher for debug */
1681 fsv->save_hdr.save_misc3 = 0; /* Eye catcher for debug */
91447636 1682 fsv->save_hdr.save_act = thread;
9bccf70c
A
1683 }
1684
0b4e3aa0
A
1685}
1686
1687
1688
1689/*
1690 * Releases saved context. We need this because the saved context is opague.
1691 * be adjusted when these contexts are attached to a new activation.
1692 *
1693 */
1694
91447636
A
1695void
1696act_thread_cfree(void *ctx)
1697{
0b4e3aa0 1698
91447636
A
1699 savearea *sv;
1700 savearea_fpu *fsv;
1701 savearea_vec *vsv;
9bccf70c
A
1702
1703 sv = (savearea *)ctx; /* Make this easier for C */
1704
55e303ae
A
1705 fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0); /* Get a possible floating point savearea */
1706 vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1); /* Get a possible vector savearea */
9bccf70c
A
1707
1708 if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1709 panic("act_thread_cfree: attempt to detatch invalid general context savearea - %08X\n", sv); /* Die */
1710 }
1711
1712 save_release(sv); /* Toss the general savearea */
1713
1714 if(fsv) { /* See if there is any saved floating point */
1715 if((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1716 panic("act_thread_cfree: attempt to detatch invalid float context savearea - %08X\n", fsv); /* Die */
1717 }
1718
1719 save_release((savearea *)fsv); /* Toss saved context */
0b4e3aa0
A
1720 }
1721
9bccf70c
A
1722 if(vsv) { /* See if there is any saved floating point */
1723 if((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5)) { /* See if valid savearea */
1724 panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %08X\n", vsv); /* Die */
1725 }
1726
1727 save_release((savearea *)vsv); /* Toss saved context */
1728 }
0b4e3aa0
A
1729
1730 return;
1731}
9bccf70c
A
1732
1733/*
1734 * thread_enable_fpe:
1735 *
1736 * enables or disables floating point exceptions for the thread.
1737 * returns old state
1738 */
91447636
A
1739int thread_enable_fpe(
1740 thread_t thread,
1741 int onoff)
9bccf70c
A
1742{
1743 savearea *sv;
91447636 1744 uint64_t oldmsr;
9bccf70c 1745
91447636
A
1746 sv = find_user_regs(thread); /* Find the user registers */
1747 if(!sv) sv = get_user_regs(thread); /* Didn't find any, allocate and initialize one */
9bccf70c 1748
91447636 1749 oldmsr = sv->save_srr1; /* Get the old msr */
9bccf70c 1750
91447636
A
1751 if(onoff) sv->save_srr1 = oldmsr | (uint64_t)(MASK(MSR_FE0) | MASK(MSR_FE1)); /* Flip on precise FP exceptions */
1752 else sv->save_srr1 = oldmsr & (uint64_t)(~(MASK(MSR_FE0) | MASK(MSR_FE1))); /* Flip on precise FP exceptions */
9bccf70c 1753
91447636 1754 return ((oldmsr & (MASK(MSR_FE0) | MASK(MSR_FE1))) != 0); /* Return if it was enabled or not */
9bccf70c 1755}