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