]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/ppc/unix_signal.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / bsd / dev / ppc / unix_signal.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
27 */
28
29 #include <mach/mach_types.h>
30 #include <mach/exception_types.h>
31
32 #include <sys/param.h>
33 #include <sys/proc.h>
34 #include <sys/user.h>
35 #include <sys/ucontext.h>
36
37 #include <ppc/signal.h>
38 #include <sys/signalvar.h>
39 #include <sys/kdebug.h>
40 #include <sys/wait.h>
41 #include <kern/thread.h>
42 #include <kern/thread_act.h>
43 #include <mach/ppc/thread_status.h>
44 #include <ppc/proc_reg.h>
45
46 #define C_REDZONE_LEN 224
47 #define C_STK_ALIGN 16
48 #define C_PARAMSAVE_LEN 64
49 #define C_LINKAGE_LEN 48
50 #define TRUNC_DOWN(a,b,c) (((((unsigned)a)-(b))/(c)) * (c))
51
52 /*
53 * The stack layout possibilities (info style); This needs to mach with signal trampoline code
54 *
55 * Traditional: 1
56 * Traditional64: 20
57 * Traditional64with vec: 25
58 * 32bit context 30
59 * 32bit context with vector 35
60 * 64bit context 40
61 * 64bit context with vector 45
62 * Dual context 50
63 * Dual context with vector 55
64 *
65 */
66
67 #define UC_TRAD 1
68 #define UC_TRAD64 20
69 #define UC_TRAD64_VEC 25
70 #define UC_FLAVOR 30
71 #define UC_FLAVOR_VEC 35
72 #define UC_FLAVOR64 40
73 #define UC_FLAVOR64_VEC 45
74 #define UC_DUAL 50
75 #define UC_DUAL_VEC 55
76
77 /* The following are valid mcontext sizes */
78 #define UC_FLAVOR_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
79
80 #define UC_FLAVOR_VEC_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
81
82 #define UC_FLAVOR64_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
83
84 #define UC_FLAVOR64_VEC_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
85
86
87 /*
88 * Arrange for this process to run a signal handler
89 */
90
91 void
92 sendsig(p, catcher, sig, mask, code)
93 struct proc *p;
94 sig_t catcher;
95 int sig, mask;
96 u_long code;
97 {
98 struct mcontext mctx, *p_mctx;
99 struct mcontext64 mctx64, *p_mctx64;
100 struct ucontext uctx, *p_uctx;
101 siginfo_t sinfo, *p_sinfo;
102 struct sigacts *ps = p->p_sigacts;
103 int framesize;
104 int oonstack;
105 unsigned long sp;
106 unsigned long state_count;
107 thread_act_t th_act;
108 struct uthread *ut;
109 unsigned long paramp,linkp;
110 int infostyle = UC_TRAD;
111 int dualcontext =0;
112 sig_t trampact;
113 int vec_used = 0;
114 int stack_size = 0;
115 int stack_flags = 0;
116 void * tstate;
117 int flavor;
118 int ctx32 = 1;
119 int is_64signalregset(void);
120
121 th_act = current_act();
122 ut = get_bsdthread_info(th_act);
123
124
125 if (p->p_sigacts->ps_siginfo & sigmask(sig)) {
126 infostyle = UC_FLAVOR;
127 }
128 if(is_64signalregset() && (infostyle == UC_FLAVOR)) {
129 dualcontext = 1;
130 infostyle = UC_DUAL;
131 }
132 if (p->p_sigacts->ps_64regset & sigmask(sig)) {
133 dualcontext = 0;
134 ctx32 = 0;
135 infostyle = UC_FLAVOR64;
136 }
137 if (is_64signalregset() && (infostyle == UC_TRAD)) {
138 ctx32=0;
139 infostyle = UC_TRAD64;
140 }
141
142 /* I need this for SIGINFO anyway */
143 flavor = PPC_THREAD_STATE;
144 tstate = (void *)&mctx.ss;
145 state_count = PPC_THREAD_STATE_COUNT;
146 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
147 goto bad;
148
149 if ((ctx32 == 0) || dualcontext) {
150 flavor = PPC_THREAD_STATE64;
151 tstate = (void *)&mctx64.ss;
152 state_count = PPC_THREAD_STATE64_COUNT;
153 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
154 goto bad;
155 }
156
157 if ((ctx32 == 1) || dualcontext) {
158 flavor = PPC_EXCEPTION_STATE;
159 tstate = (void *)&mctx.es;
160 state_count = PPC_EXCEPTION_STATE_COUNT;
161 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
162 goto bad;
163 }
164
165 if ((ctx32 == 0) || dualcontext) {
166 flavor = PPC_EXCEPTION_STATE64;
167 tstate = (void *)&mctx64.es;
168 state_count = PPC_EXCEPTION_STATE64_COUNT;
169
170 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
171 goto bad;
172
173 }
174
175
176 if ((ctx32 == 1) || dualcontext) {
177 flavor = PPC_FLOAT_STATE;
178 tstate = (void *)&mctx.fs;
179 state_count = PPC_FLOAT_STATE_COUNT;
180 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
181 goto bad;
182 }
183
184 if ((ctx32 == 0) || dualcontext) {
185 flavor = PPC_FLOAT_STATE;
186 tstate = (void *)&mctx64.fs;
187 state_count = PPC_FLOAT_STATE_COUNT;
188 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
189 goto bad;
190
191 }
192
193
194 vec_save(th_act);
195 if (find_user_vec(th_act)) {
196 vec_used = 1;
197
198 if ((ctx32 == 1) || dualcontext) {
199 flavor = PPC_VECTOR_STATE;
200 tstate = (void *)&mctx.vs;
201 state_count = PPC_VECTOR_STATE_COUNT;
202 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
203 goto bad;
204 infostyle += 5;
205 }
206
207 if ((ctx32 == 0) || dualcontext) {
208 flavor = PPC_VECTOR_STATE;
209 tstate = (void *)&mctx64.vs;
210 state_count = PPC_VECTOR_STATE_COUNT;
211 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
212 goto bad;
213 infostyle += 5;
214 }
215 }
216
217 trampact = ps->ps_trampact[sig];
218 oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;
219
220 /* figure out where our new stack lives */
221 if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack &&
222 (ps->ps_sigonstack & sigmask(sig))) {
223 sp = (unsigned long)(ps->ps_sigstk.ss_sp);
224 sp += ps->ps_sigstk.ss_size;
225 stack_size = ps->ps_sigstk.ss_size;
226 ps->ps_sigstk.ss_flags |= SA_ONSTACK;
227 }
228 else {
229 if (ctx32 == 0)
230 sp = (unsigned int)mctx64.ss.r1;
231 else
232 sp = mctx.ss.r1;
233 }
234
235
236 /* put siginfo on top */
237
238 /* preserve RED ZONE area */
239 sp = TRUNC_DOWN(sp, C_REDZONE_LEN, C_STK_ALIGN);
240
241 /* next are the saved registers */
242 if ((ctx32 == 0) || dualcontext) {
243 sp -= sizeof(*p_mctx64);
244 p_mctx64 = (struct mcontext64 *)sp;
245 }
246 if ((ctx32 == 1) || dualcontext) {
247 sp -= sizeof(*p_mctx);
248 p_mctx = (struct mcontext *)sp;
249 }
250
251 /* context goes first on stack */
252 sp -= sizeof(*p_uctx);
253 p_uctx = (struct ucontext *) sp;
254
255 /* this is where siginfo goes on stack */
256 sp -= sizeof(*p_sinfo);
257 p_sinfo = (siginfo_t *) sp;
258
259 /* C calling conventions, create param save and linkage
260 * areas
261 */
262
263 sp = TRUNC_DOWN(sp, C_PARAMSAVE_LEN, C_STK_ALIGN);
264 paramp = sp;
265 sp -= C_LINKAGE_LEN;
266 linkp = sp;
267
268 uctx.uc_onstack = oonstack;
269 uctx.uc_sigmask = mask;
270 uctx.uc_stack.ss_sp = (char *)sp;
271 uctx.uc_stack.ss_size = stack_size;
272 if (oonstack)
273 uctx.uc_stack.ss_flags |= SS_ONSTACK;
274
275 uctx.uc_link = 0;
276 if (ctx32 == 0)
277 uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE64_COUNT + PPC_THREAD_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
278 else
279 uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE_COUNT + PPC_THREAD_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
280
281 if (vec_used)
282 uctx.uc_mcsize += (size_t)(PPC_VECTOR_STATE_COUNT * sizeof(int));
283
284 if (ctx32 == 0)
285 uctx.uc_mcontext = (void *)p_mctx64;
286 else
287 uctx.uc_mcontext = (void *)p_mctx;
288
289 /* setup siginfo */
290 bzero((caddr_t)&sinfo, sizeof(siginfo_t));
291 sinfo.si_signo = sig;
292 sinfo.si_addr = (void *)mctx.ss.srr0;
293 sinfo.pad[0] = (unsigned int)mctx.ss.r1;
294
295 switch (sig) {
296 case SIGCHLD:
297 sinfo.si_pid = p->si_pid;
298 p->si_pid =0;
299 sinfo.si_status = p->si_status;
300 p->si_status = 0;
301 sinfo.si_uid = p->si_uid;
302 p->si_uid =0;
303 sinfo.si_code = p->si_code;
304 p->si_code = 0;
305 if (sinfo.si_code == CLD_EXITED) {
306 if (WIFEXITED(sinfo.si_status))
307 sinfo.si_code = CLD_EXITED;
308 else if (WIFSIGNALED(sinfo.si_status)) {
309 if (WCOREDUMP(sinfo.si_status))
310 sinfo.si_code = CLD_DUMPED;
311 else
312 sinfo.si_code = CLD_KILLED;
313 }
314 }
315 break;
316 case SIGILL:
317 sinfo.si_addr = (void *)mctx.ss.srr0;
318 if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
319 sinfo.si_code = ILL_ILLOPC;
320 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
321 sinfo.si_code = ILL_PRVOPC;
322 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
323 sinfo.si_code = ILL_ILLTRP;
324 else
325 sinfo.si_code = ILL_NOOP;
326 break;
327 case SIGFPE:
328 #define FPSCR_VX 2
329 #define FPSCR_OX 3
330 #define FPSCR_UX 4
331 #define FPSCR_ZX 5
332 #define FPSCR_XX 6
333 sinfo.si_addr = (void *)mctx.ss.srr0;
334 if (mctx.fs.fpscr & (1 << (31 - FPSCR_VX)))
335 sinfo.si_code = FPE_FLTINV;
336 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_OX)))
337 sinfo.si_code = FPE_FLTOVF;
338 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_UX)))
339 sinfo.si_code = FPE_FLTUND;
340 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_ZX)))
341 sinfo.si_code = FPE_FLTDIV;
342 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_XX)))
343 sinfo.si_code = FPE_FLTRES;
344 else
345 sinfo.si_code = FPE_NOOP;
346 break;
347
348 case SIGBUS:
349 sinfo.si_addr = (void *)mctx.ss.srr0;
350 /* on ppc we generate only if EXC_PPC_UNALIGNED */
351 sinfo.si_code = BUS_ADRALN;
352 break;
353
354 case SIGSEGV:
355 sinfo.si_addr = (void *)mctx.ss.srr0;
356 /* First check in srr1 and then in dsisr */
357 if (mctx.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
358 sinfo.si_code = SEGV_ACCERR;
359 else if (mctx.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
360 sinfo.si_code = SEGV_ACCERR;
361 else
362 sinfo.si_code = SEGV_MAPERR;
363 break;
364 default:
365 break;
366 }
367
368
369 /* copy info out to user space */
370 if (copyout((caddr_t)&uctx, (caddr_t)p_uctx, sizeof(struct ucontext)))
371 goto bad;
372 if (copyout((caddr_t)&sinfo, (caddr_t)p_sinfo, sizeof(siginfo_t)))
373 goto bad;
374 if ((ctx32 == 0) || dualcontext) {
375 tstate = &mctx64;
376 if (copyout((caddr_t)tstate, (caddr_t)p_mctx64, uctx.uc_mcsize))
377 goto bad;
378 }
379 if ((ctx32 == 1) || dualcontext) {
380 tstate = &mctx;
381 if (copyout((caddr_t)tstate, (caddr_t)p_mctx, uctx.uc_mcsize))
382 goto bad;
383 }
384
385
386 /* Place our arguments in arg registers: rtm dependent */
387
388 mctx.ss.r3 = (unsigned long)catcher;
389 mctx.ss.r4 = (unsigned long)infostyle;
390 mctx.ss.r5 = (unsigned long)sig;
391 mctx.ss.r6 = (unsigned long)p_sinfo;
392 mctx.ss.r7 = (unsigned long)p_uctx;
393
394 mctx.ss.srr0 = (unsigned long)trampact;
395 mctx.ss.srr1 = get_msr_exportmask(); /* MSR_EXPORT_MASK_SET */
396 mctx.ss.r1 = sp;
397 state_count = PPC_THREAD_STATE_COUNT;
398 if (thread_setstatus(th_act, PPC_THREAD_STATE, &mctx.ss, &state_count) != KERN_SUCCESS) {
399 goto bad;
400 }
401 return;
402
403 bad:
404 SIGACTION(p, SIGILL) = SIG_DFL;
405 sig = sigmask(SIGILL);
406 p->p_sigignore &= ~sig;
407 p->p_sigcatch &= ~sig;
408 ut->uu_sigmask &= ~sig;
409 /* sendsig is called with signal lock held */
410 psignal_lock(p, SIGILL, 0);
411 return;
412 }
413
414 /*
415 * System call to cleanup state after a signal
416 * has been taken. Reset signal mask and
417 * stack state from context left by sendsig (above).
418 * Return to previous pc and psl as specified by
419 * context left by sendsig. Check carefully to
420 * make sure that the user has not modified the
421 * psl to gain improper priviledges or to cause
422 * a machine fault.
423 */
424
425 #define FOR64_TRANSITION 1
426
427 #ifdef FOR64_TRANSITION
428
429 struct osigreturn_args {
430 struct ucontext *uctx;
431 };
432
433 /* ARGSUSED */
434 int
435 osigreturn(p, uap, retval)
436 struct proc *p;
437 struct osigreturn_args *uap;
438 int *retval;
439 {
440 struct ucontext uctx;
441 struct ucontext *p_uctx;
442 struct mcontext64 mctx64;
443 struct mcontext64 *p_64mctx;
444 struct mcontext *p_mctx;
445 int error;
446 thread_act_t th_act;
447 struct sigacts *ps = p->p_sigacts;
448 sigset_t mask;
449 register sig_t action;
450 unsigned long state_count;
451 unsigned int state_flavor;
452 struct uthread * ut;
453 int vec_used = 0;
454 void *tsptr, *fptr, *vptr, *mactx;
455 void ppc_checkthreadstate(void *, int);
456
457 th_act = current_act();
458 /* lets use the larger one */
459 mactx = (void *)&mctx64;
460
461 ut = (struct uthread *)get_bsdthread_info(th_act);
462 if (error = copyin(uap->uctx, &uctx, sizeof(struct ucontext))) {
463 return(error);
464 }
465 if (error = copyin(uctx.uc_mcontext, mactx, uctx.uc_mcsize)) {
466 return(error);
467 }
468
469 if (uctx.uc_onstack & 01)
470 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
471 else
472 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
473
474 ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask;
475 if (ut->uu_siglist & ~ut->uu_sigmask)
476 signal_setast(current_act());
477
478 vec_used = 0;
479 switch (uctx.uc_mcsize) {
480 case UC_FLAVOR64_VEC_SIZE :
481 vec_used = 1;
482 case UC_FLAVOR64_SIZE : {
483 p_64mctx = (struct mcontext64 *)mactx;
484 tsptr = (void *)&p_64mctx->ss;
485 fptr = (void *)&p_64mctx->fs;
486 vptr = (void *)&p_64mctx->vs;
487 state_flavor = PPC_THREAD_STATE64;
488 state_count = PPC_THREAD_STATE64_COUNT;
489 }
490 break;
491 case UC_FLAVOR_VEC_SIZE :
492 vec_used = 1;
493 case UC_FLAVOR_SIZE:
494 default: {
495 p_mctx = (struct mcontext *)mactx;
496 tsptr = (void *)&p_mctx->ss;
497 fptr = (void *)&p_mctx->fs;
498 vptr = (void *)&p_mctx->vs;
499 state_flavor = PPC_THREAD_STATE;
500 state_count = PPC_THREAD_STATE_COUNT;
501 }
502 break;
503 } /* switch () */
504
505 /* validate the thread state, set/reset appropriate mode bits in srr1 */
506 (void)ppc_checkthreadstate(tsptr, state_flavor);
507
508 if (thread_setstatus(th_act, state_flavor, tsptr, &state_count) != KERN_SUCCESS) {
509 return(EINVAL);
510 }
511
512 state_count = PPC_FLOAT_STATE_COUNT;
513 if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, &state_count) != KERN_SUCCESS) {
514 return(EINVAL);
515 }
516
517 mask = sigmask(SIGFPE);
518 if (((ut->uu_sigmask & mask) == 0) && (p->p_sigcatch & mask) && ((p->p_sigignore & mask) == 0)) {
519 action = ps->ps_sigact[SIGFPE];
520 if((action != SIG_DFL) && (action != SIG_IGN)) {
521 thread_enable_fpe(th_act, 1);
522 }
523 }
524
525 if (vec_used) {
526 state_count = PPC_VECTOR_STATE_COUNT;
527 if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, &state_count) != KERN_SUCCESS) {
528 return(EINVAL);
529 }
530 }
531 return (EJUSTRETURN);
532 }
533
534 #endif /* FOR64_TRANSITION */
535
536 struct sigreturn_args {
537 struct ucontext *uctx;
538 int infostyle;
539 };
540
541 /* ARGSUSED */
542 int
543 sigreturn(p, uap, retval)
544 struct proc *p;
545 struct sigreturn_args *uap;
546 int *retval;
547 {
548 struct ucontext uctx;
549 struct ucontext *p_uctx;
550 char mactx[sizeof(struct mcontext64)];
551 struct mcontext *p_mctx;
552 struct mcontext64 *p_64mctx;
553 int error;
554 thread_act_t th_act;
555 struct sigacts *ps = p->p_sigacts;
556 sigset_t mask;
557 register sig_t action;
558 unsigned long state_count;
559 unsigned int state_flavor;
560 struct uthread * ut;
561 int vec_used = 0;
562 void *tsptr, *fptr, *vptr;
563 int infostyle = uap->infostyle;
564 void ppc_checkthreadstate(void *, int);
565
566 th_act = current_act();
567
568 ut = (struct uthread *)get_bsdthread_info(th_act);
569 if (error = copyin(uap->uctx, &uctx, sizeof(struct ucontext))) {
570 return(error);
571 }
572
573
574 if (error = copyin(uctx.uc_mcontext, mactx, uctx.uc_mcsize)) {
575 return(error);
576 }
577
578 if (uctx.uc_onstack & 01)
579 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
580 else
581 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
582
583 ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask;
584 if (ut->uu_siglist & ~ut->uu_sigmask)
585 signal_setast(current_act());
586
587 vec_used = 0;
588 switch (infostyle) {
589 case UC_FLAVOR64_VEC:
590 case UC_TRAD64_VEC:
591 vec_used = 1;
592 case UC_TRAD64:
593 case UC_FLAVOR64: {
594 p_64mctx = (struct mcontext64 *)mactx;
595 tsptr = (void *)&p_64mctx->ss;
596 fptr = (void *)&p_64mctx->fs;
597 vptr = (void *)&p_64mctx->vs;
598 state_flavor = PPC_THREAD_STATE64;
599 state_count = PPC_THREAD_STATE64_COUNT;
600 }
601 break;
602 case UC_FLAVOR_VEC :
603 vec_used = 1;
604 case UC_FLAVOR :
605 default: {
606 p_mctx = (struct mcontext *)mactx;
607 tsptr = (void *)&p_mctx->ss;
608 fptr = (void *)&p_mctx->fs;
609 vptr = (void *)&p_mctx->vs;
610 state_flavor = PPC_THREAD_STATE;
611 state_count = PPC_THREAD_STATE_COUNT;
612 }
613 break;
614 } /* switch () */
615
616 /* validate the thread state, set/reset appropriate mode bits in srr1 */
617 (void)ppc_checkthreadstate(tsptr, state_flavor);
618
619 if (thread_setstatus(th_act, state_flavor, tsptr, &state_count) != KERN_SUCCESS) {
620 return(EINVAL);
621 }
622
623 state_count = PPC_FLOAT_STATE_COUNT;
624 if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, &state_count) != KERN_SUCCESS) {
625 return(EINVAL);
626 }
627
628 mask = sigmask(SIGFPE);
629 if (((ut->uu_sigmask & mask) == 0) && (p->p_sigcatch & mask) && ((p->p_sigignore & mask) == 0)) {
630 action = ps->ps_sigact[SIGFPE];
631 if((action != SIG_DFL) && (action != SIG_IGN)) {
632 thread_enable_fpe(th_act, 1);
633 }
634 }
635
636 if (vec_used) {
637 state_count = PPC_VECTOR_STATE_COUNT;
638 if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, &state_count) != KERN_SUCCESS) {
639 return(EINVAL);
640 }
641 }
642 return (EJUSTRETURN);
643 }
644
645 /*
646 * machine_exception() performs MD translation
647 * of a mach exception to a unix signal and code.
648 */
649
650 boolean_t
651 machine_exception(
652 int exception,
653 int code,
654 int subcode,
655 int *unix_signal,
656 int *unix_code
657 )
658 {
659 switch(exception) {
660
661 case EXC_BAD_INSTRUCTION:
662 *unix_signal = SIGILL;
663 *unix_code = code;
664 break;
665
666 case EXC_ARITHMETIC:
667 *unix_signal = SIGFPE;
668 *unix_code = code;
669 break;
670
671 case EXC_SOFTWARE:
672 if (code == EXC_PPC_TRAP) {
673 *unix_signal = SIGTRAP;
674 *unix_code = code;
675 break;
676 } else
677 return(FALSE);
678
679 default:
680 return(FALSE);
681 }
682
683 return(TRUE);
684 }
685