|
|
1.1 root 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:
46:
47: struct ppc_saved_state * get_user_regs(thread_act_t);
48:
49: #define USRSTACK 0xc0000000
50:
51: kern_return_t
52: thread_userstack(
53: thread_t,
54: int,
55: thread_state_t,
56: unsigned int,
57: vm_offset_t *
58: );
59:
60: kern_return_t
61: thread_entrypoint(
62: thread_t,
63: int,
64: thread_state_t,
65: unsigned int,
66: vm_offset_t *
67: );
68:
69: unsigned int get_msr_exportmask(void);
70: unsigned int get_msr_nbits(void);
71: unsigned int get_msr_rbits(void);
72: void thread_set_child(thread_act_t child, int pid);
73:
74: /*
75: * Maps state flavor to number of words in the state:
76: */
77: unsigned int state_count[] = {
78: /* FLAVOR_LIST */ 0,
79: PPC_THREAD_STATE_COUNT,
80: PPC_FLOAT_STATE_COUNT,
81: PPC_EXCEPTION_STATE_COUNT,
82: };
83:
84: /*
85: * thread_getstatus:
86: *
87: * Get the status of the specified thread.
88: */
89:
90: kern_return_t
91: act_machine_get_state(
92: thread_act_t thr_act,
93: thread_flavor_t flavor,
94: thread_state_t tstate,
95: mach_msg_type_number_t *count)
96: {
97:
98: register struct savearea *sv; /* Pointer to the context savearea */
99: int i, j;
100: unsigned int vrvalidwrk;
101:
102: register struct ppc_thread_state *ts;
103: register struct ppc_exception_state *es;
104: register struct ppc_float_state *fs;
105: register struct ppc_vector_state *vs;
106:
107: #if MACH_ASSERT
108: if (watchacts & WA_STATE)
109: printf("act_%x act_machine_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n",
110: current_act(), thr_act, flavor, tstate,
111: count, (count ? *count : 0));
112: #endif /* MACH_ASSERT */
113:
114:
115: switch (flavor) {
116:
117: case THREAD_STATE_FLAVOR_LIST:
118:
119: if (*count < 3) {
120: panic("act_machine_get_state: THREAD_STATE_FLAVOR_LIST returns KERN_INVALID_ARGUMENT\n");
121: return (KERN_INVALID_ARGUMENT);
122: }
123:
124: tstate[0] = PPC_THREAD_STATE;
125: tstate[1] = PPC_FLOAT_STATE;
126: tstate[2] = PPC_EXCEPTION_STATE;
127: *count = 3;
128:
129: return KERN_SUCCESS;
130:
131: case PPC_THREAD_STATE:
132:
133: if (*count < PPC_THREAD_STATE_COUNT) { /* Is the count ok? */
134: panic("act_machine_get_state: PPC_THREAD_STATE returns KERN_INVALID_ARGUMENT\n");
135: return KERN_INVALID_ARGUMENT;
136: }
137:
138: ts = (struct ppc_thread_state *) tstate;
139:
140: sv = (savearea *)(thr_act->mact.pcb); /* Start with the normal savearea */
141: while(sv) { /* Find the user context */
142: if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
143: break; /* Outta here */
144: }
145: sv = sv->save_prev; /* Back chain */
146: }
147:
148: if(sv) { /* Is there a save area yet? */
149: ts->r0 = sv->save_r0;
150: ts->r1 = sv->save_r1;
151: ts->r2 = sv->save_r2;
152: ts->r3 = sv->save_r3;
153: ts->r4 = sv->save_r4;
154: ts->r5 = sv->save_r5;
155: ts->r6 = sv->save_r6;
156: ts->r7 = sv->save_r7;
157: ts->r8 = sv->save_r8;
158: ts->r9 = sv->save_r9;
159: ts->r10 = sv->save_r10;
160: ts->r11 = sv->save_r11;
161: ts->r12 = sv->save_r12;
162: ts->r13 = sv->save_r13;
163: ts->r14 = sv->save_r14;
164: ts->r15 = sv->save_r15;
165: ts->r16 = sv->save_r16;
166: ts->r17 = sv->save_r17;
167: ts->r18 = sv->save_r18;
168: ts->r19 = sv->save_r19;
169: ts->r20 = sv->save_r20;
170: ts->r21 = sv->save_r21;
171: ts->r22 = sv->save_r22;
172: ts->r23 = sv->save_r23;
173: ts->r24 = sv->save_r24;
174: ts->r25 = sv->save_r25;
175: ts->r26 = sv->save_r26;
176: ts->r27 = sv->save_r27;
177: ts->r28 = sv->save_r28;
178: ts->r29 = sv->save_r29;
179: ts->r30 = sv->save_r30;
180: ts->r31 = sv->save_r31;
181: ts->cr = sv->save_cr;
182: ts->xer = sv->save_xer;
183: ts->lr = sv->save_lr;
184: ts->ctr = sv->save_ctr;
185: ts->srr0 = sv->save_srr0;
186: ts->srr1 = sv->save_srr1;
187: ts->mq = sv->save_mq; /* MQ register (601 only) */
188: ts->vrsave = sv->save_vrsave; /* VRSAVE register (Altivec only) */
189: }
190: else { /* No user state yet. Save seemingly random values. */
191:
192: for(i=0; i < 32; i+=2) { /* Fill up with defaults */
193: ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
194: ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
195: }
196: ts->cr = 0;
197: ts->xer = 0;
198: ts->lr = ((unsigned int *)&FloatInit)[0];
199: ts->ctr = ((unsigned int *)&FloatInit)[1];
200: ts->srr0 = ((unsigned int *)&FloatInit)[0];
201: ts->srr1 = MSR_EXPORT_MASK_SET;
202: ts->mq = 0;
203: ts->vrsave = 0; /* VRSAVE register (Altivec only) */
204: }
205:
206: *count = PPC_THREAD_STATE_COUNT; /* Pass back the amount we actually copied */
207: return KERN_SUCCESS;
208:
209: case PPC_EXCEPTION_STATE:
210:
211: if (*count < PPC_EXCEPTION_STATE_COUNT) {
212: panic("act_machine_get_state: PPC_EXCEPTION_STATE returns KERN_INVALID_ARGUMENT\n");
213: return KERN_INVALID_ARGUMENT;
214: }
215:
216: es = (struct ppc_exception_state *) tstate;
217:
218: sv = (savearea *)(thr_act->mact.pcb); /* Start with the normal savearea */
219: while(sv) { /* Find the user context */
220: if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
221: break; /* Outta here */
222: }
223: sv = sv->save_prev; /* Back chain */
224: }
225:
226: if(sv) { /* See if valid state yet */
227: es->dar = sv->save_dar;
228: es->dsisr = sv->save_dsisr;
229: es->exception = sv->save_exception;
230: }
231: else { /* Nope, not yet */
232: es->dar = 0;
233: es->dsisr = 0;
234: es->exception = ((unsigned int *)&FloatInit)[0];
235: }
236:
237: *count = PPC_EXCEPTION_STATE_COUNT;
238: return KERN_SUCCESS;
239:
240: case PPC_FLOAT_STATE:
241:
242: if (*count < PPC_FLOAT_STATE_COUNT) {
243: panic("act_machine_get_state: PPC_FLOAT_STATE returns KERN_INVALID_ARGUMENT\n");
244: return KERN_INVALID_ARGUMENT;
245: }
246:
247: fpu_save(); /* 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: #if 0
274: for(i=0; i < 32; i++) { /* (TEST/DEBUG) */
275: if((*((unsigned int *)&fs->fpregs[i]) >> 16) == 0xFFF8) __asm__ volatile ("tweq r1,r1"); /* (TEST/DEBUG) */
276: }
277: #endif
278:
279: return KERN_SUCCESS;
280:
281: case PPC_VECTOR_STATE:
282:
283: if (*count < PPC_VECTOR_STATE_COUNT) {
284: panic("act_machine_get_state: PPC_VECTOR_STATE returns KERN_INVALID_ARGUMENT\n");
285: return KERN_INVALID_ARGUMENT;
286: }
287:
288: vec_save(); /* Just in case it's live, save it */
289:
290: vs = (struct ppc_vector_state *) tstate; /* Point to destination */
291:
292: sv = (savearea *)(thr_act->mact.VMX_pcb); /* Start with the top FPU savearea */
293: while(sv) { /* Find the user context */
294: if(!sv->save_level_vec) { /* Are we looking at the user context? */
295: break; /* Outta here */
296: }
297: sv = sv->save_prev_vector; /* Back chain */
298: }
299:
300: if(sv) { /* See if we have any */
301:
302: vrvalidwrk = sv->save_vrvalid; /* Get the valid flags */
303: vs->save_vrvalid = sv->save_vrvalid; /* Set the valid flags */
304: for(j=0; j < 4; j++) vs->save_vscr[j] = sv->save_vscr[j]; /* Set value for vscr */
305:
306: for(i=0; i < 32; i++) { /* Copy the saved registers and invalidate the others */
307: for(j=0; j < 4; j++) {
308: if(vrvalidwrk & 0x80000000) (vs->save_vr)[i][j] =
309: ((unsigned long **)(&sv->save_vr0))[i][j]; /* We have this register saved */
310: else vs->save_vr[i][j] = QNaNbarbarian[j]; /* Set invalid value */
311: }
312: vrvalidwrk = vrvalidwrk << 1; /* Shift over to the next */
313: }
314: }
315: else { /* No vector yet */
316:
317: for(i=0; i < 32; i++) { /* Initialize vector registers */
318: for(j=0; j < 4; j++) vs->save_vr[i][j] = QNaNbarbarian[j]; /* Initial value */
319: }
320: for(j=0; j < 4; j++) vs->save_vscr[j] = 0; /* Initial value */
321: vs->save_vrvalid = 0; /* Clear the valid flags */
322: }
323:
324: for (i=0; i < 4; i++) vs->save_pad5[i] = 0; /* Clear cruft */
325: for (i=0; i < 7; i++) vs->save_pad6[i] = 0; /* Clear cruft */
326:
327: *count = PPC_VECTOR_STATE_COUNT;
328: return KERN_SUCCESS;
329:
330: default:
331: panic("act_machine_get_state: default returns KERN_INVALID_ARGUMENT\n");
332: return KERN_INVALID_ARGUMENT;
333: }
334: }
335:
336:
337: /*
338: * thread_setstatus:
339: *
340: * Set the status of the specified thread.
341: */
342: kern_return_t
343: act_machine_set_state(
344: thread_act_t thr_act,
345: thread_flavor_t flavor,
346: thread_state_t tstate,
347: mach_msg_type_number_t count)
348: {
349:
350: savearea *sv, *osv, *usv, *ssv;
351: unsigned int spc, i, *srs, isnew, clgn;
352: register struct ppc_thread_state *ts;
353: register struct ppc_exception_state *es;
354: register struct ppc_float_state *fs;
355: register struct ppc_vector_state *vs;
356: spl_t spl;
357:
358: int kernel_act = thr_act->kernel_loading || thr_act->kernel_loaded;
359:
360: #if MACH_ASSERT
361: if (watchacts & WA_STATE)
362: printf("act_%x act_machine_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n",
363: current_act(), thr_act, flavor, tstate, count);
364: #endif /* MACH_ASSERT */
365:
366: // dbgTrace((unsigned int)thr_act, (unsigned int)sv, flavor); /* (TEST/DEBUG) */
367:
368: clgn = count; /* Get the count */
369:
370: switch (flavor) { /* Validate the count before we do anything else */
371: case PPC_THREAD_STATE:
372:
373: if (clgn < PPC_THREAD_STATE_COUNT) { /* Is it too short? */
374: return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
375: }
376:
377: if(clgn > PPC_THREAD_STATE_COUNT) clgn = PPC_THREAD_STATE_COUNT; /* If too long, pin it at max */
378: break;
379:
380: case PPC_EXCEPTION_STATE:
381:
382: if (clgn < PPC_EXCEPTION_STATE_COUNT) { /* Is it too short? */
383: return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
384: }
385:
386: if(clgn > PPC_EXCEPTION_STATE_COUNT) clgn = PPC_EXCEPTION_STATE_COUNT; /* If too long, pin it at max */
387: break;
388:
389: case PPC_FLOAT_STATE:
390:
391: if (clgn < PPC_FLOAT_STATE_COUNT) { /* Is it too short? */
392: return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
393: }
394:
395: if(clgn > PPC_FLOAT_STATE_COUNT) clgn = PPC_FLOAT_STATE_COUNT; /* If too long, pin it at max */
396: break;
397:
398:
399: case PPC_VECTOR_STATE:
400:
401: if (clgn < PPC_VECTOR_STATE_COUNT) { /* Is it too short? */
402: return KERN_INVALID_ARGUMENT; /* Yeah, just leave... */
403: }
404:
405: if(clgn > PPC_VECTOR_STATE_COUNT) clgn = PPC_VECTOR_STATE_COUNT; /* If too long, pin it at max */
406: break;
407:
408: default:
409: return KERN_INVALID_ARGUMENT;
410: }
411:
412: isnew = 0; /* Remember when we make a new one */
413:
414: switch (flavor) {
415:
416: case PPC_THREAD_STATE:
417: case PPC_EXCEPTION_STATE:
418:
419: ts = (struct ppc_thread_state *)tstate;
420:
421: sv = (savearea *)thr_act->mact.pcb; /* Get the top savearea on the stack */
422: osv = 0; /* Set no user savearea yet */
423:
424: while(sv) { /* Find the user context */
425: if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
426: break; /* Outta here */
427: }
428: osv = sv; /* Save the last one */
429: sv = sv->save_prev; /* Get the previous context */
430: }
431:
432: if(!sv) { /* We didn't find a user context so allocate and initialize one */
433: isnew = 1; /* Remember we made a new one */
434: sv = save_alloc(); /* Get one */
435: sv->save_act = thr_act; /* Point to the activation */
436: sv->save_flags |= SAVattach; /* Say that it is in use */
437: sv->save_srr1 = MSR_EXPORT_MASK_SET & ~MASK(MSR_PR); /* Assume kernel state */
438:
439: spc=(unsigned int)thr_act->map->pmap->space; /* Get the space we're in */
440:
441: srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
442: for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
443: srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
444: }
445:
446: sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
447:
448: if(osv) { /* Did we already have one? */
449: osv->save_prev = sv; /* Chain us on the end */
450: }
451: else { /* We are the first */
452: thr_act->mact.pcb = (pcb_t)sv; /* Put it there */
453: }
454: sv->save_prev = 0; /* Properly terminate the chain */
455:
456: }
457:
458: if(flavor == PPC_THREAD_STATE) { /* Are we updating plain state? */
459:
460: sv->save_r0 = ts->r0;
461: sv->save_r1 = ts->r1;
462: sv->save_r2 = ts->r2;
463: sv->save_r3 = ts->r3;
464: sv->save_r4 = ts->r4;
465: sv->save_r5 = ts->r5;
466: sv->save_r6 = ts->r6;
467: sv->save_r7 = ts->r7;
468: sv->save_r8 = ts->r8;
469: sv->save_r9 = ts->r9;
470: sv->save_r10 = ts->r10;
471: sv->save_r11 = ts->r11;
472: sv->save_r12 = ts->r12;
473: sv->save_r13 = ts->r13;
474: sv->save_r14 = ts->r14;
475: sv->save_r15 = ts->r15;
476: sv->save_r16 = ts->r16;
477: sv->save_r17 = ts->r17;
478: sv->save_r18 = ts->r18;
479: sv->save_r19 = ts->r19;
480: sv->save_r20 = ts->r20;
481: sv->save_r21 = ts->r21;
482: sv->save_r22 = ts->r22;
483: sv->save_r23 = ts->r23;
484: sv->save_r24 = ts->r24;
485: sv->save_r25 = ts->r25;
486: sv->save_r26 = ts->r26;
487: sv->save_r27 = ts->r27;
488: sv->save_r28 = ts->r28;
489: sv->save_r29 = ts->r29;
490: sv->save_r30 = ts->r30;
491: sv->save_r31 = ts->r31;
492:
493: sv->save_cr = ts->cr;
494: sv->save_xer = ts->xer;
495: sv->save_lr = ts->lr;
496: sv->save_ctr = ts->ctr;
497: sv->save_srr0 = ts->srr0;
498: sv->save_mq = ts->mq;
499: sv->save_vrsave = ts->vrsave; /* VRSAVE register (Altivec only) */
500: sv->save_srr1 = MSR_PREPARE_FOR_IMPORT(sv->save_srr1, ts->srr1); /* Set the bits we can change */
501:
502: if(!kernel_act) sv->save_srr1 |= MSR_EXPORT_MASK_SET; /* If not a kernel guy, force the magic bits on */
503:
504: sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_FP)); /* Make sure we don't enable the floating point unit */
505:
506: if(isnew) { /* Is it a new one? */
507: sv->save_dar = 0; /* Yes, these need initialization also */
508: sv->save_dsisr = 0;
509: sv->save_exception = 0;
510: }
511:
512: return KERN_SUCCESS;
513: }
514: else { /* This must be exception state */
515: if(isnew) /* If new, we need to initialize the normal registers */
516: for(i=0; i < 32; i+=2) { /* Fill up with defaults */
517: ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
518: ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
519: }
520: sv->save_cr = 0;
521: sv->save_xer = 0;
522: sv->save_lr = ((unsigned int *)&FloatInit)[0];
523: sv->save_ctr = ((unsigned int *)&FloatInit)[1];
524: sv->save_srr0 = ((unsigned int *)&FloatInit)[0];
525: sv->save_srr1 = MSR_EXPORT_MASK_SET;
526: sv->save_mq = 0;
527: sv->save_vrsave = 0; /* VRSAVE register (Altivec only) */
528: }
529:
530: es = (struct ppc_exception_state *) tstate;
531:
532: sv->save_dar = es->dar;
533: sv->save_dsisr = es->dsisr;
534: sv->save_exception = es->exception;
535:
536: return KERN_SUCCESS;
537:
538: case PPC_FLOAT_STATE:
539:
540: spl = splhigh(); /* Don't bother me while I'm zapping the owner stuff */
541:
542: if (per_proc_info[cpu_number()].FPU_thread == (unsigned int)thr_act) /* If we own the FPU, and */
543: 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 */
544:
545: splx(spl); /* Restore the interrupt level */
546:
547: sv = (savearea *)thr_act->mact.FPU_pcb; /* Get the top savearea on the stack */
548: osv = 0; /* Set no user savearea yet */
549:
550: while(sv) { /* Find the user context */
551: if(!(sv->save_level_fp)) { /* Are we looking at the user context? */
552: break; /* Outta here */
553: }
554: osv = sv; /* Save the last one */
555: sv = sv->save_prev_float; /* Get the previous context */
556: }
557:
558: if(!sv) { /* We didn't find a user context so allocate and initialize one */
559:
560: sv = (savearea *)thr_act->mact.pcb; /* Point to the top savearea on the normal stack */
561:
562: while(sv) { /* Have we hit the end? */
563: if(!(sv->save_flags & SAVfpuvalid)) break; /* Is floating point in use here? */
564: sv = sv->save_prev; /* Back chain */
565: }
566:
567: if(!sv) { /* If there wasn't one on the normal chain, check vector */
568: sv = (savearea *)thr_act->mact.VMX_pcb; /* Point to the top savearea on the vector stack */
569: while(sv) { /* Have we hit the end? */
570: if(!(sv->save_flags & SAVfpuvalid)) break; /* Is floating point in use here? */
571: sv = sv->save_prev_vector; /* Back chain */
572: }
573: }
574:
575: if(!sv) { /* Do we have one yet? */
576: sv = save_alloc(); /* If we still don't have one, get a new one */
577: sv->save_act = thr_act; /* Point to the activation */
578:
579: spc=(unsigned int)thr_act->map->pmap->space; /* Get the space we're in */
580:
581: srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
582: for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
583: srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
584: }
585:
586: sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
587: }
588:
589: if(osv) { /* Did we already have one? */
590: osv->save_prev_float = sv; /* Chain us on the end */
591: }
592: else { /* We are the first */
593: thr_act->mact.FPU_pcb = (pcb_t)sv; /* Put it there */
594: }
595: sv->save_prev_float = 0; /* Properly terminate the chain */
596: sv->save_level_fp = 0; /* Make sure we are for the user level */
597: sv->save_flags |= SAVfpuvalid; /* Say that it is in use by floating point */
598: }
599:
600:
601: fs = (struct ppc_float_state *) tstate; /* Point to source */
602:
603: #if 0
604: for(i=0; i < 32; i++) { /* (TEST/DEBUG) */
605: if((*((unsigned int *)&fs->fpregs[i]) >> 16) == 0xFFF8) __asm__ volatile ("tweq r1,r1"); /* (TEST/DEBUG) */
606: }
607: #endif
608:
609: bcopy((char *)fs, (char *)&sv->save_fp0, clgn*4); /* 32 registers plus status and pad */
610:
611: return KERN_SUCCESS;
612:
613:
614: case PPC_VECTOR_STATE:
615:
616: spl = splhigh(); /* Don't bother me while I'm zapping the owner stuff */
617:
618: if (per_proc_info[cpu_number()].VMX_thread == (unsigned int)thr_act) /* If we own the vector, and */
619: 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 */
620:
621: splx(spl); /* Restore the interrupt level */
622:
623: sv = (savearea *)thr_act->mact.VMX_pcb; /* Get the top savearea on the stack */
624: osv = 0; /* Set no user savearea yet */
625:
626: while(sv) { /* Find the user context */
627: if(!(sv->save_level_vec)) { /* Are we looking at the user context? */
628: break; /* Outta here */
629: }
630: osv = sv; /* Save the last one */
631: sv = sv->save_prev_vector; /* Get the previous context */
632: }
633:
634: if(!sv) { /* We didn't find a user context so allocate and initialize one */
635:
636: sv = (savearea *)thr_act->mact.pcb; /* Point to the top savearea on the normal stack */
637:
638: while(sv) { /* Have we hit the end? */
639: if(!(sv->save_flags & SAVvmxvalid)) break; /* Is vector in use here? */
640: sv = sv->save_prev; /* Back chain */
641: }
642:
643: if(!sv) { /* If there wasn't one on the normal chain, check vector */
644: sv = (savearea *)thr_act->mact.FPU_pcb; /* Point to the top savearea on the FPU stack */
645: while(sv) { /* Have we hit the end? */
646: if(!(sv->save_flags & SAVvmxvalid)) break; /* Is vector in use here? */
647: sv = sv->save_prev_float; /* Get the previous context */
648: }
649: }
650:
651: if(!sv) { /* Do we have one yet? */
652: sv = save_alloc(); /* If we still don't have one, get a new one */
653: sv->save_act = thr_act; /* Point to the activation */
654:
655: spc=(unsigned int)thr_act->map->pmap->space; /* Get the space we're in */
656:
657: srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
658: for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
659: srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
660: }
661:
662: sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
663: }
664:
665: if(osv) { /* Did we already have one? */
666: osv->save_prev_vector = sv; /* Chain us on the end */
667: }
668: else { /* We are the first */
669: thr_act->mact.VMX_pcb = (pcb_t)sv; /* Put it there */
670: }
671: sv->save_prev_vector = 0; /* Properly terminate the chain */
672: sv->save_level_vec = 0; /* Make sure we are for the user level */
673: sv->save_flags |= SAVvmxvalid; /* Say that it is in use by vector */
674: }
675:
676:
677: vs = (struct ppc_vector_state *) tstate; /* Point to source */
678:
679: bcopy((char *)vs, (char *)&sv->save_vr0, clgn*4); /* 32 registers plus status and validity and pad */
680:
681: return KERN_SUCCESS;
682:
683:
684: default:
685: return KERN_INVALID_ARGUMENT;
686: }
687: }
688:
689: /*
690: * Duplicates the context of one thread into a new one.
691: * The new thread is assumed to be new and have no user state contexts.
692: * We also assume that the old thread can't be running anywhere.
693: *
694: * We're only going to be duplicating user context here. That means that we will have to
695: * eliminate any floating point or vector kernel contexts and carry across the user state ones.
696: * We will optimize and cram all states into one savearea. Actually that will be the easiest thing
697: * to do.
698: */
699:
700: void act_thread_dup(thread_act_t old, thread_act_t new) {
701:
702: savearea *sv, *osv, *fsv;
703: unsigned int spc, i, *srs;
704:
705: fpu_save(); /* Make certain floating point state is all saved */
706: vec_save(); /* Make certain the vector state is all saved */
707:
708: osv = (savearea *)new->mact.pcb; /* Get the top savearea on the stack */
709: sv = 0; /* Set no new user savearea yet */
710:
711: while(osv) { /* Find the user context */
712: if(osv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
713: sv=osv; /* Say which to use */
714: break; /* Outta here */
715: }
716: osv=osv->save_prev; /* Get the previous context */
717: }
718:
719: if(!sv) { /* We didn't find a user context so allocate and initialize one */
720: osv = (savearea *)new->mact.pcb; /* Point to the top savearea on the stack */
721: sv = save_alloc(); /* Get one */
722: sv->save_flags |= SAVattach; /* Say that it is in use */
723: sv->save_act = new; /* Point to the activation */
724:
725: spc=(unsigned int)new->map->pmap->space; /* Get the space we're in */
726:
727: srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
728: for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
729: srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
730: }
731:
732: sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
733:
734: if(osv) { /* Did we already have one? */
735: sv->save_prev = osv->save_prev; /* Move the back chain of the top savearea */
736: osv->save_prev = sv; /* Chain us just after it */
737: }
738: else { /* We are the first */
739: new->mact.pcb = (pcb_t)sv; /* Make it the active one */
740: }
741:
742: }
743:
744: osv = (savearea *)(old->mact.pcb); /* Start with the normal savearea */
745: while(osv) { /* Find the user context */
746: if(osv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
747: break; /* Outta here */
748: }
749: osv = osv->save_prev; /* Back chain */
750: }
751:
752: bcopy((char *)&osv->save_srr0, (char *)&sv->save_srr0, sizeof(struct ppc_thread_state)); /* Copy in normal state stuff */
753:
754: new->mact.FPU_pcb = (pcb_t)0 ; /* Initialize floating point savearea */
755: new->mact.FPU_lvl = (pcb_t)0 ; /* Initialize floating point level */
756: new->mact.FPU_cpu = 0 ; /* Initialize last used cpu (FP not live, so this doesn't really matter) */
757: new->mact.VMX_pcb = (pcb_t)0 ; /* Initialize vector savearea */
758: new->mact.VMX_lvl = (pcb_t)0 ; /* Initialize vector level */
759: new->mact.VMX_cpu = 0 ; /* Initialize last used cpu (vector not live, so this doesn't reall matter) */
760:
761: sv->save_prev_float = (savearea *)0; /* Clear the back chain */
762: sv->save_prev_vector = (savearea *)0; /* Clear the back chain */
763:
764: sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make certain that floating point and vector are turned off */
765:
766: fsv = (savearea *)old->mact.FPU_pcb; /* Get the start of the floating point chain */
767: while(fsv) { /* Look until the end or we find it */
768: if(!(fsv->save_level_fp)) { /* Is the the user state stuff? (the level is 0 if so) */
769: sv->save_flags |= SAVfpuvalid; /* Show we have it */
770: bcopy((char *)&osv->save_fp0, (char *)&sv->save_fp0, sizeof(struct ppc_float_state)); /* Copy in floating point state stuff */
771: new->mact.FPU_pcb = (pcb_t)sv; /* Make it the active one */
772: break; /* Done, everything else is all set up... */
773: }
774: fsv = fsv->save_prev_float; /* Try the previous one */
775: }
776:
777: fsv = (savearea *)old->mact.VMX_pcb; /* Get the start of the vector chain */
778: while(fsv) { /* Look until the end or we find it */
779: if(!(fsv->save_level_vec)) { /* Is the the user state stuff? (the level is 0 if so) */
780: sv->save_flags |= SAVvmxvalid; /* Show we have it */
781: bcopy((char *)&osv->save_vr0, (char *)&sv->save_vr0, sizeof(struct ppc_vector_state)); /* Copy in Altivec state stuff */
782: new->mact.VMX_pcb = (pcb_t)sv; /* Make it the active one */
783: break; /* Done, everything else is all set up... */
784: }
785: fsv = fsv->save_prev_vector; /* Try the previous one */
786: }
787:
788: return; /* Bye bye... */
789: }
790:
791: /*
792: * Initializes a fresh set of user state values. If there is no user state context,
793: * one is created. Floats and VMX are not created. We set initial values for everything.
794: */
795:
796: struct ppc_saved_state * get_user_regs(thread_act_t act) {
797:
798: savearea *sv, *osv;
799: unsigned int spc, i, *srs;
800:
801: sv = (savearea *)act->mact.pcb; /* Get the top savearea on the stack */
802: osv = 0; /* Set no user savearea yet */
803:
804: while(sv) { /* Find the user context */
805: if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
806: break; /* Outta here */
807: }
808: osv = sv; /* Save the last one */
809: sv = sv->save_prev; /* Get the previous context */
810: }
811:
812: if(!sv) { /* We didn't find a user context so allocate and initialize one */
813: sv = save_alloc(); /* Get one */
814: sv->save_flags |= SAVattach; /* Say that it is in use */
815: sv->save_act = act; /* Point to the activation */
816:
817: if(osv) { /* Did we already have one? */
818: osv->save_prev = sv; /* Chain us on the end */
819: }
820: else { /* We are the first */
821: act->mact.pcb = (pcb_t)sv; /* Put it there */
822: }
823: sv->save_prev = 0; /* Properly terminate the chain */
824:
825: }
826:
827: for(i=0; i < 32; i+=2) { /* Fill up with defaults */
828: ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
829: ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
830: }
831: sv->save_cr = 0;
832: sv->save_xer = 0;
833: sv->save_lr = ((unsigned int *)&FloatInit)[0];
834: sv->save_ctr = ((unsigned int *)&FloatInit)[1];
835: sv->save_srr0 = ((unsigned int *)&FloatInit)[0];
836: sv->save_srr1 = MSR_EXPORT_MASK_SET;
837: sv->save_mq = 0;
838: /* XXX: TO BE REMOVED WA for AltiVec compiler bug */
839: sv->save_vrsave = 0xffffffff; /* VRSAVE register (Altivec only) */
840:
841: spc=(unsigned int)act->map->pmap->space; /* Get the space we're in */
842:
843: srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */
844: for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */
845: srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */
846: }
847:
848: sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */
849:
850: return (struct ppc_saved_state *)sv; /* Bye bye... */
851: }
852:
853: /*
854: * Find the user state context. If there is no user state context,
855: * we just return a 0.
856: */
857:
858: struct ppc_saved_state * find_user_regs(thread_act_t act) {
859:
860: savearea *sv;
861:
862: sv = (savearea *)act->mact.pcb; /* Get the top savearea on the stack */
863:
864: while(sv) { /* Find the user context */
865: if(sv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */
866: break; /* Outta here */
867: }
868: sv = sv->save_prev; /* Get the previous context */
869: }
870:
871: return (struct ppc_saved_state *)sv; /* Bye bye... */
872: }
873:
874: /*
875: * Find the user state floating pointcontext. If there is no user state context,
876: * we just return a 0.
877: */
878:
879: struct ppc_float_state * find_user_fpu(thread_act_t act) {
880:
881: savearea *fsv;
882:
883: fsv = (savearea *)act->mact.FPU_pcb; /* Get the start of the floating point chain */
884: while(fsv) { /* Look until the end or we find it */
885: if(!(fsv->save_level_fp)) break; /* Is the the user state stuff? (the level is 0 if so) */
886: fsv = fsv->save_prev_float; /* Try the previous one */
887: }
888:
889: return (struct ppc_float_state *)&(fsv->save_fp0); /* Bye bye... */
890: }
891:
892: /*
893: * thread_userstack:
894: *
895: * Return the user stack pointer from the machine
896: * dependent thread state info.
897: */
898: kern_return_t
899: thread_userstack(
900: thread_t thread,
901: int flavor,
902: thread_state_t tstate,
903: unsigned int count,
904: vm_offset_t *user_stack
905: )
906: {
907: struct ppc_thread_state *state;
908:
909: /*
910: * Set a default.
911: */
912: if (*user_stack == 0)
913: *user_stack = USRSTACK;
914:
915: switch (flavor) {
916: case PPC_THREAD_STATE:
917: if (count < PPC_THREAD_STATE_COUNT)
918: return (KERN_INVALID_ARGUMENT);
919:
920: state = (struct ppc_thread_state *) tstate;
921:
922: /*
923: * If a valid user stack is specified, use it.
924: */
925: *user_stack = state->r1 ? state->r1: USRSTACK;
926: break;
927: default :
928: return (KERN_INVALID_ARGUMENT);
929: }
930:
931: return (KERN_SUCCESS);
932: }
933:
934: kern_return_t
935: thread_entrypoint(
936: thread_t thread,
937: int flavor,
938: thread_state_t tstate,
939: unsigned int count,
940: vm_offset_t *entry_point
941: )
942: {
943: struct ppc_thread_state *state;
944:
945: /*
946: * Set a default.
947: */
948: if (*entry_point == 0)
949: *entry_point = VM_MIN_ADDRESS;
950:
951: switch (flavor) {
952:
953: case PPC_THREAD_STATE:
954: if (count < PPC_THREAD_STATE_COUNT)
955: return (KERN_INVALID_ARGUMENT);
956:
957: state = (struct ppc_thread_state *) tstate;
958:
959: /*
960: * If a valid entry point is specified, use it.
961: */
962: *entry_point = state->srr0 ? state->srr0: VM_MIN_ADDRESS;
963: break;
964: default:
965: return (KERN_INVALID_ARGUMENT);
966: }
967:
968: return (KERN_SUCCESS);
969: }
970:
971: unsigned int get_msr_exportmask(void)
972: {
973: return (MSR_EXPORT_MASK_SET);
974: }
975:
976: unsigned int get_msr_nbits(void)
977: {
978: return (MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
979: }
980: unsigned int get_msr_rbits(void)
981: {
982: return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
983: }
984:
985: void thread_set_child(thread_act_t child, int pid)
986: {
987: struct ppc_saved_state *child_state;
988:
989: child_state = find_user_regs(child);
990:
991: child_state->r3 = pid;
992: child_state->r4 = 1;
993: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.