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