X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/c0fea4742e91338fffdcf79f86a7c1d5e2b97eb1..8ad349bb6ed4a0be06e34c92be0d98b92e078db4:/bsd/dev/i386/unix_signal.c?ds=sidebyside diff --git a/bsd/dev/i386/unix_signal.c b/bsd/dev/i386/unix_signal.c index 8c6305d52..5fd7eab7e 100644 --- a/bsd/dev/i386/unix_signal.c +++ b/bsd/dev/i386/unix_signal.c @@ -1,23 +1,31 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ * - * @APPLE_LICENSE_HEADER_END@ + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the + * License may not be used to create, or enable the creation or + * redistribution of, unlawful or unlicensed copies of an Apple operating + * system, or to circumvent, violate, or enable the circumvention or + * violation of, any terms of an Apple operating system software license + * agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ */ /* * Copyright (c) 1992 NeXT, Inc. @@ -38,35 +46,28 @@ #include #include #include -#include -#include #include /* for thread_abort_safely */ -#include -#include -#include #include #include -#include +#include + +extern struct i386_saved_state *get_user_regs(thread_t); + +extern boolean_t valid_user_segment_selectors(uint16_t cs, + uint16_t ss, + uint16_t ds, + uint16_t es, + uint16_t fs, + uint16_t gs); /* Forward: */ extern boolean_t machine_exception(int, int, int, int *, int *); -extern kern_return_t thread_getstatus(register thread_t act, int flavor, - thread_state_t tstate, mach_msg_type_number_t *count); -extern kern_return_t thread_setstatus(thread_t thread, int flavor, - thread_state_t tstate, mach_msg_type_number_t count); /* Signal handler flavors supported */ /* These defns should match the Libc implmn */ #define UC_TRAD 1 -#define UC_FLAVOR 30 - -#define C_32_STK_ALIGN 16 -#define C_64_STK_ALIGN 16 -#define C_64_REDZONE_LEN 128 -#define TRUNC_DOWN32(a,c) ((((uint32_t)a)-(c)) & ((uint32_t)(-(c)))) -#define TRUNC_DOWN64(a,c) ((((uint64_t)a)-(c)) & ((uint64_t)(-(c)))) /* * Send an interrupt to process. @@ -78,408 +79,101 @@ extern kern_return_t thread_setstatus(thread_t thread, int flavor, * pointer, and the argument pointer, it returns * to the user specified pc, psl. */ -struct sigframe32 { - int retaddr; - sig_t catcher; - int sigstyle; - int sig; - siginfo_t * sinfo; - struct ucontext * uctx; -}; - - - void -sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_long code) +sendsig(p, catcher, sig, mask, code) + struct proc *p; + user_addr_t catcher; /* sig_t */ + int sig, mask; + u_long code; { - union { - struct mcontext32 mctx32; - struct mcontext64 mctx64; - } mctx; - user_addr_t ua_sp; - user_addr_t ua_fp; - user_addr_t ua_cr2; - user_addr_t ua_sip; - user_addr_t ua_uctxp; - user_addr_t ua_mctxp; - user_siginfo_t sinfo64; - + struct sigframe { + int retaddr; + sig_t catcher; + int sigstyle; + int sig; + int code; + struct sigcontext * scp; + } frame, *fp; + struct sigcontext context, *scp; struct sigacts *ps = p->p_sigacts; - int oonstack, flavor; - void * state; - mach_msg_type_number_t state_count; - int uthsigaltstack = 0; - int altstack = 0; - + int oonstack; thread_t thread = current_thread(); struct uthread * ut; - int stack_size = 0; - int infostyle = UC_TRAD; + struct i386_saved_state * saved_state = get_user_regs(thread); + sig_t trampact; - if (p->p_sigacts->ps_siginfo & sigmask(sig)) - infostyle = UC_FLAVOR; - ut = get_bsdthread_info(thread); + oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK; + if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack && + (ps->ps_sigonstack & sigmask(sig))) { + scp = ((struct sigcontext *)ps->ps_sigstk.ss_sp) - 1; + ps->ps_sigstk.ss_flags |= SA_ONSTACK; + } else + scp = ((struct sigcontext *)saved_state->uesp) - 1; + fp = ((struct sigframe *)scp) - 1; + + /* + * Build the argument list for the signal handler. + */ - uthsigaltstack = p->p_lflag & P_LTHSIGSTACK; + trampact = (sig_t)ps->ps_trampact[sig]; + /* Handler should call sigreturn to get out of it */ + frame.retaddr = 0xffffffff; + frame.catcher = CAST_DOWN(sig_t,catcher); /* XXX LP64 */ + frame.sigstyle = UC_TRAD; + frame.sig = sig; + + if (sig == SIGILL || sig == SIGFPE) { + frame.code = code; + } else + frame.code = 0; + frame.scp = scp; + if (copyout((caddr_t)&frame, (user_addr_t)fp, sizeof (frame))) + goto bad; - if (uthsigaltstack != 0 ) { - oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK; - altstack = ut->uu_flag & UT_ALTSTACK; - } else { - oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK; - altstack = ps->ps_flags & SAS_ALTSTACK; - } /* - * init siginfo + * Build the signal context to be used by sigreturn. */ - bzero((caddr_t)&sinfo64, sizeof(user_siginfo_t)); - sinfo64.si_signo = sig; - - if (proc_is64bit(p)) { - x86_thread_state64_t *tstate64; - struct user_ucontext64 uctx64; - - flavor = x86_THREAD_STATE64; - state_count = x86_THREAD_STATE64_COUNT; - state = (void *)&mctx.mctx64.ss; - if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) - goto bad; - - flavor = x86_FLOAT_STATE64; - state_count = x86_FLOAT_STATE64_COUNT; - state = (void *)&mctx.mctx64.fs; - if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) - goto bad; - - flavor = x86_EXCEPTION_STATE64; - state_count = x86_EXCEPTION_STATE64_COUNT; - state = (void *)&mctx.mctx64.es; - if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) - goto bad; - - tstate64 = &mctx.mctx64.ss; - - if (altstack && !oonstack && (ps->ps_sigonstack & sigmask(sig))) { - if (uthsigaltstack != 0) { - ua_sp = ut->uu_sigstk.ss_sp; - stack_size = ut->uu_sigstk.ss_size; - ua_sp += stack_size; - ut->uu_sigstk.ss_flags |= SA_ONSTACK; - } else { - ua_sp = ps->ps_sigstk.ss_sp; - stack_size = ps->ps_sigstk.ss_size; - ua_sp += stack_size; - ps->ps_sigstk.ss_flags |= SA_ONSTACK; - } - } else - ua_sp = tstate64->rsp; - ua_cr2 = mctx.mctx64.es.faultvaddr; - - /* The x86_64 ABI defines a 128-byte red zone. */ - ua_sp -= C_64_REDZONE_LEN; - - ua_sp -= sizeof (struct user_ucontext64); - ua_uctxp = ua_sp; // someone tramples the first word! - - ua_sp -= sizeof (user_siginfo_t); - ua_sip = ua_sp; - - ua_sp -= sizeof (struct mcontext64); - ua_mctxp = ua_sp; - - /* - * Align the frame and stack pointers to 16 bytes for SSE. - * (Note that we use 'ua_fp' as the base of the stack going forward) - */ - ua_fp = TRUNC_DOWN64(ua_sp, C_64_STK_ALIGN); - - /* - * But we need to account for the return address so the alignment is - * truly "correct" at _sigtramp - */ - ua_fp -= sizeof(user_addr_t); - - /* - * Build the signal context to be used by sigreturn. - */ - bzero(&uctx64, sizeof(uctx64)); - - uctx64.uc_onstack = oonstack; - uctx64.uc_sigmask = mask; - uctx64.uc_stack.ss_sp = ua_fp; - uctx64.uc_stack.ss_size = stack_size; - - if (oonstack) - uctx64.uc_stack.ss_flags |= SS_ONSTACK; - uctx64.uc_link = 0; - - uctx64.uc_mcsize = sizeof(struct mcontext64); - uctx64.uc_mcontext64 = ua_mctxp; - - if (copyout((caddr_t)&uctx64, ua_uctxp, sizeof (uctx64))) - goto bad; - - if (copyout((caddr_t)&mctx.mctx64, ua_mctxp, sizeof (struct mcontext64))) - goto bad; - - sinfo64.pad[0] = tstate64->rsp; - sinfo64.si_addr = tstate64->rip; - - tstate64->rip = ps->ps_trampact[sig]; - tstate64->rsp = ua_fp; - tstate64->rflags = get_eflags_exportmask(); - /* - * JOE - might not need to set these - */ - tstate64->cs = USER64_CS; - tstate64->fs = NULL_SEG; - tstate64->gs = USER_CTHREAD; - - /* - * Build the argument list for the signal handler. - * Handler should call sigreturn to get out of it - */ - tstate64->rdi = ua_catcher; - tstate64->rsi = infostyle; - tstate64->rdx = sig; - tstate64->rcx = ua_sip; - tstate64->r8 = ua_uctxp; - + context.sc_onstack = oonstack; + context.sc_mask = mask; + context.sc_eax = saved_state->eax; + context.sc_ebx = saved_state->ebx; + context.sc_ecx = saved_state->ecx; + context.sc_edx = saved_state->edx; + context.sc_edi = saved_state->edi; + context.sc_esi = saved_state->esi; + context.sc_ebp = saved_state->ebp; + context.sc_esp = saved_state->uesp; + context.sc_ss = saved_state->ss; + context.sc_eflags = saved_state->efl; + context.sc_eip = saved_state->eip; + context.sc_cs = saved_state->cs; + if (saved_state->efl & EFL_VM) { + context.sc_ds = saved_state->v86_segs.v86_ds; + context.sc_es = saved_state->v86_segs.v86_es; + context.sc_fs = saved_state->v86_segs.v86_fs; + context.sc_gs = saved_state->v86_segs.v86_gs; + + saved_state->efl &= ~EFL_VM; } else { - x86_thread_state32_t *tstate32; - struct ucontext uctx32; - struct sigframe32 frame32; - - flavor = x86_THREAD_STATE32; - state_count = x86_THREAD_STATE32_COUNT; - state = (void *)&mctx.mctx32.ss; - if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) - goto bad; - - flavor = x86_FLOAT_STATE32; - state_count = x86_FLOAT_STATE32_COUNT; - state = (void *)&mctx.mctx32.fs; - if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) - goto bad; - - flavor = x86_EXCEPTION_STATE32; - state_count = x86_EXCEPTION_STATE32_COUNT; - state = (void *)&mctx.mctx32.es; - if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) - goto bad; - - tstate32 = &mctx.mctx32.ss; - - if (altstack && !oonstack && (ps->ps_sigonstack & sigmask(sig))) { - if (uthsigaltstack != 0) { - ua_sp = ut->uu_sigstk.ss_sp; - stack_size = ut->uu_sigstk.ss_size; - ua_sp += stack_size; - ut->uu_sigstk.ss_flags |= SA_ONSTACK; - } else { - ua_sp = ps->ps_sigstk.ss_sp; - stack_size = ps->ps_sigstk.ss_size; - ua_sp += stack_size; - ps->ps_sigstk.ss_flags |= SA_ONSTACK; - } - } else - ua_sp = tstate32->esp; - ua_cr2 = mctx.mctx32.es.faultvaddr; - - ua_sp -= sizeof (struct ucontext); - ua_uctxp = ua_sp; // someone tramples the first word! - - ua_sp -= sizeof (siginfo_t); - ua_sip = ua_sp; - - ua_sp -= sizeof (struct mcontext32); - ua_mctxp = ua_sp; - - ua_sp -= sizeof (struct sigframe32); - ua_fp = ua_sp; - - /* - * Align the frame and stack pointers to 16 bytes for SSE. - * (Note that we use 'fp' as the base of the stack going forward) - */ - ua_fp = TRUNC_DOWN32(ua_fp, C_32_STK_ALIGN); - - /* - * But we need to account for the return address so the alignment is - * truly "correct" at _sigtramp - */ - ua_fp -= sizeof(frame32.retaddr); - - /* - * Build the argument list for the signal handler. - * Handler should call sigreturn to get out of it - */ - frame32.retaddr = -1; - frame32.sigstyle = infostyle; - frame32.sig = sig; - frame32.catcher = CAST_DOWN(sig_t, ua_catcher); - frame32.sinfo = CAST_DOWN(siginfo_t *, ua_sip); - frame32.uctx = CAST_DOWN(struct ucontext *, ua_uctxp); - - if (copyout((caddr_t)&frame32, ua_fp, sizeof (frame32))) - goto bad; - - /* - * Build the signal context to be used by sigreturn. - */ - bzero(&uctx32, sizeof(uctx32)); - - uctx32.uc_onstack = oonstack; - uctx32.uc_sigmask = mask; - uctx32.uc_stack.ss_sp = CAST_DOWN(char *, ua_fp); - uctx32.uc_stack.ss_size = stack_size; - - if (oonstack) - uctx32.uc_stack.ss_flags |= SS_ONSTACK; - uctx32.uc_link = 0; - - uctx32.uc_mcsize = sizeof(struct mcontext32); - - uctx32.uc_mcontext = CAST_DOWN(struct mcontext *, ua_mctxp); - - if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof (uctx32))) - goto bad; - - if (copyout((caddr_t)&mctx.mctx32, ua_mctxp, sizeof (struct mcontext32))) - goto bad; - - sinfo64.pad[0] = tstate32->esp; - sinfo64.si_addr = tstate32->eip; + context.sc_ds = saved_state->ds; + context.sc_es = saved_state->es; + context.sc_fs = saved_state->fs; + context.sc_gs = saved_state->gs; } + if (copyout((caddr_t)&context, (user_addr_t)scp, sizeof (context))) + goto bad; - switch (sig) { - case SIGCHLD: - sinfo64.si_pid = p->si_pid; - p->si_pid =0; - sinfo64.si_status = p->si_status; - p->si_status = 0; - sinfo64.si_uid = p->si_uid; - p->si_uid =0; - sinfo64.si_code = p->si_code; - p->si_code = 0; - if (sinfo64.si_code == CLD_EXITED) { - if (WIFEXITED(sinfo64.si_status)) - sinfo64.si_code = CLD_EXITED; - else if (WIFSIGNALED(sinfo64.si_status)) { - if (WCOREDUMP(sinfo64.si_status)) - sinfo64.si_code = CLD_DUMPED; - else - sinfo64.si_code = CLD_KILLED; - } - } - break; - case SIGILL: - switch (ut->uu_code) { - case EXC_I386_INVOP: - sinfo64.si_code = ILL_ILLOPC; - break; - case EXC_I386_GPFLT: - sinfo64.si_code = ILL_PRVOPC; - break; - default: - printf("unknown SIGILL code %d\n", ut->uu_code); - sinfo64.si_code = ILL_NOOP; - } - break; - case SIGFPE: -#define FP_IE 0 /* Invalid operation */ -#define FP_DE 1 /* Denormalized operand */ -#define FP_ZE 2 /* Zero divide */ -#define FP_OE 3 /* overflow */ -#define FP_UE 4 /* underflow */ -#define FP_PE 5 /* precision */ - if (ut->uu_subcode & (1 << FP_ZE)) { - sinfo64.si_code = FPE_FLTDIV; - } else if (ut->uu_subcode & (1 << FP_OE)) { - sinfo64.si_code = FPE_FLTOVF; - } else if (ut->uu_subcode & (1 << FP_UE)) { - sinfo64.si_code = FPE_FLTUND; - } else if (ut->uu_subcode & (1 << FP_PE)) { - sinfo64.si_code = FPE_FLTRES; - } else if (ut->uu_subcode & (1 << FP_IE)) { - sinfo64.si_code = FPE_FLTINV; - } else { - printf("unknown SIGFPE code %d, subcode %x\n", - ut->uu_code, ut->uu_subcode); - sinfo64.si_code = FPE_NOOP; - } - break; - case SIGBUS: - sinfo64.si_code = BUS_ADRERR; - sinfo64.si_addr = ua_cr2; - break; - case SIGTRAP: - sinfo64.si_code = TRAP_BRKPT; - break; - case SIGSEGV: - sinfo64.si_addr = ua_cr2; - - switch (ut->uu_code) { - case KERN_PROTECTION_FAILURE: - sinfo64.si_code = SEGV_ACCERR; - break; - case KERN_INVALID_ADDRESS: - sinfo64.si_code = SEGV_MAPERR; - break; - default: - printf("unknown SIGSEGV code %d\n", ut->uu_code); - sinfo64.si_code = FPE_NOOP; - } - break; - default: - break; - } - if (proc_is64bit(p)) { - if (copyout((caddr_t)&sinfo64, ua_sip, sizeof (sinfo64))) - goto bad; - - flavor = x86_THREAD_STATE64; - state_count = x86_THREAD_STATE64_COUNT; - state = (void *)&mctx.mctx64.ss; - } else { - x86_thread_state32_t *tstate32; - siginfo_t sinfo32; + saved_state->eip = (unsigned int)trampact; + saved_state->cs = USER_CS; - bzero((caddr_t)&sinfo32, sizeof(siginfo_t)); - - sinfo32.si_signo = sinfo64.si_signo; - sinfo32.si_code = sinfo64.si_code; - sinfo32.si_pid = sinfo64.si_pid; - sinfo32.si_uid = sinfo64.si_uid; - sinfo32.si_status = sinfo64.si_status; - sinfo32.si_addr = CAST_DOWN(void *, sinfo64.si_addr); - sinfo32.pad[0] = sinfo64.pad[0]; - - if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32))) - goto bad; - - tstate32 = &mctx.mctx32.ss; - tstate32->eip = CAST_DOWN(unsigned int, ps->ps_trampact[sig]); - tstate32->esp = CAST_DOWN(unsigned int, ua_fp); - - tstate32->eflags = get_eflags_exportmask(); - - tstate32->cs = USER_CS; - tstate32->ss = USER_DS; - tstate32->ds = USER_DS; - tstate32->es = USER_DS; - tstate32->fs = NULL_SEG; - tstate32->gs = USER_CTHREAD; - - flavor = x86_THREAD_STATE32; - state_count = x86_THREAD_STATE32_COUNT; - state = (void *)tstate32; - } - if (thread_setstatus(thread, flavor, (thread_state_t)state, state_count) != KERN_SUCCESS) - goto bad; - ml_fp_setvalid(FALSE); + saved_state->uesp = (unsigned int)fp; + saved_state->ss = USER_DS; + saved_state->ds = USER_DS; + saved_state->es = USER_DS; + saved_state->fs = NULL_SEG; + saved_state->gs = USER_CTHREAD; return; bad: @@ -503,102 +197,92 @@ bad: * psl to gain improper priviledges or to cause * a machine fault. */ - +/* ARGSUSED */ int sigreturn( struct proc *p, struct sigreturn_args *uap, __unused int *retval) { - union { - struct mcontext32 mctx32; - struct mcontext64 mctx64; - } mctx; - thread_t thread = current_thread(); + struct sigcontext context; + thread_t thread = current_thread(); + int error; + struct i386_saved_state* saved_state = (struct i386_saved_state*) + get_user_regs(thread); struct uthread * ut; - int error; - int uthsigaltstack = 0; - int onstack = 0; - - mach_msg_type_number_t ts_count; - unsigned int ts_flavor; - void * ts; - mach_msg_type_number_t fs_count; - unsigned int fs_flavor; - void * fs; - - ut = (struct uthread *)get_bsdthread_info(thread); - uthsigaltstack = p->p_lflag & P_LTHSIGSTACK; - if (proc_is64bit(p)) { - struct user_ucontext64 uctx64; - if ((error = copyin(uap->uctx, (void *)&uctx64, sizeof (uctx64)))) - return(error); - - if ((error = copyin(uctx64.uc_mcontext64, (void *)&mctx.mctx64, sizeof (struct mcontext64)))) - return(error); - - onstack = uctx64.uc_onstack & 01; - ut->uu_sigmask = uctx64.uc_sigmask & ~sigcantmask; - - ts_flavor = x86_THREAD_STATE64; - ts_count = x86_THREAD_STATE64_COUNT; - ts = (void *)&mctx.mctx64.ss; - - fs_flavor = x86_FLOAT_STATE64; - fs_count = x86_FLOAT_STATE64_COUNT; - fs = (void *)&mctx.mctx64.fs; + + if (saved_state == NULL) + return EINVAL; - } else { - struct ucontext uctx32; + if ((error = copyin(CAST_USER_ADDR_T(uap->sigcntxp), (void *)&context, + sizeof (context)))) + return(error); - if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof (uctx32)))) - return(error); + /* + * Validate segment selectors. + * Bad values would result in kernel exception at context switch + * back to user mode. If other state is invalid an exception will + * occur in user context. + */ + if (!valid_user_segment_selectors(context.sc_cs, + context.sc_ss, + context.sc_ds, + context.sc_es, + context.sc_fs, + context.sc_gs)) { + return EINVAL; + } - if ((error = copyin(CAST_USER_ADDR_T(uctx32.uc_mcontext), (void *)&mctx.mctx32, sizeof (struct mcontext32)))) - return(error); + ut = (struct uthread *)get_bsdthread_info(thread); - onstack = uctx32.uc_onstack & 01; - ut->uu_sigmask = uctx32.uc_sigmask & ~sigcantmask; + if (context.sc_onstack & 01) + p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; - ts_flavor = x86_THREAD_STATE32; - ts_count = x86_THREAD_STATE32_COUNT; - ts = (void *)&mctx.mctx32.ss; + ut->uu_sigmask = context.sc_mask &~ sigcantmask; + if(ut->uu_siglist & ~ut->uu_sigmask) + signal_setast(thread); - fs_flavor = x86_FLOAT_STATE32; - fs_count = x86_FLOAT_STATE32_COUNT; - fs = (void *)&mctx.mctx32.fs; + saved_state->eax = context.sc_eax; + saved_state->ebx = context.sc_ebx; + saved_state->ecx = context.sc_ecx; + saved_state->edx = context.sc_edx; + saved_state->edi = context.sc_edi; + saved_state->esi = context.sc_esi; + saved_state->ebp = context.sc_ebp; + saved_state->uesp = context.sc_esp; + saved_state->ss = context.sc_ss; + saved_state->efl = context.sc_eflags; + saved_state->efl &= ~EFL_USERCLR; + saved_state->efl |= EFL_USERSET; + saved_state->eip = context.sc_eip; + saved_state->cs = context.sc_cs; + + if (context.sc_eflags & EFL_VM) { + saved_state->ds = NULL_SEG; + saved_state->es = NULL_SEG; + saved_state->fs = NULL_SEG; + saved_state->gs = NULL_SEG; + saved_state->v86_segs.v86_ds = context.sc_ds; + saved_state->v86_segs.v86_es = context.sc_es; + saved_state->v86_segs.v86_fs = context.sc_fs; + saved_state->v86_segs.v86_gs = context.sc_gs; + + saved_state->efl |= EFL_VM; } - if (onstack) { - if (uthsigaltstack != 0) - ut->uu_sigstk.ss_flags |= SA_ONSTACK; - else - p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; - } else { - if (uthsigaltstack != 0) - ut->uu_sigstk.ss_flags &= ~SA_ONSTACK; - else - p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; + else { + saved_state->ds = context.sc_ds; + saved_state->es = context.sc_es; + saved_state->fs = context.sc_fs; + saved_state->gs = context.sc_gs; } - if (ut->uu_siglist & ~ut->uu_sigmask) - signal_setast(thread); - - /* - * thread_set_state() does all the needed checks for the passed in content - */ - if (thread_setstatus(thread, ts_flavor, ts, ts_count) != KERN_SUCCESS) - return(EINVAL); - - ml_fp_setvalid(TRUE); - - if (thread_setstatus(thread, fs_flavor, fs, fs_count) != KERN_SUCCESS) - return(EINVAL); return (EJUSTRETURN); } - /* * machine_exception() performs MD translation * of a mach exception to a unix signal and code.