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