2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1992 NeXT, Inc.
32 * 13 May 1992 ? at NeXT
36 #include <mach/mach_types.h>
37 #include <mach/exception.h>
39 #include <kern/thread.h>
41 #include <sys/systm.h>
42 #include <sys/param.h>
43 #include <sys/proc_internal.h>
45 #include <sys/sysproto.h>
46 #include <sys/sysent.h>
47 #include <sys/ucontext.h>
49 #include <mach/thread_act.h> /* for thread_abort_safely */
50 #include <mach/thread_status.h>
51 #include <i386/machine_routines.h>
53 #include <i386/eflags.h>
57 #include <sys/kdebug.h>
60 extern boolean_t
machine_exception(int, int, int, int *, int *);
61 extern kern_return_t
thread_getstatus(register thread_t act
, int flavor
,
62 thread_state_t tstate
, mach_msg_type_number_t
*count
);
63 extern kern_return_t
thread_setstatus(thread_t thread
, int flavor
,
64 thread_state_t tstate
, mach_msg_type_number_t count
);
66 /* Signal handler flavors supported */
67 /* These defns should match the Libc implmn */
71 #define C_32_STK_ALIGN 16
72 #define C_64_STK_ALIGN 16
73 #define C_64_REDZONE_LEN 128
74 #define TRUNC_DOWN32(a,c) ((((uint32_t)a)-(c)) & ((uint32_t)(-(c))))
75 #define TRUNC_DOWN64(a,c) ((((uint64_t)a)-(c)) & ((uint64_t)(-(c))))
78 * Send an interrupt to process.
80 * Stack is set up to allow sigcode stored
81 * in u. to call routine, followed by chmk
82 * to sigreturn routine below. After sigreturn
83 * resets the signal mask, the stack, the frame
84 * pointer, and the argument pointer, it returns
85 * to the user specified pc, psl.
93 struct ucontext
* uctx
;
99 sendsig(struct proc
*p
, user_addr_t ua_catcher
, int sig
, int mask
, __unused u_long code
)
102 struct mcontext32 mctx32
;
103 struct mcontext64 mctx64
;
109 user_addr_t ua_uctxp
;
110 user_addr_t ua_mctxp
;
111 user_siginfo_t sinfo64
;
113 struct sigacts
*ps
= p
->p_sigacts
;
114 int oonstack
, flavor
;
116 mach_msg_type_number_t state_count
;
117 int uthsigaltstack
= 0;
120 thread_t thread
= current_thread();
123 int infostyle
= UC_TRAD
;
125 if (p
->p_sigacts
->ps_siginfo
& sigmask(sig
))
126 infostyle
= UC_FLAVOR
;
128 ut
= get_bsdthread_info(thread
);
130 uthsigaltstack
= p
->p_lflag
& P_LTHSIGSTACK
;
132 if (uthsigaltstack
!= 0 ) {
133 oonstack
= ut
->uu_sigstk
.ss_flags
& SA_ONSTACK
;
134 altstack
= ut
->uu_flag
& UT_ALTSTACK
;
136 oonstack
= ps
->ps_sigstk
.ss_flags
& SA_ONSTACK
;
137 altstack
= ps
->ps_flags
& SAS_ALTSTACK
;
142 bzero((caddr_t
)&sinfo64
, sizeof(user_siginfo_t
));
143 sinfo64
.si_signo
= sig
;
145 if (proc_is64bit(p
)) {
146 x86_thread_state64_t
*tstate64
;
147 struct user_ucontext64 uctx64
;
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
)
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
)
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
)
167 tstate64
= &mctx
.mctx64
.ss
;
169 if (altstack
&& !oonstack
&& (ps
->ps_sigonstack
& sigmask(sig
))) {
170 if (uthsigaltstack
!= 0) {
171 ua_sp
= ut
->uu_sigstk
.ss_sp
;
172 stack_size
= ut
->uu_sigstk
.ss_size
;
174 ut
->uu_sigstk
.ss_flags
|= SA_ONSTACK
;
176 ua_sp
= ps
->ps_sigstk
.ss_sp
;
177 stack_size
= ps
->ps_sigstk
.ss_size
;
179 ps
->ps_sigstk
.ss_flags
|= SA_ONSTACK
;
182 ua_sp
= tstate64
->rsp
;
183 ua_cr2
= mctx
.mctx64
.es
.faultvaddr
;
185 /* The x86_64 ABI defines a 128-byte red zone. */
186 ua_sp
-= C_64_REDZONE_LEN
;
188 ua_sp
-= sizeof (struct user_ucontext64
);
189 ua_uctxp
= ua_sp
; // someone tramples the first word!
191 ua_sp
-= sizeof (user_siginfo_t
);
194 ua_sp
-= sizeof (struct mcontext64
);
198 * Align the frame and stack pointers to 16 bytes for SSE.
199 * (Note that we use 'ua_fp' as the base of the stack going forward)
201 ua_fp
= TRUNC_DOWN64(ua_sp
, C_64_STK_ALIGN
);
204 * But we need to account for the return address so the alignment is
205 * truly "correct" at _sigtramp
207 ua_fp
-= sizeof(user_addr_t
);
210 * Build the signal context to be used by sigreturn.
212 bzero(&uctx64
, sizeof(uctx64
));
214 uctx64
.uc_onstack
= oonstack
;
215 uctx64
.uc_sigmask
= mask
;
216 uctx64
.uc_stack
.ss_sp
= ua_fp
;
217 uctx64
.uc_stack
.ss_size
= stack_size
;
220 uctx64
.uc_stack
.ss_flags
|= SS_ONSTACK
;
223 uctx64
.uc_mcsize
= sizeof(struct mcontext64
);
224 uctx64
.uc_mcontext64
= ua_mctxp
;
226 if (copyout((caddr_t
)&uctx64
, ua_uctxp
, sizeof (uctx64
)))
229 if (copyout((caddr_t
)&mctx
.mctx64
, ua_mctxp
, sizeof (struct mcontext64
)))
232 sinfo64
.pad
[0] = tstate64
->rsp
;
233 sinfo64
.si_addr
= tstate64
->rip
;
235 tstate64
->rip
= ps
->ps_trampact
[sig
];
236 tstate64
->rsp
= ua_fp
;
237 tstate64
->rflags
= get_eflags_exportmask();
239 * JOE - might not need to set these
241 tstate64
->cs
= USER64_CS
;
242 tstate64
->fs
= NULL_SEG
;
243 tstate64
->gs
= USER_CTHREAD
;
246 * Build the argument list for the signal handler.
247 * Handler should call sigreturn to get out of it
249 tstate64
->rdi
= ua_catcher
;
250 tstate64
->rsi
= infostyle
;
252 tstate64
->rcx
= ua_sip
;
253 tstate64
->r8
= ua_uctxp
;
256 x86_thread_state32_t
*tstate32
;
257 struct ucontext uctx32
;
258 struct sigframe32 frame32
;
260 flavor
= x86_THREAD_STATE32
;
261 state_count
= x86_THREAD_STATE32_COUNT
;
262 state
= (void *)&mctx
.mctx32
.ss
;
263 if (thread_getstatus(thread
, flavor
, (thread_state_t
)state
, &state_count
) != KERN_SUCCESS
)
266 flavor
= x86_FLOAT_STATE32
;
267 state_count
= x86_FLOAT_STATE32_COUNT
;
268 state
= (void *)&mctx
.mctx32
.fs
;
269 if (thread_getstatus(thread
, flavor
, (thread_state_t
)state
, &state_count
) != KERN_SUCCESS
)
272 flavor
= x86_EXCEPTION_STATE32
;
273 state_count
= x86_EXCEPTION_STATE32_COUNT
;
274 state
= (void *)&mctx
.mctx32
.es
;
275 if (thread_getstatus(thread
, flavor
, (thread_state_t
)state
, &state_count
) != KERN_SUCCESS
)
278 tstate32
= &mctx
.mctx32
.ss
;
280 if (altstack
&& !oonstack
&& (ps
->ps_sigonstack
& sigmask(sig
))) {
281 if (uthsigaltstack
!= 0) {
282 ua_sp
= ut
->uu_sigstk
.ss_sp
;
283 stack_size
= ut
->uu_sigstk
.ss_size
;
285 ut
->uu_sigstk
.ss_flags
|= SA_ONSTACK
;
287 ua_sp
= ps
->ps_sigstk
.ss_sp
;
288 stack_size
= ps
->ps_sigstk
.ss_size
;
290 ps
->ps_sigstk
.ss_flags
|= SA_ONSTACK
;
293 ua_sp
= tstate32
->esp
;
294 ua_cr2
= mctx
.mctx32
.es
.faultvaddr
;
296 ua_sp
-= sizeof (struct ucontext
);
297 ua_uctxp
= ua_sp
; // someone tramples the first word!
299 ua_sp
-= sizeof (siginfo_t
);
302 ua_sp
-= sizeof (struct mcontext32
);
305 ua_sp
-= sizeof (struct sigframe32
);
309 * Align the frame and stack pointers to 16 bytes for SSE.
310 * (Note that we use 'fp' as the base of the stack going forward)
312 ua_fp
= TRUNC_DOWN32(ua_fp
, C_32_STK_ALIGN
);
315 * But we need to account for the return address so the alignment is
316 * truly "correct" at _sigtramp
318 ua_fp
-= sizeof(frame32
.retaddr
);
321 * Build the argument list for the signal handler.
322 * Handler should call sigreturn to get out of it
324 frame32
.retaddr
= -1;
325 frame32
.sigstyle
= infostyle
;
327 frame32
.catcher
= CAST_DOWN(sig_t
, ua_catcher
);
328 frame32
.sinfo
= CAST_DOWN(siginfo_t
*, ua_sip
);
329 frame32
.uctx
= CAST_DOWN(struct ucontext
*, ua_uctxp
);
331 if (copyout((caddr_t
)&frame32
, ua_fp
, sizeof (frame32
)))
335 * Build the signal context to be used by sigreturn.
337 bzero(&uctx32
, sizeof(uctx32
));
339 uctx32
.uc_onstack
= oonstack
;
340 uctx32
.uc_sigmask
= mask
;
341 uctx32
.uc_stack
.ss_sp
= CAST_DOWN(char *, ua_fp
);
342 uctx32
.uc_stack
.ss_size
= stack_size
;
345 uctx32
.uc_stack
.ss_flags
|= SS_ONSTACK
;
348 uctx32
.uc_mcsize
= sizeof(struct mcontext32
);
350 uctx32
.uc_mcontext
= CAST_DOWN(struct mcontext
*, ua_mctxp
);
352 if (copyout((caddr_t
)&uctx32
, ua_uctxp
, sizeof (uctx32
)))
355 if (copyout((caddr_t
)&mctx
.mctx32
, ua_mctxp
, sizeof (struct mcontext32
)))
358 sinfo64
.pad
[0] = tstate32
->esp
;
359 sinfo64
.si_addr
= tstate32
->eip
;
364 sinfo64
.si_pid
= p
->si_pid
;
366 sinfo64
.si_status
= p
->si_status
;
368 sinfo64
.si_uid
= p
->si_uid
;
370 sinfo64
.si_code
= p
->si_code
;
372 if (sinfo64
.si_code
== CLD_EXITED
) {
373 if (WIFEXITED(sinfo64
.si_status
))
374 sinfo64
.si_code
= CLD_EXITED
;
375 else if (WIFSIGNALED(sinfo64
.si_status
)) {
376 if (WCOREDUMP(sinfo64
.si_status
))
377 sinfo64
.si_code
= CLD_DUMPED
;
379 sinfo64
.si_code
= CLD_KILLED
;
384 switch (ut
->uu_code
) {
386 sinfo64
.si_code
= ILL_ILLOPC
;
389 sinfo64
.si_code
= ILL_PRVOPC
;
392 printf("unknown SIGILL code %d\n", ut
->uu_code
);
393 sinfo64
.si_code
= ILL_NOOP
;
397 #define FP_IE 0 /* Invalid operation */
398 #define FP_DE 1 /* Denormalized operand */
399 #define FP_ZE 2 /* Zero divide */
400 #define FP_OE 3 /* overflow */
401 #define FP_UE 4 /* underflow */
402 #define FP_PE 5 /* precision */
403 if (ut
->uu_subcode
& (1 << FP_ZE
)) {
404 sinfo64
.si_code
= FPE_FLTDIV
;
405 } else if (ut
->uu_subcode
& (1 << FP_OE
)) {
406 sinfo64
.si_code
= FPE_FLTOVF
;
407 } else if (ut
->uu_subcode
& (1 << FP_UE
)) {
408 sinfo64
.si_code
= FPE_FLTUND
;
409 } else if (ut
->uu_subcode
& (1 << FP_PE
)) {
410 sinfo64
.si_code
= FPE_FLTRES
;
411 } else if (ut
->uu_subcode
& (1 << FP_IE
)) {
412 sinfo64
.si_code
= FPE_FLTINV
;
414 printf("unknown SIGFPE code %d, subcode %x\n",
415 ut
->uu_code
, ut
->uu_subcode
);
416 sinfo64
.si_code
= FPE_NOOP
;
420 sinfo64
.si_code
= BUS_ADRERR
;
421 sinfo64
.si_addr
= ua_cr2
;
424 sinfo64
.si_code
= TRAP_BRKPT
;
427 sinfo64
.si_addr
= ua_cr2
;
429 switch (ut
->uu_code
) {
430 case KERN_PROTECTION_FAILURE
:
431 sinfo64
.si_code
= SEGV_ACCERR
;
433 case KERN_INVALID_ADDRESS
:
434 sinfo64
.si_code
= SEGV_MAPERR
;
437 printf("unknown SIGSEGV code %d\n", ut
->uu_code
);
438 sinfo64
.si_code
= FPE_NOOP
;
444 if (proc_is64bit(p
)) {
445 if (copyout((caddr_t
)&sinfo64
, ua_sip
, sizeof (sinfo64
)))
448 flavor
= x86_THREAD_STATE64
;
449 state_count
= x86_THREAD_STATE64_COUNT
;
450 state
= (void *)&mctx
.mctx64
.ss
;
452 x86_thread_state32_t
*tstate32
;
455 bzero((caddr_t
)&sinfo32
, sizeof(siginfo_t
));
457 sinfo32
.si_signo
= sinfo64
.si_signo
;
458 sinfo32
.si_code
= sinfo64
.si_code
;
459 sinfo32
.si_pid
= sinfo64
.si_pid
;
460 sinfo32
.si_uid
= sinfo64
.si_uid
;
461 sinfo32
.si_status
= sinfo64
.si_status
;
462 sinfo32
.si_addr
= CAST_DOWN(void *, sinfo64
.si_addr
);
463 sinfo32
.pad
[0] = sinfo64
.pad
[0];
465 if (copyout((caddr_t
)&sinfo32
, ua_sip
, sizeof (sinfo32
)))
468 tstate32
= &mctx
.mctx32
.ss
;
469 tstate32
->eip
= CAST_DOWN(unsigned int, ps
->ps_trampact
[sig
]);
470 tstate32
->esp
= CAST_DOWN(unsigned int, ua_fp
);
472 tstate32
->eflags
= get_eflags_exportmask();
474 tstate32
->cs
= USER_CS
;
475 tstate32
->ss
= USER_DS
;
476 tstate32
->ds
= USER_DS
;
477 tstate32
->es
= USER_DS
;
478 tstate32
->fs
= NULL_SEG
;
479 tstate32
->gs
= USER_CTHREAD
;
481 flavor
= x86_THREAD_STATE32
;
482 state_count
= x86_THREAD_STATE32_COUNT
;
483 state
= (void *)tstate32
;
485 if (thread_setstatus(thread
, flavor
, (thread_state_t
)state
, state_count
) != KERN_SUCCESS
)
487 ml_fp_setvalid(FALSE
);
492 SIGACTION(p
, SIGILL
) = SIG_DFL
;
493 sig
= sigmask(SIGILL
);
494 p
->p_sigignore
&= ~sig
;
495 p
->p_sigcatch
&= ~sig
;
496 ut
->uu_sigmask
&= ~sig
;
497 /* sendsig is called with signal lock held */
498 psignal_lock(p
, SIGILL
, 0);
503 * System call to cleanup state after a signal
504 * has been taken. Reset signal mask and
505 * stack state from context left by sendsig (above).
506 * Return to previous pc and psl as specified by
507 * context left by sendsig. Check carefully to
508 * make sure that the user has not modified the
509 * psl to gain improper priviledges or to cause
516 struct sigreturn_args
*uap
,
517 __unused
int *retval
)
520 struct mcontext32 mctx32
;
521 struct mcontext64 mctx64
;
523 thread_t thread
= current_thread();
526 int uthsigaltstack
= 0;
529 mach_msg_type_number_t ts_count
;
530 unsigned int ts_flavor
;
532 mach_msg_type_number_t fs_count
;
533 unsigned int fs_flavor
;
536 ut
= (struct uthread
*)get_bsdthread_info(thread
);
537 uthsigaltstack
= p
->p_lflag
& P_LTHSIGSTACK
;
539 if (proc_is64bit(p
)) {
540 struct user_ucontext64 uctx64
;
542 if ((error
= copyin(uap
->uctx
, (void *)&uctx64
, sizeof (uctx64
))))
545 if ((error
= copyin(uctx64
.uc_mcontext64
, (void *)&mctx
.mctx64
, sizeof (struct mcontext64
))))
548 onstack
= uctx64
.uc_onstack
& 01;
549 ut
->uu_sigmask
= uctx64
.uc_sigmask
& ~sigcantmask
;
551 ts_flavor
= x86_THREAD_STATE64
;
552 ts_count
= x86_THREAD_STATE64_COUNT
;
553 ts
= (void *)&mctx
.mctx64
.ss
;
555 fs_flavor
= x86_FLOAT_STATE64
;
556 fs_count
= x86_FLOAT_STATE64_COUNT
;
557 fs
= (void *)&mctx
.mctx64
.fs
;
560 struct ucontext uctx32
;
562 if ((error
= copyin(uap
->uctx
, (void *)&uctx32
, sizeof (uctx32
))))
565 if ((error
= copyin(CAST_USER_ADDR_T(uctx32
.uc_mcontext
), (void *)&mctx
.mctx32
, sizeof (struct mcontext32
))))
568 onstack
= uctx32
.uc_onstack
& 01;
569 ut
->uu_sigmask
= uctx32
.uc_sigmask
& ~sigcantmask
;
571 ts_flavor
= x86_THREAD_STATE32
;
572 ts_count
= x86_THREAD_STATE32_COUNT
;
573 ts
= (void *)&mctx
.mctx32
.ss
;
575 fs_flavor
= x86_FLOAT_STATE32
;
576 fs_count
= x86_FLOAT_STATE32_COUNT
;
577 fs
= (void *)&mctx
.mctx32
.fs
;
580 if (uthsigaltstack
!= 0)
581 ut
->uu_sigstk
.ss_flags
|= SA_ONSTACK
;
583 p
->p_sigacts
->ps_sigstk
.ss_flags
|= SA_ONSTACK
;
585 if (uthsigaltstack
!= 0)
586 ut
->uu_sigstk
.ss_flags
&= ~SA_ONSTACK
;
588 p
->p_sigacts
->ps_sigstk
.ss_flags
&= ~SA_ONSTACK
;
590 if (ut
->uu_siglist
& ~ut
->uu_sigmask
)
591 signal_setast(thread
);
594 * thread_set_state() does all the needed checks for the passed in content
596 if (thread_setstatus(thread
, ts_flavor
, ts
, ts_count
) != KERN_SUCCESS
)
599 ml_fp_setvalid(TRUE
);
601 if (thread_setstatus(thread
, fs_flavor
, fs
, fs_count
) != KERN_SUCCESS
)
604 return (EJUSTRETURN
);
609 * machine_exception() performs MD translation
610 * of a mach exception to a unix signal and code.
617 __unused
int subcode
,
625 case EXC_BAD_INSTRUCTION
:
626 *unix_signal
= SIGILL
;
631 *unix_signal
= SIGFPE
;
642 #include <sys/systm.h>
643 #include <sys/sysent.h>
645 int __pthread_cset(struct sysent
*);
646 void __pthread_creset(struct sysent
*);
649 __pthread_cset(struct sysent
*callp
)
651 unsigned int cancel_enable
;
653 struct uthread
* uthread
;
655 thread
= current_thread();
656 uthread
= get_bsdthread_info(thread
);
658 cancel_enable
= callp
->sy_cancel
;
659 if (cancel_enable
== _SYSCALL_CANCEL_NONE
) {
660 uthread
->uu_flag
|= UT_NOTCANCELPT
;
662 if((uthread
->uu_flag
& (UT_CANCELDISABLE
| UT_CANCEL
| UT_CANCELED
)) == UT_CANCEL
) {
663 if (cancel_enable
== _SYSCALL_CANCEL_PRE
)
666 thread_abort_safely(thread
);
674 __pthread_creset(struct sysent
*callp
)
677 unsigned int cancel_enable
;
679 struct uthread
* uthread
;
681 thread
= current_thread();
682 uthread
= get_bsdthread_info(thread
);
684 cancel_enable
= callp
->sy_cancel
;
686 uthread
->uu_flag
&= ~UT_NOTCANCELPT
;