]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/status.c
xnu-201.14.tar.gz
[apple/xnu.git] / osfmk / ppc / status.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * @OSF_COPYRIGHT@
24 *
25 */
26
27 #include <kern/thread.h>
28 #include <kern/thread_act.h>
29 #include <kern/misc_protos.h>
30 #include <mach/ppc/thread_status.h>
31 #include <ppc/proc_reg.h>
32 #include <ppc/exception.h>
33 #include <ppc/fpu_protos.h>
34 #include <ppc/misc_protos.h>
35 #include <ppc/savearea.h>
36 #include <ppc/thread_act.h>
37 #include <ppc/Firmware.h>
38
39 #include <vm/vm_map.h>
40
41 extern unsigned int killprint;
42 extern double FloatInit;
43 extern unsigned long QNaNbarbarian[4];
44 extern void thread_bootstrap_return(void);
45 extern struct Saveanchor saveanchor;
46 extern int real_ncpus; /* Number of actual CPUs */
47
48
49 struct ppc_saved_state * get_user_regs(thread_act_t);
50
51 #define USRSTACK 0xc0000000
52
53 kern_return_t
54 thread_userstack(
55 thread_t,
56 int,
57 thread_state_t,
58 unsigned int,
59 vm_offset_t *,
60 int *
61 );
62
63 kern_return_t
64 thread_entrypoint(
65 thread_t,
66 int,
67 thread_state_t,
68 unsigned int,
69 vm_offset_t *
70 );
71
72 unsigned int get_msr_exportmask(void);
73 unsigned int get_msr_nbits(void);
74 unsigned int get_msr_rbits(void);
75 void thread_set_child(thread_act_t child, int pid);
76 void thread_set_parent(thread_act_t parent, int pid);
77
78 /*
79 * Maps state flavor to number of words in the state:
80 */
81 unsigned int state_count[] = {
82 /* FLAVOR_LIST */ 0,
83 PPC_THREAD_STATE_COUNT,
84 PPC_FLOAT_STATE_COUNT,
85 PPC_EXCEPTION_STATE_COUNT,
86 };
87
88 /*
89 * thread_getstatus:
90 *
91 * Get the status of the specified thread.
92 */
93
94 kern_return_t
95 act_machine_get_state(
96 thread_act_t thr_act,
97 thread_flavor_t flavor,
98 thread_state_t tstate,
99 mach_msg_type_number_t *count)
100 {
101
102 register struct savearea *sv; /* Pointer to the context savearea */
103 int i, j;
104 unsigned int vrvalidwrk;
105
106 register struct ppc_thread_state *ts;
107 register struct ppc_exception_state *es;
108 register struct ppc_float_state *fs;
109 register struct ppc_vector_state *vs;
110
111 #if MACH_ASSERT
112 if (watchacts & WA_STATE)
113 printf("act_%x act_machine_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n",
114 current_act(), thr_act, flavor, tstate,
115 count, (count ? *count : 0));
116 #endif /* MACH_ASSERT */
117
118
119 switch (flavor) {
120
121 case THREAD_STATE_FLAVOR_LIST:
122
123 if (*count < 3) {
124 return (KERN_INVALID_ARGUMENT);
125 }
126
127 tstate[0] = PPC_THREAD_STATE;
128 tstate[1] = PPC_FLOAT_STATE;
129 tstate[2] = PPC_EXCEPTION_STATE;
130 *count = 3;
131
132 return KERN_SUCCESS;
133
134 case PPC_THREAD_STATE:
135
136 if (*count < PPC_THREAD_STATE_COUNT) { /* Is the count ok? */
137 return KERN_INVALID_ARGUMENT;
138 }
139
140 ts = (struct ppc_thread_state *) tstate;
141
142 sv = (savearea *)(thr_act->mact.pcb); /* Start with the normal savearea */
143 while(sv) { /* Find the user context */
144 if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
145 break; /* Outta here */
146 }
147 sv = sv->save_prev; /* Back chain */
148 }
149
150 if(sv) { /* Is there a save area yet? */
151 ts->r0 = sv->save_r0;
152 ts->r1 = sv->save_r1;
153 ts->r2 = sv->save_r2;
154 ts->r3 = sv->save_r3;
155 ts->r4 = sv->save_r4;
156 ts->r5 = sv->save_r5;
157 ts->r6 = sv->save_r6;
158 ts->r7 = sv->save_r7;
159 ts->r8 = sv->save_r8;
160 ts->r9 = sv->save_r9;
161 ts->r10 = sv->save_r10;
162 ts->r11 = sv->save_r11;
163 ts->r12 = sv->save_r12;
164 ts->r13 = sv->save_r13;
165 ts->r14 = sv->save_r14;
166 ts->r15 = sv->save_r15;
167 ts->r16 = sv->save_r16;
168 ts->r17 = sv->save_r17;
169 ts->r18 = sv->save_r18;
170 ts->r19 = sv->save_r19;
171 ts->r20 = sv->save_r20;
172 ts->r21 = sv->save_r21;
173 ts->r22 = sv->save_r22;
174 ts->r23 = sv->save_r23;
175 ts->r24 = sv->save_r24;
176 ts->r25 = sv->save_r25;
177 ts->r26 = sv->save_r26;
178 ts->r27 = sv->save_r27;
179 ts->r28 = sv->save_r28;
180 ts->r29 = sv->save_r29;
181 ts->r30 = sv->save_r30;
182 ts->r31 = sv->save_r31;
183 ts->cr = sv->save_cr;
184 ts->xer = sv->save_xer;
185 ts->lr = sv->save_lr;
186 ts->ctr = sv->save_ctr;
187 ts->srr0 = sv->save_srr0;
188 ts->srr1 = sv->save_srr1;
189 ts->mq = sv->save_mq; /* MQ register (601 only) */
190 ts->vrsave = sv->save_vrsave; /* VRSAVE register (Altivec only) */
191 }
192 else { /* No user state yet. Save seemingly random values. */
193
194 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
195 ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
196 ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
197 }
198 ts->cr = 0;
199 ts->xer = 0;
200 ts->lr = ((unsigned int *)&FloatInit)[0];
201 ts->ctr = ((unsigned int *)&FloatInit)[1];
202 ts->srr0 = ((unsigned int *)&FloatInit)[0];
203 ts->srr1 = MSR_EXPORT_MASK_SET;
204 ts->mq = 0;
205 ts->vrsave = 0; /* VRSAVE register (Altivec only) */
206 }
207
208 *count = PPC_THREAD_STATE_COUNT; /* Pass back the amount we actually copied */
209 return KERN_SUCCESS;
210
211 case PPC_EXCEPTION_STATE:
212
213 if (*count < PPC_EXCEPTION_STATE_COUNT) {
214 return KERN_INVALID_ARGUMENT;
215 }
216
217 es = (struct ppc_exception_state *) tstate;
218
219 sv = (savearea *)(thr_act->mact.pcb); /* Start with the normal savearea */
220 while(sv) { /* Find the user context */
221 if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
222 break; /* Outta here */
223 }
224 sv = sv->save_prev; /* Back chain */
225 }
226
227 if(sv) { /* See if valid state yet */
228 es->dar = sv->save_dar;
229 es->dsisr = sv->save_dsisr;
230 es->exception = sv->save_exception;
231 }
232 else { /* Nope, not yet */
233 es->dar = 0;
234 es->dsisr = 0;
235 es->exception = ((unsigned int *)&FloatInit)[0];
236 }
237
238 *count = PPC_EXCEPTION_STATE_COUNT;
239 return KERN_SUCCESS;
240
241 case PPC_FLOAT_STATE:
242
243 if (*count < PPC_FLOAT_STATE_COUNT) {
244 return KERN_INVALID_ARGUMENT;
245 }
246
247 fpu_save(thr_act); /* Just in case it's live, save it */
248
249 fs = (struct ppc_float_state *) tstate; /* Point to destination */
250
251 sv = (savearea *)(thr_act->mact.FPU_pcb); /* Start with the top FPU savearea */
252 while(sv) { /* Find the user context */
253 if(!sv->save_level_fp) { /* Are we looking at the user context? */
254 break; /* Outta here */
255 }
256 sv = sv->save_prev_float; /* Back chain */
257 }
258
259 if(sv) { /* See if we have any */
260 bcopy((char *)&sv->save_fp0, (char *)fs, 33*8); /* 32 registers plus status and pad */
261 }
262 else { /* No floating point yet */
263
264 for(i=0; i < 32; i++) { /* Initialize floating points */
265 fs->fpregs[i] = FloatInit; /* Initial value */
266 }
267 fs->fpscr_pad = 0; /* Initial value */
268 fs->fpscr = 0; /* Initial value */
269 }
270
271 *count = PPC_FLOAT_STATE_COUNT;
272
273 return KERN_SUCCESS;
274
275 case PPC_VECTOR_STATE:
276
277 if (*count < PPC_VECTOR_STATE_COUNT) {
278 return KERN_INVALID_ARGUMENT;
279 }
280
281 vec_save(thr_act); /* Just in case it's live, save it */
282
283 vs = (struct ppc_vector_state *) tstate; /* Point to destination */
284
285 sv = (savearea *)(thr_act->mact.VMX_pcb); /* Start with the top FPU savearea */
286 while(sv) { /* Find the user context */
287 if(!sv->save_level_vec) { /* Are we looking at the user context? */
288 break; /* Outta here */
289 }
290 sv = sv->save_prev_vector; /* Back chain */
291 }
292
293 if(sv) { /* See if we have any */
294
295 vrvalidwrk = sv->save_vrvalid; /* Get the valid flags */
296 vs->save_vrvalid = sv->save_vrvalid; /* Set the valid flags */
297 for(j=0; j < 4; j++) vs->save_vscr[j] = sv->save_vscr[j]; /* Set value for vscr */
298
299 for(i=0; i < 32; i++) { /* Copy the saved registers and invalidate the others */
300 for(j=0; j < 4; j++) {
301 if(vrvalidwrk & 0x80000000) (vs->save_vr)[i][j] =
302 ((unsigned int *)&(sv->save_vr0))[(i * 4) + j]; /* We have this register saved */
303 else vs->save_vr[i][j] = QNaNbarbarian[j]; /* Set invalid value */
304 }
305 vrvalidwrk = vrvalidwrk << 1; /* Shift over to the next */
306 }
307 }
308 else { /* No vector yet */
309
310 for(i=0; i < 32; i++) { /* Initialize vector registers */
311 for(j=0; j < 4; j++) vs->save_vr[i][j] = QNaNbarbarian[j]; /* Initial value */
312 }
313 for(j=0; j < 4; j++) vs->save_vscr[j] = 0; /* Initial value */
314 vs->save_vrvalid = 0; /* Clear the valid flags */
315 }
316
317 for (i=0; i < 4; i++) vs->save_pad5[i] = 0; /* Clear cruft */
318 for (i=0; i < 7; i++) vs->save_pad6[i] = 0; /* Clear cruft */
319
320 *count = PPC_VECTOR_STATE_COUNT;
321 return KERN_SUCCESS;
322
323 default:
324 return KERN_INVALID_ARGUMENT;
325 }
326 }
327
328
329 /*
330 * thread_setstatus:
331 *
332 * Set the status of the specified thread.
333 */
334 kern_return_t
335 act_machine_set_state(
336 thread_act_t thr_act,
337 thread_flavor_t flavor,
338 thread_state_t tstate,
339 mach_msg_type_number_t count)
340 {
341
342 savearea *sv, *osv, *usv, *ssv;
343 unsigned int spc, i, *srs, isnew, clgn;
344 register struct ppc_thread_state *ts;
345 register struct ppc_exception_state *es;
346 register struct ppc_float_state *fs;
347 register struct ppc_vector_state *vs;
348 spl_t spl;
349
350 int kernel_act = thr_act->kernel_loading || thr_act->kernel_loaded;
351
352 #if MACH_ASSERT
353 if (watchacts & WA_STATE)
354 printf("act_%x act_machine_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n",
355 current_act(), thr_act, flavor, tstate, count);
356 #endif /* MACH_ASSERT */
357
358 // dbgTrace((unsigned int)thr_act, (unsigned int)sv, flavor); /* (TEST/DEBUG) */
359
360 clgn = count; /* Get the count */
361
362 switch (flavor) { /* Validate the count before we do anything else */
363 case PPC_THREAD_STATE:
364
365 if (clgn < PPC_THREAD_STATE_COUNT) { /* Is it too short? */
366 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
367 }
368
369 if(clgn > PPC_THREAD_STATE_COUNT) clgn = PPC_THREAD_STATE_COUNT; /* If too long, pin it at max */
370 break;
371
372 case PPC_EXCEPTION_STATE:
373
374 if (clgn < PPC_EXCEPTION_STATE_COUNT) { /* Is it too short? */
375 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
376 }
377
378 if(clgn > PPC_EXCEPTION_STATE_COUNT) clgn = PPC_EXCEPTION_STATE_COUNT; /* If too long, pin it at max */
379 break;
380
381 case PPC_FLOAT_STATE:
382
383 if (clgn < PPC_FLOAT_STATE_COUNT) { /* Is it too short? */
384 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
385 }
386
387 if(clgn > PPC_FLOAT_STATE_COUNT) clgn = PPC_FLOAT_STATE_COUNT; /* If too long, pin it at max */
388 break;
389
390
391 case PPC_VECTOR_STATE:
392
393 if (clgn < PPC_VECTOR_STATE_COUNT) { /* Is it too short? */
394 return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
395 }
396
397 if(clgn > PPC_VECTOR_STATE_COUNT) clgn = PPC_VECTOR_STATE_COUNT; /* If too long, pin it at max */
398 break;
399
400 default:
401 return KERN_INVALID_ARGUMENT;
402 }
403
404 isnew = 0; /* Remember when we make a new one */
405
406 switch (flavor) {
407
408 case PPC_THREAD_STATE:
409 case PPC_EXCEPTION_STATE:
410
411 ts = (struct ppc_thread_state *)tstate;
412
413 sv = (savearea *)thr_act->mact.pcb; /* Get the top savearea on the stack */
414 osv = 0; /* Set no user savearea yet */
415
416 while(sv) { /* Find the user context */
417 if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
418 break; /* Outta here */
419 }
420 osv = sv; /* Save the last one */
421 sv = sv->save_prev; /* Get the previous context */
422 }
423
424 if(!sv) { /* We didn't find a user context so allocate and initialize one */
425 isnew = 1; /* Remember we made a new one */
426 sv = save_alloc(); /* Get one */
427 sv->save_act = thr_act; /* Point to the activation */
428 sv->save_flags |= SAVattach; /* Say that it is in use */
429 sv->save_srr1 = MSR_EXPORT_MASK_SET & ~MASK(MSR_PR); /* Assume kernel state */
430 sv->save_xfpscrpad = 0; /* Start with a clear fpscr */
431 sv->save_xfpscr = 0; /* Start with a clear fpscr */
432
433 spc = (unsigned int)thr_act->map->pmap->space; /* Get the space we're in */
434
435 srs = (unsigned int *)&sv->save_sr0; /* Point to the SRs */
436 for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
437 srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
438 }
439
440 sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
441
442 if(osv) { /* Did we already have one? */
443 osv->save_prev = sv; /* Chain us on the end */
444 }
445 else { /* We are the first */
446 thr_act->mact.pcb = (pcb_t)sv; /* Put it there */
447 }
448 sv->save_prev = 0; /* Properly terminate the chain */
449
450 }
451
452 if(flavor == PPC_THREAD_STATE) { /* Are we updating plain state? */
453
454 sv->save_r0 = ts->r0;
455 sv->save_r1 = ts->r1;
456 sv->save_r2 = ts->r2;
457 sv->save_r3 = ts->r3;
458 sv->save_r4 = ts->r4;
459 sv->save_r5 = ts->r5;
460 sv->save_r6 = ts->r6;
461 sv->save_r7 = ts->r7;
462 sv->save_r8 = ts->r8;
463 sv->save_r9 = ts->r9;
464 sv->save_r10 = ts->r10;
465 sv->save_r11 = ts->r11;
466 sv->save_r12 = ts->r12;
467 sv->save_r13 = ts->r13;
468 sv->save_r14 = ts->r14;
469 sv->save_r15 = ts->r15;
470 sv->save_r16 = ts->r16;
471 sv->save_r17 = ts->r17;
472 sv->save_r18 = ts->r18;
473 sv->save_r19 = ts->r19;
474 sv->save_r20 = ts->r20;
475 sv->save_r21 = ts->r21;
476 sv->save_r22 = ts->r22;
477 sv->save_r23 = ts->r23;
478 sv->save_r24 = ts->r24;
479 sv->save_r25 = ts->r25;
480 sv->save_r26 = ts->r26;
481 sv->save_r27 = ts->r27;
482 sv->save_r28 = ts->r28;
483 sv->save_r29 = ts->r29;
484 sv->save_r30 = ts->r30;
485 sv->save_r31 = ts->r31;
486
487 sv->save_cr = ts->cr;
488 sv->save_xer = ts->xer;
489 sv->save_lr = ts->lr;
490 sv->save_ctr = ts->ctr;
491 sv->save_srr0 = ts->srr0;
492 sv->save_mq = ts->mq;
493 sv->save_vrsave = ts->vrsave; /* VRSAVE register (Altivec only) */
494
495 sv->save_srr1 = MSR_PREPARE_FOR_IMPORT(sv->save_srr1, ts->srr1); /* Set the bits we can change */
496
497 if(!kernel_act) sv->save_srr1 |= MSR_EXPORT_MASK_SET; /* If not a kernel guy, force the magic bits on */
498
499 sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make sure we don't enable the floating point unit */
500
501 if(isnew) { /* Is it a new one? */
502 sv->save_dar = 0; /* Yes, these need initialization also */
503 sv->save_dsisr = 0;
504 sv->save_exception = 0;
505 }
506
507 return KERN_SUCCESS;
508 }
509 else { /* This must be exception state */
510 if(isnew) /* If new, we need to initialize the normal registers */
511 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
512 ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
513 ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
514 }
515 sv->save_cr = 0;
516 sv->save_xer = 0;
517 sv->save_lr = ((unsigned int *)&FloatInit)[0];
518 sv->save_ctr = ((unsigned int *)&FloatInit)[1];
519 sv->save_srr0 = ((unsigned int *)&FloatInit)[0];
520 sv->save_srr1 = MSR_EXPORT_MASK_SET;
521 sv->save_mq = 0;
522 sv->save_vrsave = 0; /* VRSAVE register (Altivec only) */
523 }
524
525 es = (struct ppc_exception_state *) tstate;
526
527 sv->save_dar = es->dar;
528 sv->save_dsisr = es->dsisr;
529 sv->save_exception = es->exception;
530
531 return KERN_SUCCESS;
532
533 case PPC_FLOAT_STATE:
534
535 spl = splhigh(); /* Don't bother me while I'm zapping the owner stuff */
536
537 if (per_proc_info[cpu_number()].FPU_thread == (unsigned int)thr_act) /* If we own the FPU, and */
538 if(!thr_act->mact.FPU_lvl) per_proc_info[cpu_number()].FPU_thread = 0; /* it's user level, say we don't own it any more */
539
540 splx(spl); /* Restore the interrupt level */
541
542 sv = (savearea *)thr_act->mact.FPU_pcb; /* Get the top savearea on the stack */
543 osv = 0; /* Set no user savearea yet */
544
545 if(sv && (sv->save_level_fp == 1)) { /* Is the first savearea invalid? */
546 thr_act->mact.FPU_pcb = (pcb_t)sv->save_prev_float; /* Yes, clean it out */
547 sv->save_flags &= ~SAVfpuvalid; /* Clear the floating point flag */
548 if(!(sv->save_flags & SAVinuse)) { /* Anyone left with this one? */
549 save_release(sv); /* Nope, release it */
550 }
551 sv = (savearea *)thr_act->mact.FPU_pcb; /* Get the new top savearea on the stack */
552 }
553
554 while(sv) { /* Find the user context */
555 if(!(sv->save_level_fp)) { /* Are we looking at the user context? */
556 break; /* Outta here */
557 }
558 osv = sv; /* Save the last one */
559 sv = sv->save_prev_float; /* Get the previous context */
560 }
561
562 if(!sv) { /* We didn't find a user context so allocate and initialize one */
563
564 sv = (savearea *)thr_act->mact.pcb; /* Point to the top savearea on the normal stack */
565
566 while(sv) { /* Have we hit the end? */
567 if(!(sv->save_flags & SAVfpuvalid)) break; /* Is floating point in use here? */
568 sv = sv->save_prev; /* Back chain */
569 }
570
571 if(!sv) { /* If there wasn't one on the normal chain, check vector */
572 sv = (savearea *)thr_act->mact.VMX_pcb; /* Point to the top savearea on the vector stack */
573 while(sv) { /* Have we hit the end? */
574 if(!(sv->save_flags & SAVfpuvalid)) break; /* Is floating point in use here? */
575 sv = sv->save_prev_vector; /* Back chain */
576 }
577 }
578
579 if(!sv) { /* Do we have one yet? */
580 sv = save_alloc(); /* If we still don't have one, get a new one */
581 sv->save_act = thr_act; /* Point to the activation */
582
583 spc=(unsigned int)thr_act->map->pmap->space; /* Get the space we're in */
584
585 srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
586 for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
587 srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
588 }
589
590 sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
591 }
592
593 if(osv) { /* Did we already have one? */
594 osv->save_prev_float = sv; /* Chain us on the end */
595 }
596 else { /* We are the first */
597 thr_act->mact.FPU_pcb = (pcb_t)sv; /* Put it there */
598 }
599 sv->save_prev_float = 0; /* Properly terminate the chain */
600 sv->save_level_fp = 0; /* Make sure we are for the user level */
601 sv->save_flags |= SAVfpuvalid; /* Say that it is in use by floating point */
602 }
603
604 fs = (struct ppc_float_state *) tstate; /* Point to source */
605
606
607 bcopy((char *)fs, (char *)&sv->save_fp0, clgn*4); /* 32 registers plus status and pad */
608
609 usv = find_user_regs(thr_act); /* Find the user registers */
610 if(!usv) usv = get_user_regs(thr_act); /* Didn't find any, allocate and initialize one */
611
612 usv->save_xfpscrpad = sv->save_fpscr_pad; /* Copy the pad value to normal */
613 usv->save_xfpscr = sv->save_fpscr; /* Copy the fpscr value to normal */
614
615 return KERN_SUCCESS;
616
617
618 case PPC_VECTOR_STATE:
619
620 spl = splhigh(); /* Don't bother me while I'm zapping the owner stuff */
621
622 if (per_proc_info[cpu_number()].VMX_thread == (unsigned int)thr_act) /* If we own the vector, and */
623 if(!thr_act->mact.VMX_lvl) per_proc_info[cpu_number()].VMX_thread = 0; /* it's user level, say we don't own it any more */
624
625 splx(spl); /* Restore the interrupt level */
626
627 sv = (savearea *)thr_act->mact.VMX_pcb; /* Get the top savearea on the stack */
628 osv = 0; /* Set no user savearea yet */
629
630 if(sv && (sv->save_level_vec == 1)) { /* Is the first savearea invalid? */
631 thr_act->mact.VMX_pcb = (pcb_t)sv->save_prev_vector; /* Yes, clean it out */
632 sv->save_flags &= ~SAVvmxvalid; /* Clear the floating point flag */
633 if(!(sv->save_flags & SAVinuse)) { /* Anyone left with this one? */
634 save_release(sv); /* Nope, release it */
635 }
636 sv = (savearea *)thr_act->mact.VMX_pcb; /* Get the new top savearea on the stack */
637 }
638
639 while(sv) { /* Find the user context */
640 if(!(sv->save_level_vec)) { /* Are we looking at the user context? */
641 break; /* Outta here */
642 }
643 osv = sv; /* Save the last one */
644 sv = sv->save_prev_vector; /* Get the previous context */
645 }
646
647 if(!sv) { /* We didn't find a user context so allocate and initialize one */
648
649 sv = (savearea *)thr_act->mact.pcb; /* Point to the top savearea on the normal stack */
650
651 while(sv) { /* Have we hit the end? */
652 if(!(sv->save_flags & SAVvmxvalid)) break; /* Is vector in use here? */
653 sv = sv->save_prev; /* Back chain */
654 }
655
656 if(!sv) { /* If there wasn't one on the normal chain, check vector */
657 sv = (savearea *)thr_act->mact.FPU_pcb; /* Point to the top savearea on the FPU stack */
658 while(sv) { /* Have we hit the end? */
659 if(!(sv->save_flags & SAVvmxvalid)) break; /* Is vector in use here? */
660 sv = sv->save_prev_float; /* Get the previous context */
661 }
662 }
663
664 if(!sv) { /* Do we have one yet? */
665 sv = save_alloc(); /* If we still don't have one, get a new one */
666 sv->save_act = thr_act; /* Point to the activation */
667
668 spc=(unsigned int)thr_act->map->pmap->space; /* Get the space we're in */
669
670 srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
671 for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
672 srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
673 }
674
675 sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
676 }
677
678 if(osv) { /* Did we already have one? */
679 osv->save_prev_vector = sv; /* Chain us on the end */
680 }
681 else { /* We are the first */
682 thr_act->mact.VMX_pcb = (pcb_t)sv; /* Put it there */
683 }
684 sv->save_prev_vector = 0; /* Properly terminate the chain */
685 sv->save_level_vec = 0; /* Make sure we are for the user level */
686 sv->save_flags |= SAVvmxvalid; /* Say that it is in use by vector */
687 }
688
689
690 vs = (struct ppc_vector_state *) tstate; /* Point to source */
691
692 bcopy((char *)vs, (char *)&sv->save_vr0, clgn*4); /* 32 registers plus status and validity and pad */
693
694 return KERN_SUCCESS;
695
696
697 default:
698 return KERN_INVALID_ARGUMENT;
699 }
700 }
701
702 /*
703 * Duplicates the context of one thread into a new one.
704 * The new thread is assumed to be new and have no user state contexts.
705 * We also assume that the old thread can't be running anywhere.
706 *
707 * We're only going to be duplicating user context here. That means that we will have to
708 * eliminate any floating point or vector kernel contexts and carry across the user state ones.
709 * We will optimize and cram all states into one savearea. Actually that will be the easiest thing
710 * to do.
711 */
712
713 void act_thread_dup(thread_act_t old, thread_act_t new) {
714
715 savearea *sv, *osv, *fsv;
716 unsigned int spc, i, *srs;
717
718 fpu_save(old); /* Make certain floating point state is all saved */
719 vec_save(old); /* Make certain the vector state is all saved */
720
721 osv = (savearea *)new->mact.pcb; /* Get the top savearea on the stack */
722 sv = 0; /* Set no new user savearea yet */
723
724 while(osv) { /* Find the user context */
725 if(osv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
726 sv=osv; /* Say which to use */
727 break; /* Outta here */
728 }
729 osv=osv->save_prev; /* Get the previous context */
730 }
731
732 if(!sv) { /* We didn't find a user context so allocate and initialize one */
733 osv = (savearea *)new->mact.pcb; /* Point to the top savearea on the stack */
734 sv = save_alloc(); /* Get one */
735 sv->save_flags |= SAVattach; /* Say that it is in use */
736 sv->save_act = new; /* Point to the activation */
737
738 spc=(unsigned int)new->map->pmap->space; /* Get the space we're in */
739
740 srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
741 for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
742 srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
743 }
744
745 sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
746
747 if(osv) { /* Did we already have one? */
748 sv->save_prev = osv->save_prev; /* Move the back chain of the top savearea */
749 osv->save_prev = sv; /* Chain us just after it */
750 }
751 else { /* We are the first */
752 new->mact.pcb = (pcb_t)sv; /* Make it the active one */
753 }
754
755 }
756
757 osv = (savearea *)(old->mact.pcb); /* Start with the normal savearea */
758 while(osv) { /* Find the user context */
759 if(osv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
760 break; /* Outta here */
761 }
762 osv = osv->save_prev; /* Back chain */
763 }
764
765 bcopy((char *)&osv->save_srr0, (char *)&sv->save_srr0, sizeof(struct ppc_thread_state)); /* Copy in normal state stuff */
766
767 sv->save_xfpscrpad = osv->save_xfpscrpad; /* Copy the pad value to old */
768 sv->save_xfpscr = osv->save_xfpscr; /* Copy the fpscr value to old */
769
770 new->mact.FPU_pcb = (pcb_t)0 ; /* Initialize floating point savearea */
771 new->mact.FPU_lvl = (pcb_t)0 ; /* Initialize floating point level */
772 new->mact.FPU_cpu = 0 ; /* Initialize last used cpu (FP not live, so this doesn't really matter) */
773 new->mact.VMX_pcb = (pcb_t)0 ; /* Initialize vector savearea */
774 new->mact.VMX_lvl = (pcb_t)0 ; /* Initialize vector level */
775 new->mact.VMX_cpu = 0 ; /* Initialize last used cpu (vector not live, so this doesn't reall matter) */
776
777 sv->save_prev_float = (savearea *)0; /* Clear the back chain */
778 sv->save_prev_vector = (savearea *)0; /* Clear the back chain */
779 sv->save_level_fp = 0; /* Set the level for FP */
780 sv->save_level_vec = 0; /* Set the level for vector */
781
782 sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make certain that floating point and vector are turned off */
783
784 fsv = (savearea *)old->mact.FPU_pcb; /* Get the start of the floating point chain */
785 while(fsv) { /* Look until the end or we find it */
786 if(!(fsv->save_level_fp)) { /* Is the the user state stuff? (the level is 0 if so) */
787 sv->save_flags |= SAVfpuvalid; /* Show we have it */
788 bcopy((char *)&osv->save_fp0, (char *)&sv->save_fp0, sizeof(struct ppc_float_state)); /* Copy in floating point state stuff */
789 new->mact.FPU_pcb = (pcb_t)sv; /* Make it the active one */
790 break; /* Done, everything else is all set up... */
791 }
792 fsv = fsv->save_prev_float; /* Try the previous one */
793 }
794
795 fsv = (savearea *)old->mact.VMX_pcb; /* Get the start of the vector chain */
796 while(fsv) { /* Look until the end or we find it */
797 if(!(fsv->save_level_vec)) { /* Is the the user state stuff? (the level is 0 if so) */
798 sv->save_flags |= SAVvmxvalid; /* Show we have it */
799 bcopy((char *)&osv->save_vr0, (char *)&sv->save_vr0, sizeof(struct ppc_vector_state)); /* Copy in Altivec state stuff */
800 new->mact.VMX_pcb = (pcb_t)sv; /* Make it the active one */
801 break; /* Done, everything else is all set up... */
802 }
803 fsv = fsv->save_prev_vector; /* Try the previous one */
804 }
805
806 return; /* Bye bye... */
807 }
808
809 /*
810 * Initializes a fresh set of user state values. If there is no user state context,
811 * one is created. Floats and VMX are not created. We set initial values for everything.
812 */
813
814 struct ppc_saved_state * get_user_regs(thread_act_t act) {
815
816 savearea *sv, *osv;
817 unsigned int spc, i, *srs;
818
819 sv = (savearea *)act->mact.pcb; /* Get the top savearea on the stack */
820 osv = 0; /* Set no user savearea yet */
821
822 while(sv) { /* Find the user context */
823 if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
824 break; /* Outta here */
825 }
826 osv = sv; /* Save the last one */
827 sv = sv->save_prev; /* Get the previous context */
828 }
829
830 if(!sv) { /* We didn't find a user context so allocate and initialize one */
831 sv = save_alloc(); /* Get one */
832 sv->save_flags |= SAVattach; /* Say that it is in use */
833 sv->save_act = act; /* Point to the activation */
834
835 if(osv) { /* Did we already have one? */
836 osv->save_prev = sv; /* Chain us on the end */
837 }
838 else { /* We are the first */
839 act->mact.pcb = (pcb_t)sv; /* Put it there */
840 }
841 sv->save_prev = 0; /* Properly terminate the chain */
842 }
843
844 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
845 ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
846 ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
847 }
848 sv->save_cr = 0;
849 sv->save_xer = 0;
850 sv->save_lr = ((unsigned int *)&FloatInit)[0];
851 sv->save_ctr = ((unsigned int *)&FloatInit)[1];
852 sv->save_srr0 = ((unsigned int *)&FloatInit)[0];
853 sv->save_srr1 = MSR_EXPORT_MASK_SET;
854 sv->save_mq = 0;
855 sv->save_vrsave = 0; /* VRSAVE register (Altivec only) */
856 sv->save_xfpscrpad = 0; /* Start with a clear fpscr */
857 sv->save_xfpscr = 0; /* Start with a clear fpscr */
858
859 spc=(unsigned int)act->map->pmap->space; /* Get the space we're in */
860
861 srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
862 for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
863 srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
864 }
865
866 sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
867
868 return (struct ppc_saved_state *)sv; /* Bye bye... */
869 }
870
871 /*
872 * Find the user state context. If there is no user state context,
873 * we just return a 0.
874 */
875
876 struct ppc_saved_state * find_user_regs(thread_act_t act) {
877
878 savearea *sv;
879
880 sv = (savearea *)act->mact.pcb; /* Get the top savearea on the stack */
881
882 while(sv) { /* Find the user context */
883 if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
884 break; /* Outta here */
885 }
886 sv = sv->save_prev; /* Get the previous context */
887 }
888
889 return (struct ppc_saved_state *)sv; /* Bye bye... */
890 }
891
892 /*
893 * Find the user state floating pointcontext. If there is no user state context,
894 * we just return a 0.
895 */
896
897 struct ppc_float_state * find_user_fpu(thread_act_t act) {
898
899 savearea *fsv;
900
901 fsv = (savearea *)act->mact.FPU_pcb; /* Get the start of the floating point chain */
902 while(fsv) { /* Look until the end or we find it */
903 if(!(fsv->save_level_fp)) break; /* Is the the user state stuff? (the level is 0 if so) */
904 fsv = fsv->save_prev_float; /* Try the previous one */
905 }
906
907 return (struct ppc_float_state *)&(fsv->save_fp0); /* Bye bye... */
908 }
909
910 /*
911 * thread_userstack:
912 *
913 * Return the user stack pointer from the machine
914 * dependent thread state info.
915 */
916 kern_return_t
917 thread_userstack(
918 thread_t thread,
919 int flavor,
920 thread_state_t tstate,
921 unsigned int count,
922 vm_offset_t *user_stack,
923 int *customstack
924 )
925 {
926 struct ppc_thread_state *state;
927
928 /*
929 * Set a default.
930 */
931 if (*user_stack == 0)
932 *user_stack = USRSTACK;
933 if (customstack)
934 *customstack = 0;
935
936 switch (flavor) {
937 case PPC_THREAD_STATE:
938 if (count < PPC_THREAD_STATE_COUNT)
939 return (KERN_INVALID_ARGUMENT);
940
941 state = (struct ppc_thread_state *) tstate;
942
943 /*
944 * If a valid user stack is specified, use it.
945 */
946 *user_stack = state->r1 ? state->r1: USRSTACK;
947
948 if (customstack && state->r1)
949 *customstack = 1;
950
951 break;
952 default :
953 return (KERN_INVALID_ARGUMENT);
954 }
955
956 return (KERN_SUCCESS);
957 }
958
959 kern_return_t
960 thread_entrypoint(
961 thread_t thread,
962 int flavor,
963 thread_state_t tstate,
964 unsigned int count,
965 vm_offset_t *entry_point
966 )
967 {
968 struct ppc_thread_state *state;
969
970 /*
971 * Set a default.
972 */
973 if (*entry_point == 0)
974 *entry_point = VM_MIN_ADDRESS;
975
976 switch (flavor) {
977
978 case PPC_THREAD_STATE:
979 if (count < PPC_THREAD_STATE_COUNT)
980 return (KERN_INVALID_ARGUMENT);
981
982 state = (struct ppc_thread_state *) tstate;
983
984 /*
985 * If a valid entry point is specified, use it.
986 */
987 *entry_point = state->srr0 ? state->srr0: VM_MIN_ADDRESS;
988 break;
989 default:
990 return (KERN_INVALID_ARGUMENT);
991 }
992
993 return (KERN_SUCCESS);
994 }
995
996 unsigned int get_msr_exportmask(void)
997 {
998 return (MSR_EXPORT_MASK_SET);
999 }
1000
1001 unsigned int get_msr_nbits(void)
1002 {
1003 return (MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
1004 }
1005 unsigned int get_msr_rbits(void)
1006 {
1007 return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
1008 }
1009
1010 void thread_set_child(thread_act_t child, int pid)
1011 {
1012 struct ppc_saved_state *child_state;
1013
1014 child_state = find_user_regs(child);
1015
1016 child_state->r3 = pid;
1017 child_state->r4 = 1;
1018 }
1019 void thread_set_parent(thread_act_t parent, int pid)
1020 {
1021 struct ppc_saved_state *parent_state;
1022
1023 parent_state = find_user_regs(parent);
1024
1025 parent_state->r3 = pid;
1026 parent_state->r4 = 0;
1027 }
1028
1029 /*
1030 * Saves the complete context (general, floating point, and vector) of the current activation.
1031 * We will collect everything into one savearea and pass that back.
1032 *
1033 * The savearea is made to look like it belongs to the source activation. This needs to
1034 * be adjusted when these contexts are attached to a new activation.
1035 *
1036 */
1037
1038 void *act_thread_csave(void) {
1039
1040 savearea *sv, *osv, *fsv;
1041 unsigned int spc, i, *srs;
1042
1043 thread_act_t act;
1044
1045 fpu_save(current_act()); /* Make certain floating point state is all saved */
1046 vec_save(current_act()); /* Make certain the vector state is all saved */
1047
1048 sv = save_alloc(); /* Get a fresh save area */
1049 hw_atomic_add(&saveanchor.saveneed, 1); /* Account for the extra saveareas "need" */
1050
1051 act = current_act(); /* Find ourselves */
1052
1053 sv->save_flags |= SAVattach; /* Say that it is in use */
1054 sv->save_act = act; /* Point to the activation */
1055
1056 spc=(unsigned int)act->map->pmap->space; /* Get the space we're in */
1057
1058 srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
1059 for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
1060 srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
1061 }
1062
1063 sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
1064
1065 osv = (savearea *)(act->mact.pcb); /* Start with the normal savearea */
1066 fsv = 0; /* Assume none */
1067 while(osv) { /* Find the user context */
1068 if(osv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
1069 fsv = osv; /* Remember what we found */
1070 break; /* Outta here */
1071 }
1072 osv = osv->save_prev; /* Back chain */
1073 }
1074
1075 if(!fsv) { /* Did we find one? */
1076 for(i=0; i < 32; i+=2) { /* Fill up with defaults */
1077 ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
1078 ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
1079 }
1080 sv->save_cr = 0;
1081 sv->save_xer = 0;
1082 sv->save_lr = ((unsigned int *)&FloatInit)[0];
1083 sv->save_ctr = ((unsigned int *)&FloatInit)[1];
1084 sv->save_srr0 = ((unsigned int *)&FloatInit)[0];
1085 sv->save_srr1 = MSR_EXPORT_MASK_SET;
1086 sv->save_mq = 0;
1087 sv->save_vrsave = 0; /* VRSAVE register (Altivec only) */
1088 sv->save_xfpscrpad = 0; /* Start with a clear fpscr */
1089 sv->save_xfpscr = 0; /* Start with a clear fpscr */
1090 }
1091 else { /* We did find one, copy it */
1092 bcopy((char *)&fsv->save_srr0, (char *)&sv->save_srr0, sizeof(struct ppc_thread_state)); /* Copy in normal state stuff */
1093 sv->save_xfpscrpad = osv->save_xfpscrpad; /* Copy the pad value to old */
1094 sv->save_xfpscr = osv->save_xfpscr; /* Copy the fpscr value to old */
1095 }
1096
1097
1098 sv->save_prev = (savearea *)0xDEBB1ED0; /* Eye catcher for debug */
1099 sv->save_prev_float = (savearea *)0xE5DA11A5; /* Eye catcher for debug */
1100 sv->save_prev_vector = (savearea *)0; /* Clear */
1101 sv->save_level_fp = 0; /* Set the level for FP */
1102 sv->save_level_vec = 0; /* Set the level for vector */
1103
1104 sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make certain that floating point and vector are turned off */
1105
1106 fsv = (savearea *)act->mact.FPU_pcb; /* Get the start of the floating point chain */
1107 while(fsv) { /* Look until the end or we find it */
1108 if(!(fsv->save_level_fp)) { /* Is the the user state stuff? (the level is 0 if so) */
1109 sv->save_flags |= SAVfpuvalid; /* Show we have it */
1110 bcopy((char *)&fsv->save_fp0, (char *)&sv->save_fp0, sizeof(struct ppc_float_state)); /* Copy in floating point state stuff */
1111 break; /* Done, everything else is all set up... */
1112 }
1113 fsv = fsv->save_prev_float; /* Try the previous one */
1114 }
1115
1116 fsv = (savearea *)act->mact.VMX_pcb; /* Get the start of the vector chain */
1117 while(fsv) { /* Look until the end or we find it */
1118 if(!(fsv->save_level_vec)) { /* Is the the user state stuff? (the level is 0 if so) */
1119 sv->save_flags |= SAVvmxvalid; /* Show we have it */
1120 bcopy((char *)&fsv->save_vr0, (char *)&sv->save_vr0, sizeof(struct ppc_vector_state)); /* Copy in Altivec state stuff */
1121 break; /* Done, everything else is all set up... */
1122 }
1123 fsv = fsv->save_prev_vector; /* Try the previous one */
1124 }
1125
1126 return (void *)sv; /* Bye bye... */
1127 }
1128
1129
1130
1131 /*
1132 * Attaches saved user state context to an activation. We will replace any
1133 * user state context with what is passed in. The saved context consists of a
1134 * savearea that was setup by
1135 * We will collect everything into one savearea and pass that back.
1136 *
1137 * The savearea is made to look like it belongs to the source activation. This needs to
1138 * be adjusted when these contexts are attached to a new activation.
1139 *
1140 */
1141
1142 void act_thread_catt(void *ctx) {
1143
1144 savearea *sv, *osv, *fsv, *psv;
1145 unsigned int spc, i, *srs;
1146 thread_act_t act;
1147
1148 sv = (savearea *)ctx; /* Make this easier for C */
1149
1150 if((sv->save_prev != (savearea *)0xDEBB1ED0) || (sv->save_prev_float != (savearea *)0xE5DA11A5)) { /* See if valid savearea */
1151 panic("act_thread_catt: attempt to attach invalid context savearea - %08X\n", sv); /* Die */
1152 }
1153
1154 act = current_act(); /* Find ourselves */
1155
1156 /*
1157 * This next bit insures that any live facility context for this thread is discarded on every processor
1158 * that may have it.
1159 *
1160 * Note that this will not be good if the activation has any kernel fp or vec contexts that are live.
1161 * We won't worry about it because it would be silly to call this if we are a kernel task using altivec
1162 * or floating point......
1163 */
1164
1165 for(i=0; i < real_ncpus; i++) { /* Cycle through processors */
1166 (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */
1167 (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].VMX_thread); /* Clear if ours */
1168 }
1169
1170
1171 /*
1172 * Now we make the savearea look like we own it
1173 */
1174
1175 sv->save_prev = (savearea *)0; /* Clear */
1176 sv->save_prev_float = (savearea *)0; /* Clear */
1177 sv->save_prev_vector = (savearea *)0; /* Clear */
1178 sv->save_act = act; /* Point to the activation */
1179
1180 spc=(unsigned int)act->map->pmap->space; /* Get the space we're in */
1181
1182 srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
1183 for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
1184 srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SRs */
1185 }
1186
1187 sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
1188
1189 osv = (savearea *)act->mact.VMX_pcb; /* Get the top vector savearea */
1190
1191 if(osv && (osv->save_level_vec == 1)) { /* Is the first one a special dummy one? */
1192 psv = osv; /* Yes, remember it */
1193 osv = osv->save_prev_vector; /* Step to the next */
1194 (savearea *)act->mact.VMX_pcb = osv; /* Dequeue it */
1195 psv->save_flags &= ~SAVvmxvalid; /* Clear the VMX flag */
1196 if(!(psv->save_flags & SAVinuse)) { /* Anyone left with this one? */
1197 save_release(psv); /* Nope, release it */
1198 }
1199 }
1200
1201 psv = 0;
1202 while(osv) { /* Any VMX saved state? */
1203 if(!(osv->save_level_vec)) break; /* Leave if this is user state */
1204 psv = osv; /* Save previous savearea address */
1205 osv = osv->save_prev_vector; /* Get one underneath our's */
1206 }
1207
1208 if(osv) { /* Did we find one? */
1209 if(psv) psv->save_prev_vector = 0; /* Yes, clear pointer to it (it should always be last) or */
1210 else act->mact.VMX_pcb = 0; /* to the start if the only one */
1211
1212 osv->save_flags &= ~SAVvmxvalid; /* Clear the VMX flag */
1213 if(!(osv->save_flags & SAVinuse)) { /* Anyone left with this one? */
1214 save_release(osv); /* Nope, release it */
1215 }
1216 }
1217
1218 if(sv->save_flags & SAVvmxvalid) { /* Are we adding Altivec context? */
1219 if(psv) psv->save_prev_vector = sv; /* Yes, chain us to the end or */
1220 else act->mact.VMX_pcb = (pcb_t)sv; /* to the start if the only one */
1221 }
1222
1223 osv = (savearea *)act->mact.FPU_pcb; /* Get the top floating point savearea */
1224
1225 if(osv && (osv->save_level_fp == 1)) { /* Is the first one a special dummy one? */
1226 psv = osv; /* Yes, remember it */
1227 osv = osv->save_prev_float; /* Step to the next */
1228 (savearea *)act->mact.FPU_pcb = osv; /* Dequeue it */
1229 psv->save_flags &= ~SAVfpuvalid; /* Clear the float flag */
1230 if(!(psv->save_flags & SAVinuse)) { /* Anyone left with this one? */
1231 save_release(psv); /* Nope, release it */
1232 }
1233 }
1234
1235 psv = 0;
1236 while(osv) { /* Any floating point saved state? */
1237 if(!(osv->save_level_fp)) break; /* Leave if this is user state */
1238 psv = osv; /* Save previous savearea address */
1239 osv = osv->save_prev_float; /* Get one underneath our's */
1240 }
1241
1242 if(osv) { /* Did we find one? */
1243 if(psv) psv->save_prev_float = 0; /* Yes, clear pointer to it (it should always be last) or */
1244 else act->mact.FPU_pcb = 0; /* to the start if the only one */
1245
1246 osv->save_flags &= ~SAVfpuvalid; /* Clear the floating point flag */
1247 if(!(osv->save_flags & SAVinuse)) { /* Anyone left with this one? */
1248 save_release(osv); /* Nope, release it */
1249 }
1250 }
1251
1252 if(sv->save_flags & SAVfpuvalid) { /* Are we adding floating point context? */
1253 if(psv) psv->save_prev_float = sv; /* Yes, chain us to the end or */
1254 else act->mact.FPU_pcb = (pcb_t)sv; /* to the start if the only one */
1255 }
1256
1257 osv = (savearea *)act->mact.pcb; /* Get the top general savearea */
1258 psv = 0;
1259 while(osv) { /* Any floating point saved state? */
1260 if(osv->save_srr1 & MASK(MSR_PR)) break; /* Leave if this is user state */
1261 psv = osv; /* Save previous savearea address */
1262 osv = osv->save_prev; /* Get one underneath our's */
1263 }
1264
1265 if(osv) { /* Did we find one? */
1266 if(psv) psv->save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */
1267 else act->mact.pcb = 0; /* to the start if the only one */
1268
1269 osv->save_flags &= ~SAVattach; /* Clear the attached flag */
1270 if(!(osv->save_flags & SAVinuse)) { /* Anyone left with this one? */
1271 save_release(osv); /* Nope, release it */
1272 }
1273 }
1274
1275 if(psv) psv->save_prev = sv; /* Chain us to the end or */
1276 else act->mact.pcb = (pcb_t)sv; /* to the start if the only one */
1277
1278 hw_atomic_sub(&saveanchor.saveneed, 1); /* Unaccount for the savearea we think we "need" */
1279 }
1280
1281
1282
1283 /*
1284 * Releases saved context. We need this because the saved context is opague.
1285 * be adjusted when these contexts are attached to a new activation.
1286 *
1287 */
1288
1289 void act_thread_cfree(void *ctx) {
1290
1291 if((((savearea *)ctx)->save_prev != (savearea *)0xDEBB1ED0) ||
1292 (((savearea *)ctx)->save_prev_float != (savearea *)0xE5DA11A5)) { /* See if valid savearea */
1293 panic("act_thread_cfree: attempt to free invalid context savearea - %08X\n", ctx); /* Die */
1294 }
1295
1296 ((savearea *)ctx)->save_flags = 0; /* Clear all flags since we release this in any case */
1297 save_release((savearea *)ctx); /* Release this one */
1298 hw_atomic_sub(&saveanchor.saveneed, 1); /* Unaccount for the savearea we think we "need" */
1299
1300 return;
1301 }