]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/ppc/unix_signal.c
d218d4a76c24b4850a2e470c3a89ad0135a9b16d
[apple/xnu.git] / bsd / dev / ppc / unix_signal.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
32 */
33
34 #include <mach/mach_types.h>
35 #include <mach/exception_types.h>
36
37 #include <sys/param.h>
38 #include <sys/proc_internal.h>
39 #include <sys/user.h>
40 #include <sys/ucontext.h>
41 #include <sys/sysproto.h>
42 #include <sys/systm.h>
43 #include <sys/ux_exception.h>
44
45 #include <ppc/signal.h>
46 #include <sys/signalvar.h>
47 #include <sys/kdebug.h>
48 #include <sys/wait.h>
49 #include <kern/thread.h>
50 #include <mach/ppc/thread_status.h>
51 #include <ppc/proc_reg.h>
52
53 // #include <machine/thread.h> XXX include path messed up for some reason...
54
55 /* XXX functions not in a Mach headers */
56 extern kern_return_t thread_getstatus(register thread_t act, int flavor,
57 thread_state_t tstate, mach_msg_type_number_t *count);
58 extern int is_64signalregset(void);
59 extern unsigned int get_msr_exportmask(void);
60 extern kern_return_t thread_setstatus(thread_t thread, int flavor,
61 thread_state_t tstate, mach_msg_type_number_t count);
62 extern void ppc_checkthreadstate(void *, int);
63 extern struct savearea_vec *find_user_vec_curr(void);
64 extern int thread_enable_fpe(thread_t act, int onoff);
65
66
67
68 #define C_32_REDZONE_LEN 224
69 #define C_32_STK_ALIGN 16
70 #define C_32_PARAMSAVE_LEN 64
71 #define C_32_LINKAGE_LEN 48
72
73 #define C_64_REDZONE_LEN 320
74 #define C_64_STK_ALIGN 32
75 #define C_64_PARAMSAVE_LEN 64
76 #define C_64_LINKAGE_LEN 48
77
78 #define TRUNC_DOWN32(a,b,c) ((((uint32_t)a)-(b)) & ((uint32_t)(-(c))))
79 #define TRUNC_DOWN64(a,b,c) ((((uint64_t)a)-(b)) & ((uint64_t)(-(c))))
80
81 /*
82 * The stack layout possibilities (info style); This needs to mach with signal trampoline code
83 *
84 * Traditional: 1
85 * Traditional64: 20
86 * Traditional64with vec: 25
87 * 32bit context 30
88 * 32bit context with vector 35
89 * 64bit context 40
90 * 64bit context with vector 45
91 * Dual context 50
92 * Dual context with vector 55
93 *
94 */
95
96 #define UC_TRAD 1
97 #define UC_TRAD_VEC 6
98 #define UC_TRAD64 20
99 #define UC_TRAD64_VEC 25
100 #define UC_FLAVOR 30
101 #define UC_FLAVOR_VEC 35
102 #define UC_FLAVOR64 40
103 #define UC_FLAVOR64_VEC 45
104 #define UC_DUAL 50
105 #define UC_DUAL_VEC 55
106
107 /* The following are valid mcontext sizes */
108 #define UC_FLAVOR_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
109
110 #define UC_FLAVOR_VEC_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
111
112 #define UC_FLAVOR64_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
113
114 #define UC_FLAVOR64_VEC_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
115
116
117 /*
118 * NOTE: Source and target may *NOT* overlap!
119 */
120 static void
121 ucontext_32to64(struct ucontext64 *in, struct user_ucontext64 *out)
122 {
123 out->uc_onstack = in->uc_onstack;
124 out->uc_sigmask = in->uc_sigmask;
125
126 /* internal "structure assign" */
127 out->uc_stack.ss_sp = CAST_USER_ADDR_T(in->uc_stack.ss_sp);
128 out->uc_stack.ss_size = in->uc_stack.ss_size;
129 out->uc_stack.ss_flags = in->uc_stack.ss_flags;
130
131 out->uc_link = CAST_USER_ADDR_T(in->uc_link);
132 out->uc_mcsize = in->uc_mcsize;
133 out->uc_mcontext64 = CAST_USER_ADDR_T(in->uc_mcontext64);
134 }
135
136 /*
137 * This conversion is safe, since if we are converting for a 32 bit process,
138 * then it's values of uc-stack.ss_size and uc_mcsize will never exceed 4G.
139 *
140 * NOTE: Source and target may *NOT* overlap!
141 */
142 static void
143 ucontext_64to32(struct user_ucontext64 *in, struct ucontext64 *out)
144 {
145 out->uc_onstack = in->uc_onstack;
146 out->uc_sigmask = in->uc_sigmask;
147
148 /* internal "structure assign" */
149 out->uc_stack.ss_sp = CAST_DOWN(void *,in->uc_stack.ss_sp);
150 out->uc_stack.ss_size = in->uc_stack.ss_size; /* range reduction */
151 out->uc_stack.ss_flags = in->uc_stack.ss_flags;
152
153 out->uc_link = CAST_DOWN(void *,in->uc_link);
154 out->uc_mcsize = in->uc_mcsize; /* range reduction */
155 out->uc_mcontext64 = CAST_DOWN(void *,in->uc_mcontext64);
156 }
157
158 /*
159 * NOTE: Source and target may *NOT* overlap!
160 */
161 static void
162 siginfo_64to32(user_siginfo_t *in, siginfo_t *out)
163 {
164 out->si_signo = in->si_signo;
165 out->si_errno = in->si_errno;
166 out->si_code = in->si_code;
167 out->si_pid = in->si_pid;
168 out->si_uid = in->si_uid;
169 out->si_status = in->si_status;
170 out->si_addr = CAST_DOWN(void *,in->si_addr);
171 /* following cast works for sival_int because of padding */
172 out->si_value.sival_ptr = CAST_DOWN(void *,in->si_value.sival_ptr);
173 out->si_band = in->si_band; /* range reduction */
174 out->pad[0] = in->pad[0]; /* mcontext.ss.r1 */
175 }
176
177
178 /*
179 * Arrange for this process to run a signal handler
180 */
181
182 void
183 sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long code)
184 {
185 kern_return_t kretn;
186 struct mcontext mctx;
187 user_addr_t p_mctx = USER_ADDR_NULL; /* mcontext dest. */
188 struct mcontext64 mctx64;
189 user_addr_t p_mctx64 = USER_ADDR_NULL; /* mcontext dest. */
190 struct user_ucontext64 uctx;
191 user_addr_t p_uctx; /* user stack addr top copy ucontext */
192 user_siginfo_t sinfo;
193 user_addr_t p_sinfo; /* user stack addr top copy siginfo */
194 struct sigacts *ps = p->p_sigacts;
195 int oonstack;
196 user_addr_t sp;
197 mach_msg_type_number_t state_count;
198 thread_t th_act;
199 struct uthread *ut;
200 int infostyle = UC_TRAD;
201 int dualcontext =0;
202 user_addr_t trampact;
203 int vec_used = 0;
204 int stack_size = 0;
205 void * tstate;
206 int flavor;
207 int ctx32 = 1;
208 int uthsigaltstack = 0;
209 int altstack = 0;
210
211
212 th_act = current_thread();
213 ut = get_bsdthread_info(th_act);
214
215
216 if (p->p_sigacts->ps_siginfo & sigmask(sig)) {
217 infostyle = UC_FLAVOR;
218 }
219 if(is_64signalregset() && (infostyle == UC_FLAVOR)) {
220 dualcontext = 1;
221 infostyle = UC_DUAL;
222 }
223 if (p->p_sigacts->ps_64regset & sigmask(sig)) {
224 dualcontext = 0;
225 ctx32 = 0;
226 infostyle = UC_FLAVOR64;
227 }
228 /* treat 64 bit processes as having used 64 bit registers */
229 if ((IS_64BIT_PROCESS(p) || is_64signalregset()) &&
230 (infostyle == UC_TRAD)) {
231 ctx32=0;
232 infostyle = UC_TRAD64;
233 }
234 if (IS_64BIT_PROCESS(p)) {
235 ctx32=0;
236 dualcontext = 0;
237 }
238
239 /* I need this for SIGINFO anyway */
240 flavor = PPC_THREAD_STATE;
241 tstate = (void *)&mctx.ss;
242 state_count = PPC_THREAD_STATE_COUNT;
243 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
244 goto bad;
245
246 if ((ctx32 == 0) || dualcontext) {
247 flavor = PPC_THREAD_STATE64;
248 tstate = (void *)&mctx64.ss;
249 state_count = PPC_THREAD_STATE64_COUNT;
250 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
251 goto bad;
252 }
253
254 if ((ctx32 == 1) || dualcontext) {
255 flavor = PPC_EXCEPTION_STATE;
256 tstate = (void *)&mctx.es;
257 state_count = PPC_EXCEPTION_STATE_COUNT;
258 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
259 goto bad;
260 }
261
262 if ((ctx32 == 0) || dualcontext) {
263 flavor = PPC_EXCEPTION_STATE64;
264 tstate = (void *)&mctx64.es;
265 state_count = PPC_EXCEPTION_STATE64_COUNT;
266
267 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
268 goto bad;
269
270 }
271
272
273 if ((ctx32 == 1) || dualcontext) {
274 flavor = PPC_FLOAT_STATE;
275 tstate = (void *)&mctx.fs;
276 state_count = PPC_FLOAT_STATE_COUNT;
277 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
278 goto bad;
279 }
280
281 if ((ctx32 == 0) || dualcontext) {
282 flavor = PPC_FLOAT_STATE;
283 tstate = (void *)&mctx64.fs;
284 state_count = PPC_FLOAT_STATE_COUNT;
285 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
286 goto bad;
287
288 }
289
290
291 if (find_user_vec_curr()) {
292 vec_used = 1;
293
294 if ((ctx32 == 1) || dualcontext) {
295 flavor = PPC_VECTOR_STATE;
296 tstate = (void *)&mctx.vs;
297 state_count = PPC_VECTOR_STATE_COUNT;
298 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
299 goto bad;
300 infostyle += 5;
301 }
302
303 if ((ctx32 == 0) || dualcontext) {
304 flavor = PPC_VECTOR_STATE;
305 tstate = (void *)&mctx64.vs;
306 state_count = PPC_VECTOR_STATE_COUNT;
307 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
308 goto bad;
309 infostyle += 5;
310 }
311 }
312
313 trampact = ps->ps_trampact[sig];
314 uthsigaltstack = p->p_lflag & P_LTHSIGSTACK;
315
316 if (uthsigaltstack != 0 ) {
317 oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
318 altstack = ut->uu_flag & UT_ALTSTACK;
319 } else {
320 oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;
321 altstack = ps->ps_flags & SAS_ALTSTACK;
322 }
323
324
325 /* figure out where our new stack lives */
326 if (altstack && !oonstack &&
327 (ps->ps_sigonstack & sigmask(sig))) {
328 if (uthsigaltstack != 0) {
329 sp = ut->uu_sigstk.ss_sp;
330 sp += ut->uu_sigstk.ss_size;
331 stack_size = ut->uu_sigstk.ss_size;
332 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
333 } else {
334 sp = ps->ps_sigstk.ss_sp;
335 sp += ps->ps_sigstk.ss_size;
336 stack_size = ps->ps_sigstk.ss_size;
337 ps->ps_sigstk.ss_flags |= SA_ONSTACK;
338 }
339 }
340 else {
341 if (ctx32 == 0)
342 sp = mctx64.ss.r1;
343 else
344 sp = CAST_USER_ADDR_T(mctx.ss.r1);
345 }
346
347
348 /* put siginfo on top */
349
350 /* preserve RED ZONE area */
351 if (IS_64BIT_PROCESS(p))
352 sp = TRUNC_DOWN64(sp, C_64_REDZONE_LEN, C_64_STK_ALIGN);
353 else
354 sp = TRUNC_DOWN32(sp, C_32_REDZONE_LEN, C_32_STK_ALIGN);
355
356 /* next are the saved registers */
357 if ((ctx32 == 0) || dualcontext) {
358 sp -= sizeof(struct mcontext64);
359 p_mctx64 = sp;
360 }
361 if ((ctx32 == 1) || dualcontext) {
362 sp -= sizeof(struct mcontext);
363 p_mctx = sp;
364 }
365
366 if (IS_64BIT_PROCESS(p)) {
367 /* context goes first on stack */
368 sp -= sizeof(struct user_ucontext64);
369 p_uctx = sp;
370
371 /* this is where siginfo goes on stack */
372 sp -= sizeof(user_siginfo_t);
373 p_sinfo = sp;
374
375 sp = TRUNC_DOWN64(sp, C_64_PARAMSAVE_LEN+C_64_LINKAGE_LEN, C_64_STK_ALIGN);
376 } else {
377 /*
378 * struct ucontext and struct ucontext64 are identical in
379 * size and content; the only difference is the internal
380 * pointer type for the last element, which makes no
381 * difference for the copyout().
382 */
383
384 /* context goes first on stack */
385 sp -= sizeof(struct ucontext64);
386 p_uctx = sp;
387
388 /* this is where siginfo goes on stack */
389 sp -= sizeof(siginfo_t);
390 p_sinfo = sp;
391
392 sp = TRUNC_DOWN32(sp, C_32_PARAMSAVE_LEN+C_32_LINKAGE_LEN, C_32_STK_ALIGN);
393 }
394
395 uctx.uc_onstack = oonstack;
396 uctx.uc_sigmask = mask;
397 uctx.uc_stack.ss_sp = sp;
398 uctx.uc_stack.ss_size = stack_size;
399 if (oonstack)
400 uctx.uc_stack.ss_flags |= SS_ONSTACK;
401
402 uctx.uc_link = 0;
403 if (ctx32 == 0)
404 uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE64_COUNT + PPC_THREAD_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
405 else
406 uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE_COUNT + PPC_THREAD_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
407
408 if (vec_used)
409 uctx.uc_mcsize += (size_t)(PPC_VECTOR_STATE_COUNT * sizeof(int));
410
411 if (ctx32 == 0)
412 uctx.uc_mcontext64 = p_mctx64;
413 else
414 uctx.uc_mcontext64 = p_mctx;
415
416 /* setup siginfo */
417 bzero((caddr_t)&sinfo, sizeof(user_siginfo_t));
418 sinfo.si_signo = sig;
419 if (ctx32 == 0) {
420 sinfo.si_addr = mctx64.ss.srr0;
421 sinfo.pad[0] = mctx64.ss.r1;
422 } else {
423 sinfo.si_addr = CAST_USER_ADDR_T(mctx.ss.srr0);
424 sinfo.pad[0] = CAST_USER_ADDR_T(mctx.ss.r1);
425 }
426
427 switch (sig) {
428 case SIGCHLD:
429 sinfo.si_pid = p->si_pid;
430 p->si_pid =0;
431 sinfo.si_status = p->si_status;
432 p->si_status = 0;
433 sinfo.si_uid = p->si_uid;
434 p->si_uid =0;
435 sinfo.si_code = p->si_code;
436 p->si_code = 0;
437 if (sinfo.si_code == CLD_EXITED) {
438 if (WIFEXITED(sinfo.si_status))
439 sinfo.si_code = CLD_EXITED;
440 else if (WIFSIGNALED(sinfo.si_status)) {
441 if (WCOREDUMP(sinfo.si_status))
442 sinfo.si_code = CLD_DUMPED;
443 else
444 sinfo.si_code = CLD_KILLED;
445 }
446 }
447 break;
448 case SIGILL:
449 /*
450 * If it's 64 bit and not a dual context, mctx will
451 * contain uninitialized data, so we have to use
452 * mctx64 here.
453 */
454 if(ctx32 == 0) {
455 if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
456 sinfo.si_code = ILL_ILLOPC;
457 else if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
458 sinfo.si_code = ILL_PRVOPC;
459 else if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
460 sinfo.si_code = ILL_ILLTRP;
461 else
462 sinfo.si_code = ILL_NOOP;
463 } else {
464 if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
465 sinfo.si_code = ILL_ILLOPC;
466 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
467 sinfo.si_code = ILL_PRVOPC;
468 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
469 sinfo.si_code = ILL_ILLTRP;
470 else
471 sinfo.si_code = ILL_NOOP;
472 }
473 break;
474 case SIGFPE:
475 #define FPSCR_VX 2
476 #define FPSCR_OX 3
477 #define FPSCR_UX 4
478 #define FPSCR_ZX 5
479 #define FPSCR_XX 6
480 /*
481 * If it's 64 bit and not a dual context, mctx will
482 * contain uninitialized data, so we have to use
483 * mctx64 here.
484 */
485 if(ctx32 == 0) {
486 if (mctx64.fs.fpscr & (1 << (31 - FPSCR_VX)))
487 sinfo.si_code = FPE_FLTINV;
488 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_OX)))
489 sinfo.si_code = FPE_FLTOVF;
490 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_UX)))
491 sinfo.si_code = FPE_FLTUND;
492 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_ZX)))
493 sinfo.si_code = FPE_FLTDIV;
494 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_XX)))
495 sinfo.si_code = FPE_FLTRES;
496 else
497 sinfo.si_code = FPE_NOOP;
498 } else {
499 if (mctx.fs.fpscr & (1 << (31 - FPSCR_VX)))
500 sinfo.si_code = FPE_FLTINV;
501 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_OX)))
502 sinfo.si_code = FPE_FLTOVF;
503 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_UX)))
504 sinfo.si_code = FPE_FLTUND;
505 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_ZX)))
506 sinfo.si_code = FPE_FLTDIV;
507 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_XX)))
508 sinfo.si_code = FPE_FLTRES;
509 else
510 sinfo.si_code = FPE_NOOP;
511 }
512 break;
513
514 case SIGBUS:
515 if (ctx32 == 0) {
516 sinfo.si_addr = mctx64.es.dar;
517 } else {
518 sinfo.si_addr = CAST_USER_ADDR_T(mctx.es.dar);
519 }
520 /* on ppc we generate only if EXC_PPC_UNALIGNED */
521 sinfo.si_code = BUS_ADRALN;
522 break;
523
524 case SIGSEGV:
525 /*
526 * If it's 64 bit and not a dual context, mctx will
527 * contain uninitialized data, so we have to use
528 * mctx64 here.
529 */
530 if (ctx32 == 0) {
531 sinfo.si_addr = mctx64.es.dar;
532 /* First check in srr1 and then in dsisr */
533 if (mctx64.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
534 sinfo.si_code = SEGV_ACCERR;
535 else if (mctx64.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
536 sinfo.si_code = SEGV_ACCERR;
537 else
538 sinfo.si_code = SEGV_MAPERR;
539 } else {
540 sinfo.si_addr = CAST_USER_ADDR_T(mctx.es.dar);
541 /* First check in srr1 and then in dsisr */
542 if (mctx.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
543 sinfo.si_code = SEGV_ACCERR;
544 else if (mctx.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
545 sinfo.si_code = SEGV_ACCERR;
546 else
547 sinfo.si_code = SEGV_MAPERR;
548 }
549 break;
550 default:
551 break;
552 }
553
554
555 /* copy info out to user space */
556 if (IS_64BIT_PROCESS(p)) {
557 if (copyout(&uctx, p_uctx, sizeof(struct user_ucontext64)))
558 goto bad;
559 if (copyout(&sinfo, p_sinfo, sizeof(user_siginfo_t)))
560 goto bad;
561 } else {
562 struct ucontext64 uctx32;
563 siginfo_t sinfo32;
564
565 ucontext_64to32(&uctx, &uctx32);
566 if (copyout(&uctx32, p_uctx, sizeof(struct ucontext64)))
567 goto bad;
568
569 siginfo_64to32(&sinfo,&sinfo32);
570 if (copyout(&sinfo32, p_sinfo, sizeof(siginfo_t)))
571 goto bad;
572 }
573 if ((ctx32 == 0) || dualcontext) {
574 /*
575 * NOTE: Size of mcontext is not variant between 64bit and
576 * 32bit programs usng 64bit registers.
577 */
578 if (copyout(&mctx64, p_mctx64, (vec_used? UC_FLAVOR64_VEC_SIZE: UC_FLAVOR64_SIZE)))
579 goto bad;
580 }
581 if ((ctx32 == 1) || dualcontext) {
582 if (copyout(&mctx, p_mctx, uctx.uc_mcsize))
583 goto bad;
584 }
585
586
587 /* Place our arguments in arg registers: rtm dependent */
588 if(IS_64BIT_PROCESS(p)) {
589 mctx64.ss.r3 = catcher;
590 mctx64.ss.r4 = CAST_USER_ADDR_T(infostyle);
591 mctx64.ss.r5 = CAST_USER_ADDR_T(sig);
592 mctx64.ss.r6 = p_sinfo;
593 mctx64.ss.r7 = p_uctx;
594
595 mctx64.ss.srr0 = trampact;
596 /* MSR_EXPORT_MASK_SET */
597 mctx64.ss.srr1 = CAST_USER_ADDR_T(get_msr_exportmask());
598 mctx64.ss.r1 = sp;
599 state_count = PPC_THREAD_STATE64_COUNT;
600 if ((kretn = thread_setstatus(th_act, PPC_THREAD_STATE64, (void *)&mctx64.ss, state_count)) != KERN_SUCCESS) {
601 panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn);
602 }
603 } else {
604 mctx.ss.r3 = CAST_DOWN(unsigned long,catcher);
605 mctx.ss.r4 = (unsigned long)infostyle;
606 mctx.ss.r5 = (unsigned long)sig;
607 mctx.ss.r6 = CAST_DOWN(unsigned long,p_sinfo);
608 mctx.ss.r7 = CAST_DOWN(unsigned long,p_uctx);
609
610 mctx.ss.srr0 = CAST_DOWN(unsigned long,trampact);
611 /* MSR_EXPORT_MASK_SET */
612 mctx.ss.srr1 = get_msr_exportmask();
613 mctx.ss.r1 = CAST_DOWN(unsigned long,sp);
614 state_count = PPC_THREAD_STATE_COUNT;
615 if ((kretn = thread_setstatus(th_act, PPC_THREAD_STATE, (void *)&mctx.ss, state_count)) != KERN_SUCCESS) {
616 panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn);
617 }
618 }
619 return;
620
621 bad:
622 SIGACTION(p, SIGILL) = SIG_DFL;
623 sig = sigmask(SIGILL);
624 p->p_sigignore &= ~sig;
625 p->p_sigcatch &= ~sig;
626 ut->uu_sigmask &= ~sig;
627 /* sendsig is called with signal lock held */
628 psignal_lock(p, SIGILL, 0);
629 return;
630 }
631
632 /*
633 * System call to cleanup state after a signal
634 * has been taken. Reset signal mask and
635 * stack state from context left by sendsig (above).
636 * Return to previous pc and psl as specified by
637 * context left by sendsig. Check carefully to
638 * make sure that the user has not modified the
639 * psl to gain improper priviledges or to cause
640 * a machine fault.
641 */
642
643 /* ARGSUSED */
644 int
645 sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
646 {
647 struct user_ucontext64 uctx;
648
649 char mactx[sizeof(struct mcontext64)];
650 struct mcontext *p_mctx;
651 struct mcontext64 *p_64mctx;
652 int error;
653 thread_t th_act;
654 struct sigacts *ps = p->p_sigacts;
655 sigset_t mask;
656 user_addr_t action;
657 unsigned long state_count;
658 unsigned int state_flavor;
659 struct uthread * ut;
660 int vec_used = 0;
661 void *tsptr, *fptr, *vptr;
662 int infostyle = uap->infostyle;
663 int uthsigaltstack = 0;
664
665 th_act = current_thread();
666
667 ut = (struct uthread *)get_bsdthread_info(th_act);
668 if (IS_64BIT_PROCESS(p)) {
669 error = copyin(uap->uctx, &uctx, sizeof(struct user_ucontext64));
670 if (error)
671 return(error);
672 } else {
673 struct ucontext64 uctx32;
674
675 /*
676 * struct ucontext and struct ucontext64 are identical in
677 * size and content; the only difference is the internal
678 * pointer type for the last element, which makes no
679 * difference for the copyin().
680 */
681 error = copyin(uap->uctx, &uctx32, sizeof(struct ucontext));
682 if (error)
683 return(error);
684 ucontext_32to64(&uctx32, &uctx);
685 }
686
687
688 /* validate the machine context size */
689 switch (uctx.uc_mcsize) {
690 case UC_FLAVOR64_VEC_SIZE:
691 case UC_FLAVOR64_SIZE:
692 case UC_FLAVOR_VEC_SIZE:
693 case UC_FLAVOR_SIZE:
694 break;
695 default:
696 return(EINVAL);
697 }
698
699 /*
700 * The 64 bit process mcontext is identical to the mcontext64, so
701 * there is no conversion necessary.
702 */
703 error = copyin(uctx.uc_mcontext64, mactx, uctx.uc_mcsize);
704 if (error)
705 return(error);
706
707 uthsigaltstack = p->p_lflag & P_LTHSIGSTACK;
708
709
710 if (uctx.uc_onstack & 01) {
711 if (uthsigaltstack != 0)
712 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
713 else
714 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
715 } else {
716 if (uthsigaltstack != 0)
717 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
718 else
719 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
720 }
721
722 ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask;
723 if (ut->uu_siglist & ~ut->uu_sigmask)
724 signal_setast(current_thread());
725
726 vec_used = 0;
727 switch (infostyle) {
728 case UC_FLAVOR64_VEC:
729 case UC_TRAD64_VEC:
730 vec_used = 1;
731 case UC_TRAD64:
732 case UC_FLAVOR64: {
733 p_64mctx = (struct mcontext64 *)mactx;
734 tsptr = (void *)&p_64mctx->ss;
735 fptr = (void *)&p_64mctx->fs;
736 vptr = (void *)&p_64mctx->vs;
737 state_flavor = PPC_THREAD_STATE64;
738 state_count = PPC_THREAD_STATE64_COUNT;
739 }
740 break;
741 case UC_FLAVOR_VEC :
742 case UC_TRAD_VEC :
743 vec_used = 1;
744 case UC_FLAVOR :
745 case UC_TRAD :
746 default: {
747 p_mctx = (struct mcontext *)mactx;
748 tsptr = (void *)&p_mctx->ss;
749 fptr = (void *)&p_mctx->fs;
750 vptr = (void *)&p_mctx->vs;
751 state_flavor = PPC_THREAD_STATE;
752 state_count = PPC_THREAD_STATE_COUNT;
753 }
754 break;
755 } /* switch () */
756
757 /* validate the thread state, set/reset appropriate mode bits in srr1 */
758 (void)ppc_checkthreadstate(tsptr, state_flavor);
759
760 if (thread_setstatus(th_act, state_flavor, tsptr, state_count) != KERN_SUCCESS) {
761 return(EINVAL);
762 }
763
764 state_count = PPC_FLOAT_STATE_COUNT;
765 if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, state_count) != KERN_SUCCESS) {
766 return(EINVAL);
767 }
768
769 mask = sigmask(SIGFPE);
770 if (((ut->uu_sigmask & mask) == 0) && (p->p_sigcatch & mask) && ((p->p_sigignore & mask) == 0)) {
771 action = ps->ps_sigact[SIGFPE];
772 if((action != SIG_DFL) && (action != SIG_IGN)) {
773 thread_enable_fpe(th_act, 1);
774 }
775 }
776
777 if (vec_used) {
778 state_count = PPC_VECTOR_STATE_COUNT;
779 if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, state_count) != KERN_SUCCESS) {
780 return(EINVAL);
781 }
782 }
783 return (EJUSTRETURN);
784 }
785
786 /*
787 * machine_exception() performs MD translation
788 * of a mach exception to a unix signal and code.
789 */
790
791 boolean_t
792 machine_exception(
793 int exception,
794 int code,
795 __unused int subcode,
796 int *unix_signal,
797 int *unix_code
798 )
799 {
800 switch(exception) {
801
802 case EXC_BAD_INSTRUCTION:
803 *unix_signal = SIGILL;
804 *unix_code = code;
805 break;
806
807 case EXC_ARITHMETIC:
808 *unix_signal = SIGFPE;
809 *unix_code = code;
810 break;
811
812 case EXC_SOFTWARE:
813 if (code == EXC_PPC_TRAP) {
814 *unix_signal = SIGTRAP;
815 *unix_code = code;
816 break;
817 } else
818 return(FALSE);
819
820 default:
821 return(FALSE);
822 }
823
824 return(TRUE);
825 }
826