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