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