]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/i386/unix_signal.c
xnu-1699.32.7.tar.gz
[apple/xnu.git] / bsd / dev / i386 / unix_signal.c
CommitLineData
1c79356b 1/*
0c530ab8 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * Copyright (c) 1992 NeXT, Inc.
30 *
31 * HISTORY
32 * 13 May 1992 ? at NeXT
33 * Created.
34 */
35
36#include <mach/mach_types.h>
37#include <mach/exception.h>
38
39#include <kern/thread.h>
1c79356b 40
91447636 41#include <sys/systm.h>
1c79356b 42#include <sys/param.h>
91447636 43#include <sys/proc_internal.h>
1c79356b 44#include <sys/user.h>
91447636
A
45#include <sys/sysproto.h>
46#include <sys/sysent.h>
0c530ab8
A
47#include <sys/ucontext.h>
48#include <sys/wait.h>
91447636 49#include <mach/thread_act.h> /* for thread_abort_safely */
0c530ab8 50#include <mach/thread_status.h>
1c79356b 51
0c530ab8 52#include <i386/eflags.h>
1c79356b 53#include <i386/psl.h>
b0d623f7 54#include <i386/machine_routines.h>
91447636 55#include <i386/seg.h>
1c79356b 56
6d2010ae 57#include <machine/pal_routines.h>
1c79356b 58
6d2010ae 59#include <sys/kdebug.h>
2d21ac55
A
60#include <sys/sdt.h>
61
b0d623f7 62
91447636 63/* Forward: */
2d21ac55
A
64extern boolean_t machine_exception(int, mach_exception_code_t,
65 mach_exception_subcode_t, int *, mach_exception_subcode_t *);
0c530ab8
A
66extern kern_return_t thread_getstatus(register thread_t act, int flavor,
67 thread_state_t tstate, mach_msg_type_number_t *count);
68extern kern_return_t thread_setstatus(thread_t thread, int flavor,
69 thread_state_t tstate, mach_msg_type_number_t count);
1c79356b 70
55e303ae
A
71/* Signal handler flavors supported */
72/* These defns should match the Libc implmn */
73#define UC_TRAD 1
0c530ab8 74#define UC_FLAVOR 30
2d21ac55
A
75#define UC_SET_ALT_STACK 0x40000000
76#define UC_RESET_ALT_STACK 0x80000000
0c530ab8
A
77
78#define C_32_STK_ALIGN 16
79#define C_64_STK_ALIGN 16
80#define C_64_REDZONE_LEN 128
81#define TRUNC_DOWN32(a,c) ((((uint32_t)a)-(c)) & ((uint32_t)(-(c))))
82#define TRUNC_DOWN64(a,c) ((((uint64_t)a)-(c)) & ((uint64_t)(-(c))))
55e303ae 83
1c79356b
A
84/*
85 * Send an interrupt to process.
86 *
87 * Stack is set up to allow sigcode stored
88 * in u. to call routine, followed by chmk
89 * to sigreturn routine below. After sigreturn
90 * resets the signal mask, the stack, the frame
91 * pointer, and the argument pointer, it returns
92 * to the user specified pc, psl.
93 */
0c530ab8 94struct sigframe32 {
b0d623f7
A
95 int retaddr;
96 user32_addr_t catcher; /* sig_t */
97 int sigstyle;
98 int sig;
99 user32_addr_t sinfo; /* siginfo32_t* */
100 user32_addr_t uctx; /* struct ucontext32 */
0c530ab8
A
101};
102
b0d623f7
A
103/*
104 * NOTE: Source and target may *NOT* overlap!
105 */
106static void
107siginfo_user_to_user32(user_siginfo_t *in, user32_siginfo_t *out)
108{
109 out->si_signo = in->si_signo;
110 out->si_errno = in->si_errno;
111 out->si_code = in->si_code;
112 out->si_pid = in->si_pid;
113 out->si_uid = in->si_uid;
114 out->si_status = in->si_status;
115 out->si_addr = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_addr);
116 /* following cast works for sival_int because of padding */
117 out->si_value.sival_ptr = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_value.sival_ptr);
118 out->si_band = in->si_band; /* range reduction */
119 out->__pad[0] = in->pad[0]; /* mcontext.ss.r1 */
120}
0c530ab8 121
b0d623f7
A
122static void
123siginfo_user_to_user64(user_siginfo_t *in, user64_siginfo_t *out)
124{
125 out->si_signo = in->si_signo;
126 out->si_errno = in->si_errno;
127 out->si_code = in->si_code;
128 out->si_pid = in->si_pid;
129 out->si_uid = in->si_uid;
130 out->si_status = in->si_status;
131 out->si_addr = in->si_addr;
132 out->si_value.sival_ptr = in->si_value.sival_ptr;
133 out->si_band = in->si_band; /* range reduction */
134 out->__pad[0] = in->pad[0]; /* mcontext.ss.r1 */
135}
0c530ab8 136
1c79356b 137void
b0d623f7 138sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code)
1c79356b 139{
060df5ea
A
140 union {
141 struct mcontext_avx32 mctx_avx32;
142 struct mcontext_avx64 mctx_avx64;
143 } mctx_store, *mctxp = &mctx_store;
144
0c530ab8
A
145 user_addr_t ua_sp;
146 user_addr_t ua_fp;
147 user_addr_t ua_cr2;
148 user_addr_t ua_sip;
149 user_addr_t ua_uctxp;
150 user_addr_t ua_mctxp;
151 user_siginfo_t sinfo64;
152
1c79356b 153 struct sigacts *ps = p->p_sigacts;
0c530ab8 154 int oonstack, flavor;
b0d623f7
A
155 user_addr_t trampact;
156 int sigonstack;
0c530ab8
A
157 void * state;
158 mach_msg_type_number_t state_count;
0c530ab8 159
2d21ac55 160 thread_t thread;
9bccf70c 161 struct uthread * ut;
0c530ab8
A
162 int stack_size = 0;
163 int infostyle = UC_TRAD;
060df5ea
A
164 boolean_t sig_avx;
165
2d21ac55
A
166 thread = current_thread();
167 ut = get_bsdthread_info(thread);
168
0c530ab8
A
169 if (p->p_sigacts->ps_siginfo & sigmask(sig))
170 infostyle = UC_FLAVOR;
171
2d21ac55 172 oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
b0d623f7
A
173 trampact = ps->ps_trampact[sig];
174 sigonstack = (ps->ps_sigonstack & sigmask(sig));
1c79356b 175
9bccf70c 176 /*
0c530ab8 177 * init siginfo
9bccf70c 178 */
2d21ac55
A
179 proc_unlock(p);
180
b0d623f7 181 bzero((caddr_t)&sinfo64, sizeof(sinfo64));
0c530ab8 182 sinfo64.si_signo = sig;
060df5ea
A
183
184 bzero(mctxp, sizeof(*mctxp));
185 sig_avx = ml_fpu_avx_enabled();
2d21ac55 186
0c530ab8
A
187 if (proc_is64bit(p)) {
188 x86_thread_state64_t *tstate64;
189 struct user_ucontext64 uctx64;
190
191 flavor = x86_THREAD_STATE64;
192 state_count = x86_THREAD_STATE64_COUNT;
060df5ea 193 state = (void *)&mctxp->mctx_avx64.ss;
0c530ab8
A
194 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
195 goto bad;
196
060df5ea
A
197 if (sig_avx) {
198 flavor = x86_AVX_STATE64;
199 state_count = x86_AVX_STATE64_COUNT;
200 }
201 else {
202 flavor = x86_FLOAT_STATE64;
203 state_count = x86_FLOAT_STATE64_COUNT;
204 }
205 state = (void *)&mctxp->mctx_avx64.fs;
0c530ab8
A
206 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
207 goto bad;
208
209 flavor = x86_EXCEPTION_STATE64;
210 state_count = x86_EXCEPTION_STATE64_COUNT;
060df5ea 211 state = (void *)&mctxp->mctx_avx64.es;
0c530ab8
A
212 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
213 goto bad;
214
060df5ea 215 tstate64 = &mctxp->mctx_avx64.ss;
0c530ab8 216
2d21ac55
A
217 /* figure out where our new stack lives */
218 if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
b0d623f7 219 (sigonstack)) {
2d21ac55
A
220 ua_sp = ut->uu_sigstk.ss_sp;
221 stack_size = ut->uu_sigstk.ss_size;
222 ua_sp += stack_size;
223 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
224 } else {
0c530ab8 225 ua_sp = tstate64->rsp;
2d21ac55 226 }
060df5ea 227 ua_cr2 = mctxp->mctx_avx64.es.faultvaddr;
0c530ab8
A
228
229 /* The x86_64 ABI defines a 128-byte red zone. */
230 ua_sp -= C_64_REDZONE_LEN;
231
232 ua_sp -= sizeof (struct user_ucontext64);
233 ua_uctxp = ua_sp; // someone tramples the first word!
234
b0d623f7 235 ua_sp -= sizeof (user64_siginfo_t);
0c530ab8
A
236 ua_sip = ua_sp;
237
060df5ea 238 ua_sp -= sizeof (struct mcontext_avx64);
0c530ab8
A
239 ua_mctxp = ua_sp;
240
241 /*
242 * Align the frame and stack pointers to 16 bytes for SSE.
243 * (Note that we use 'ua_fp' as the base of the stack going forward)
244 */
245 ua_fp = TRUNC_DOWN64(ua_sp, C_64_STK_ALIGN);
246
247 /*
248 * But we need to account for the return address so the alignment is
249 * truly "correct" at _sigtramp
250 */
251 ua_fp -= sizeof(user_addr_t);
252
253 /*
254 * Build the signal context to be used by sigreturn.
255 */
256 bzero(&uctx64, sizeof(uctx64));
257
258 uctx64.uc_onstack = oonstack;
259 uctx64.uc_sigmask = mask;
260 uctx64.uc_stack.ss_sp = ua_fp;
261 uctx64.uc_stack.ss_size = stack_size;
262
263 if (oonstack)
264 uctx64.uc_stack.ss_flags |= SS_ONSTACK;
265 uctx64.uc_link = 0;
266
060df5ea 267 uctx64.uc_mcsize = sig_avx ? sizeof(struct mcontext_avx64) : sizeof(struct mcontext64);
0c530ab8
A
268 uctx64.uc_mcontext64 = ua_mctxp;
269
270 if (copyout((caddr_t)&uctx64, ua_uctxp, sizeof (uctx64)))
271 goto bad;
272
060df5ea 273 if (copyout((caddr_t)&mctxp->mctx_avx64, ua_mctxp, sizeof (struct mcontext_avx64)))
0c530ab8
A
274 goto bad;
275
276 sinfo64.pad[0] = tstate64->rsp;
277 sinfo64.si_addr = tstate64->rip;
278
b0d623f7 279 tstate64->rip = trampact;
0c530ab8
A
280 tstate64->rsp = ua_fp;
281 tstate64->rflags = get_eflags_exportmask();
282 /*
283 * JOE - might not need to set these
284 */
285 tstate64->cs = USER64_CS;
286 tstate64->fs = NULL_SEG;
287 tstate64->gs = USER_CTHREAD;
288
289 /*
290 * Build the argument list for the signal handler.
291 * Handler should call sigreturn to get out of it
292 */
293 tstate64->rdi = ua_catcher;
294 tstate64->rsi = infostyle;
295 tstate64->rdx = sig;
296 tstate64->rcx = ua_sip;
297 tstate64->r8 = ua_uctxp;
298
9bccf70c 299 } else {
0c530ab8 300 x86_thread_state32_t *tstate32;
b0d623f7 301 struct user_ucontext32 uctx32;
0c530ab8
A
302 struct sigframe32 frame32;
303
304 flavor = x86_THREAD_STATE32;
305 state_count = x86_THREAD_STATE32_COUNT;
060df5ea 306 state = (void *)&mctxp->mctx_avx32.ss;
0c530ab8
A
307 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
308 goto bad;
309
060df5ea
A
310 if (sig_avx) {
311 flavor = x86_AVX_STATE32;
312 state_count = x86_AVX_STATE32_COUNT;
313 }
314 else {
315 flavor = x86_FLOAT_STATE32;
316 state_count = x86_FLOAT_STATE32_COUNT;
317 }
318
319 state = (void *)&mctxp->mctx_avx32.fs;
0c530ab8
A
320 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
321 goto bad;
322
323 flavor = x86_EXCEPTION_STATE32;
324 state_count = x86_EXCEPTION_STATE32_COUNT;
060df5ea 325 state = (void *)&mctxp->mctx_avx32.es;
0c530ab8
A
326 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
327 goto bad;
328
060df5ea 329 tstate32 = &mctxp->mctx_avx32.ss;
0c530ab8 330
2d21ac55
A
331 /* figure out where our new stack lives */
332 if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
b0d623f7 333 (sigonstack)) {
2d21ac55
A
334 ua_sp = ut->uu_sigstk.ss_sp;
335 stack_size = ut->uu_sigstk.ss_size;
336 ua_sp += stack_size;
337 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
338 } else {
0c530ab8 339 ua_sp = tstate32->esp;
2d21ac55 340 }
060df5ea 341 ua_cr2 = mctxp->mctx_avx32.es.faultvaddr;
0c530ab8 342
b0d623f7 343 ua_sp -= sizeof (struct user_ucontext32);
0c530ab8
A
344 ua_uctxp = ua_sp; // someone tramples the first word!
345
b0d623f7 346 ua_sp -= sizeof (user32_siginfo_t);
0c530ab8
A
347 ua_sip = ua_sp;
348
060df5ea 349 ua_sp -= sizeof (struct mcontext_avx32);
0c530ab8
A
350 ua_mctxp = ua_sp;
351
352 ua_sp -= sizeof (struct sigframe32);
353 ua_fp = ua_sp;
354
355 /*
356 * Align the frame and stack pointers to 16 bytes for SSE.
357 * (Note that we use 'fp' as the base of the stack going forward)
358 */
359 ua_fp = TRUNC_DOWN32(ua_fp, C_32_STK_ALIGN);
360
361 /*
362 * But we need to account for the return address so the alignment is
363 * truly "correct" at _sigtramp
364 */
365 ua_fp -= sizeof(frame32.retaddr);
366
367 /*
368 * Build the argument list for the signal handler.
369 * Handler should call sigreturn to get out of it
370 */
371 frame32.retaddr = -1;
372 frame32.sigstyle = infostyle;
373 frame32.sig = sig;
b0d623f7
A
374 frame32.catcher = CAST_DOWN_EXPLICIT(user32_addr_t, ua_catcher);
375 frame32.sinfo = CAST_DOWN_EXPLICIT(user32_addr_t, ua_sip);
376 frame32.uctx = CAST_DOWN_EXPLICIT(user32_addr_t, ua_uctxp);
0c530ab8
A
377
378 if (copyout((caddr_t)&frame32, ua_fp, sizeof (frame32)))
379 goto bad;
380
381 /*
382 * Build the signal context to be used by sigreturn.
383 */
384 bzero(&uctx32, sizeof(uctx32));
385
386 uctx32.uc_onstack = oonstack;
387 uctx32.uc_sigmask = mask;
b0d623f7 388 uctx32.uc_stack.ss_sp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp);
0c530ab8
A
389 uctx32.uc_stack.ss_size = stack_size;
390
391 if (oonstack)
392 uctx32.uc_stack.ss_flags |= SS_ONSTACK;
393 uctx32.uc_link = 0;
394
060df5ea 395 uctx32.uc_mcsize = sig_avx ? sizeof(struct mcontext_avx32) : sizeof(struct mcontext32);
0c530ab8 396
b0d623f7 397 uctx32.uc_mcontext = CAST_DOWN_EXPLICIT(user32_addr_t, ua_mctxp);
0c530ab8
A
398
399 if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof (uctx32)))
400 goto bad;
401
060df5ea 402 if (copyout((caddr_t)&mctxp->mctx_avx32, ua_mctxp, sizeof (struct mcontext_avx32)))
0c530ab8
A
403 goto bad;
404
405 sinfo64.pad[0] = tstate32->esp;
406 sinfo64.si_addr = tstate32->eip;
9bccf70c 407 }
9bccf70c 408
0c530ab8 409 switch (sig) {
0c530ab8
A
410 case SIGILL:
411 switch (ut->uu_code) {
412 case EXC_I386_INVOP:
413 sinfo64.si_code = ILL_ILLOPC;
414 break;
0c530ab8 415 default:
0c530ab8
A
416 sinfo64.si_code = ILL_NOOP;
417 }
418 break;
419 case SIGFPE:
420#define FP_IE 0 /* Invalid operation */
421#define FP_DE 1 /* Denormalized operand */
422#define FP_ZE 2 /* Zero divide */
423#define FP_OE 3 /* overflow */
424#define FP_UE 4 /* underflow */
425#define FP_PE 5 /* precision */
b0d623f7
A
426 if (ut->uu_code == EXC_I386_DIV) {
427 sinfo64.si_code = FPE_INTDIV;
428 }
429 else if (ut->uu_code == EXC_I386_INTO) {
430 sinfo64.si_code = FPE_INTOVF;
431 }
432 else if (ut->uu_subcode & (1 << FP_ZE)) {
0c530ab8
A
433 sinfo64.si_code = FPE_FLTDIV;
434 } else if (ut->uu_subcode & (1 << FP_OE)) {
435 sinfo64.si_code = FPE_FLTOVF;
436 } else if (ut->uu_subcode & (1 << FP_UE)) {
437 sinfo64.si_code = FPE_FLTUND;
438 } else if (ut->uu_subcode & (1 << FP_PE)) {
439 sinfo64.si_code = FPE_FLTRES;
440 } else if (ut->uu_subcode & (1 << FP_IE)) {
441 sinfo64.si_code = FPE_FLTINV;
442 } else {
0c530ab8
A
443 sinfo64.si_code = FPE_NOOP;
444 }
445 break;
446 case SIGBUS:
447 sinfo64.si_code = BUS_ADRERR;
448 sinfo64.si_addr = ua_cr2;
449 break;
450 case SIGTRAP:
451 sinfo64.si_code = TRAP_BRKPT;
452 break;
453 case SIGSEGV:
454 sinfo64.si_addr = ua_cr2;
455
456 switch (ut->uu_code) {
2d21ac55
A
457 case EXC_I386_GPFLT:
458 /* CR2 is meaningless after GP fault */
459 /* XXX namespace clash! */
460 sinfo64.si_addr = 0ULL;
461 sinfo64.si_code = 0;
462 break;
0c530ab8
A
463 case KERN_PROTECTION_FAILURE:
464 sinfo64.si_code = SEGV_ACCERR;
465 break;
466 case KERN_INVALID_ADDRESS:
467 sinfo64.si_code = SEGV_MAPERR;
468 break;
469 default:
0c530ab8
A
470 sinfo64.si_code = FPE_NOOP;
471 }
472 break;
473 default:
2d21ac55
A
474 {
475 int status_and_exitcode;
476
477 /*
478 * All other signals need to fill out a minimum set of
479 * information for the siginfo structure passed into
480 * the signal handler, if SA_SIGINFO was specified.
481 *
482 * p->si_status actually contains both the status and
483 * the exit code; we save it off in its own variable
484 * for later breakdown.
485 */
486 proc_lock(p);
487 sinfo64.si_pid = p->si_pid;
488 p->si_pid =0;
489 status_and_exitcode = p->si_status;
490 p->si_status = 0;
491 sinfo64.si_uid = p->si_uid;
492 p->si_uid =0;
493 sinfo64.si_code = p->si_code;
494 p->si_code = 0;
495 proc_unlock(p);
496 if (sinfo64.si_code == CLD_EXITED) {
497 if (WIFEXITED(status_and_exitcode))
498 sinfo64.si_code = CLD_EXITED;
499 else if (WIFSIGNALED(status_and_exitcode)) {
500 if (WCOREDUMP(status_and_exitcode)) {
501 sinfo64.si_code = CLD_DUMPED;
502 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
503 } else {
504 sinfo64.si_code = CLD_KILLED;
505 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
506 }
507 }
508 }
509 /*
510 * The recorded status contains the exit code and the
511 * signal information, but the information to be passed
512 * in the siginfo to the handler is supposed to only
513 * contain the status, so we have to shift it out.
514 */
515 sinfo64.si_status = WEXITSTATUS(status_and_exitcode);
0c530ab8 516 break;
2d21ac55 517 }
0c530ab8
A
518 }
519 if (proc_is64bit(p)) {
b0d623f7
A
520 user64_siginfo_t sinfo64_user64;
521
522 bzero((caddr_t)&sinfo64_user64, sizeof(sinfo64_user64));
523
524 siginfo_user_to_user64(&sinfo64,&sinfo64_user64);
525
526#if CONFIG_DTRACE
527 bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
528
529 ut->t_dtrace_siginfo.si_signo = sinfo64.si_signo;
530 ut->t_dtrace_siginfo.si_code = sinfo64.si_code;
531 ut->t_dtrace_siginfo.si_pid = sinfo64.si_pid;
532 ut->t_dtrace_siginfo.si_uid = sinfo64.si_uid;
533 ut->t_dtrace_siginfo.si_status = sinfo64.si_status;
534 /* XXX truncates faulting address to void * on K32 */
535 ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo64.si_addr);
536
537 /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
538 switch (sig) {
539 case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
540 DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
541 break;
542 default:
543 break;
544 }
2d21ac55
A
545
546 /* XXX truncates catcher address to uintptr_t */
b0d623f7 547 DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
2d21ac55 548 void (*)(void), CAST_DOWN(sig_t, ua_catcher));
b0d623f7 549#endif /* CONFIG_DTRACE */
2d21ac55 550
b0d623f7
A
551 if (copyout((caddr_t)&sinfo64_user64, ua_sip, sizeof (sinfo64_user64)))
552 goto bad;
9bccf70c 553
0c530ab8
A
554 flavor = x86_THREAD_STATE64;
555 state_count = x86_THREAD_STATE64_COUNT;
060df5ea 556 state = (void *)&mctxp->mctx_avx64.ss;
0c530ab8 557 } else {
b0d623f7
A
558 x86_thread_state32_t *tstate32;
559 user32_siginfo_t sinfo32;
560
561 bzero((caddr_t)&sinfo32, sizeof(sinfo32));
0c530ab8 562
b0d623f7 563 siginfo_user_to_user32(&sinfo64,&sinfo32);
0c530ab8 564
b0d623f7
A
565#if CONFIG_DTRACE
566 bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
2d21ac55 567
b0d623f7
A
568 ut->t_dtrace_siginfo.si_signo = sinfo32.si_signo;
569 ut->t_dtrace_siginfo.si_code = sinfo32.si_code;
570 ut->t_dtrace_siginfo.si_pid = sinfo32.si_pid;
571 ut->t_dtrace_siginfo.si_uid = sinfo32.si_uid;
572 ut->t_dtrace_siginfo.si_status = sinfo32.si_status;
573 ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo32.si_addr);
574
575 /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
576 switch (sig) {
577 case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
578 DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
579 break;
580 default:
581 break;
582 }
583
584 DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
2d21ac55 585 void (*)(void), CAST_DOWN(sig_t, ua_catcher));
b0d623f7 586#endif /* CONFIG_DTRACE */
0c530ab8 587
b0d623f7
A
588 if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32)))
589 goto bad;
0c530ab8 590
060df5ea 591 tstate32 = &mctxp->mctx_avx32.ss;
b0d623f7
A
592
593 tstate32->eip = CAST_DOWN_EXPLICIT(user32_addr_t, trampact);
594 tstate32->esp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp);
595
0c530ab8
A
596 tstate32->eflags = get_eflags_exportmask();
597
598 tstate32->cs = USER_CS;
599 tstate32->ss = USER_DS;
600 tstate32->ds = USER_DS;
601 tstate32->es = USER_DS;
602 tstate32->fs = NULL_SEG;
603 tstate32->gs = USER_CTHREAD;
604
605 flavor = x86_THREAD_STATE32;
606 state_count = x86_THREAD_STATE32_COUNT;
607 state = (void *)tstate32;
608 }
609 if (thread_setstatus(thread, flavor, (thread_state_t)state, state_count) != KERN_SUCCESS)
610 goto bad;
611 ml_fp_setvalid(FALSE);
9bccf70c 612
6d2010ae
A
613 /* Tell the PAL layer about the signal */
614 pal_set_signal_delivery( thread );
b0d623f7 615
2d21ac55
A
616 proc_lock(p);
617
9bccf70c 618 return;
1c79356b
A
619
620bad:
060df5ea 621
2d21ac55 622 proc_lock(p);
1c79356b
A
623 SIGACTION(p, SIGILL) = SIG_DFL;
624 sig = sigmask(SIGILL);
625 p->p_sigignore &= ~sig;
626 p->p_sigcatch &= ~sig;
9bccf70c 627 ut->uu_sigmask &= ~sig;
1c79356b 628 /* sendsig is called with signal lock held */
2d21ac55
A
629 proc_unlock(p);
630 psignal_locked(p, SIGILL);
631 proc_lock(p);
1c79356b
A
632 return;
633}
634
635/*
636 * System call to cleanup state after a signal
637 * has been taken. Reset signal mask and
638 * stack state from context left by sendsig (above).
639 * Return to previous pc and psl as specified by
640 * context left by sendsig. Check carefully to
641 * make sure that the user has not modified the
642 * psl to gain improper priviledges or to cause
643 * a machine fault.
644 */
0c530ab8 645
1c79356b 646int
2d21ac55 647sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
1c79356b 648{
060df5ea
A
649 union {
650 struct mcontext_avx32 mctx_avx32;
651 struct mcontext_avx64 mctx_avx64;
652 } mctx_store, *mctxp = &mctx_store;
653
0c530ab8 654 thread_t thread = current_thread();
9bccf70c 655 struct uthread * ut;
0c530ab8 656 int error;
0c530ab8 657 int onstack = 0;
5d5c5d0d 658
0c530ab8
A
659 mach_msg_type_number_t ts_count;
660 unsigned int ts_flavor;
661 void * ts;
662 mach_msg_type_number_t fs_count;
663 unsigned int fs_flavor;
664 void * fs;
060df5ea
A
665 int rval = EJUSTRETURN;
666 boolean_t sig_avx;
5d5c5d0d 667
0c530ab8 668 ut = (struct uthread *)get_bsdthread_info(thread);
2d21ac55
A
669
670 /*
671 * If we are being asked to change the altstack flag on the thread, we
672 * just set/reset it and return (the uap->uctx is not used).
673 */
674 if ((unsigned int)uap->infostyle == UC_SET_ALT_STACK) {
675 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
676 return (0);
677 } else if ((unsigned int)uap->infostyle == UC_RESET_ALT_STACK) {
678 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
679 return (0);
680 }
4452a7af 681
060df5ea
A
682 bzero(mctxp, sizeof(*mctxp));
683 sig_avx = ml_fpu_avx_enabled();
684
0c530ab8
A
685 if (proc_is64bit(p)) {
686 struct user_ucontext64 uctx64;
4452a7af 687
0c530ab8
A
688 if ((error = copyin(uap->uctx, (void *)&uctx64, sizeof (uctx64))))
689 return(error);
4452a7af 690
060df5ea 691 if ((error = copyin(uctx64.uc_mcontext64, (void *)&mctxp->mctx_avx64, sizeof (struct mcontext_avx64))))
0c530ab8 692 return(error);
4452a7af 693
0c530ab8
A
694 onstack = uctx64.uc_onstack & 01;
695 ut->uu_sigmask = uctx64.uc_sigmask & ~sigcantmask;
89b3af67 696
060df5ea 697 ts_flavor = x86_THREAD_STATE64;
0c530ab8 698 ts_count = x86_THREAD_STATE64_COUNT;
060df5ea 699 ts = (void *)&mctxp->mctx_avx64.ss;
0c530ab8 700
060df5ea
A
701 if (sig_avx) {
702 fs_flavor = x86_AVX_STATE64;
703 fs_count = x86_AVX_STATE64_COUNT;
704 }
705 else {
706 fs_flavor = x86_FLOAT_STATE64;
707 fs_count = x86_FLOAT_STATE64_COUNT;
708 }
709
710 fs = (void *)&mctxp->mctx_avx64.fs;
0c530ab8
A
711
712 } else {
b0d623f7 713 struct user_ucontext32 uctx32;
0c530ab8
A
714
715 if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof (uctx32))))
716 return(error);
717
060df5ea 718 if ((error = copyin(CAST_USER_ADDR_T(uctx32.uc_mcontext), (void *)&mctxp->mctx_avx32, sizeof (struct mcontext_avx32))))
0c530ab8
A
719 return(error);
720
721 onstack = uctx32.uc_onstack & 01;
722 ut->uu_sigmask = uctx32.uc_sigmask & ~sigcantmask;
4452a7af 723
0c530ab8
A
724 ts_flavor = x86_THREAD_STATE32;
725 ts_count = x86_THREAD_STATE32_COUNT;
060df5ea
A
726 ts = (void *)&mctxp->mctx_avx32.ss;
727
728 if (sig_avx) {
729 fs_flavor = x86_AVX_STATE32;
730 fs_count = x86_AVX_STATE32_COUNT;
731 }
732 else {
733 fs_flavor = x86_FLOAT_STATE32;
734 fs_count = x86_FLOAT_STATE32_COUNT;
735 }
0c530ab8 736
060df5ea 737 fs = (void *)&mctxp->mctx_avx32.fs;
91447636 738 }
2d21ac55
A
739
740 if (onstack)
741 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
742 else
743 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
744
0c530ab8
A
745 if (ut->uu_siglist & ~ut->uu_sigmask)
746 signal_setast(thread);
0c530ab8 747 /*
2d21ac55
A
748 * thread_set_state() does all the needed checks for the passed in
749 * content
0c530ab8 750 */
060df5ea
A
751 if (thread_setstatus(thread, ts_flavor, ts, ts_count) != KERN_SUCCESS) {
752 rval = EINVAL;
753 goto error_ret;
754 }
755
0c530ab8
A
756 ml_fp_setvalid(TRUE);
757
060df5ea
A
758 if (thread_setstatus(thread, fs_flavor, fs, fs_count) != KERN_SUCCESS) {
759 rval = EINVAL;
760 goto error_ret;
1c79356b 761
060df5ea
A
762 }
763error_ret:
764 return rval;
1c79356b
A
765}
766
0c530ab8 767
1c79356b
A
768/*
769 * machine_exception() performs MD translation
770 * of a mach exception to a unix signal and code.
771 */
772
773boolean_t
774machine_exception(
2d21ac55
A
775 int exception,
776 mach_exception_code_t code,
777 __unused mach_exception_subcode_t subcode,
778 int *unix_signal,
779 mach_exception_code_t *unix_code)
91447636 780{
91447636 781
2d21ac55 782 switch(exception) {
91447636 783
2d21ac55
A
784 case EXC_BAD_ACCESS:
785 /* Map GP fault to SIGSEGV, otherwise defer to caller */
786 if (code == EXC_I386_GPFLT) {
787 *unix_signal = SIGSEGV;
788 *unix_code = code;
789 break;
790 }
791 return(FALSE);
792
793 case EXC_BAD_INSTRUCTION:
794 *unix_signal = SIGILL;
795 *unix_code = code;
796 break;
797
798 case EXC_ARITHMETIC:
799 *unix_signal = SIGFPE;
800 *unix_code = code;
801 break;
802
803 case EXC_SOFTWARE:
804 if (code == EXC_I386_BOUND) {
805 /*
806 * Map #BR, the Bound Range Exceeded exception, to
807 * SIGTRAP.
808 */
809 *unix_signal = SIGTRAP;
810 *unix_code = code;
811 break;
91447636 812 }
91447636 813
2d21ac55
A
814 default:
815 return(FALSE);
816 }
817
818 return(TRUE);
91447636
A
819}
820