]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/i386/unix_signal.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / bsd / dev / i386 / unix_signal.c
index 7a9291cae418f39fa31eadf62d52463ef3f89dc7..4f31f83e5a7914d19b21bbd014282b6f8691ca95 100644 (file)
 #include <sys/wait.h>
 #include <mach/thread_act.h>   /* for thread_abort_safely */
 #include <mach/thread_status.h>        
-#include <i386/machine_routines.h>
 
 #include <i386/eflags.h>
 #include <i386/psl.h>
+#include <i386/machine_routines.h>
 #include <i386/seg.h>
 
-#include <sys/kdebug.h>
+#include <machine/pal_routines.h>
 
+#include <sys/kdebug.h>
 #include <sys/sdt.h>
 
+
 /* Forward: */
 extern boolean_t machine_exception(int, mach_exception_code_t, 
                mach_exception_subcode_t, int *, mach_exception_subcode_t *);
@@ -90,23 +92,57 @@ extern kern_return_t thread_setstatus(thread_t thread, int flavor,
  * to the user specified pc, psl.
  */
 struct sigframe32 {
-        int              retaddr;
-       sig_t             catcher;
-       int               sigstyle;
-       int               sig;
-       siginfo_t       * sinfo;
-       struct ucontext * uctx;
+       int             retaddr;
+       user32_addr_t   catcher; /* sig_t */
+       int             sigstyle;
+       int             sig;
+       user32_addr_t   sinfo;  /* siginfo32_t* */
+       user32_addr_t   uctx;   /* struct ucontext32 */
 };
 
+/*
+ * NOTE: Source and target may *NOT* overlap!
+ * XXX: Unify with bsd/kern/kern_exit.c
+ */
+static void
+siginfo_user_to_user32_x86(user_siginfo_t *in, user32_siginfo_t *out)
+{
+       out->si_signo   = in->si_signo;
+       out->si_errno   = in->si_errno;
+       out->si_code    = in->si_code;
+       out->si_pid     = in->si_pid;
+       out->si_uid     = in->si_uid;
+       out->si_status  = in->si_status;
+       out->si_addr    = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_addr);
+       /* following cast works for sival_int because of padding */
+       out->si_value.sival_ptr = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_value.sival_ptr);
+       out->si_band    = in->si_band;                  /* range reduction */
+       out->__pad[0]   = in->pad[0];                   /* mcontext.ss.r1 */
+}
 
+static void
+siginfo_user_to_user64_x86(user_siginfo_t *in, user64_siginfo_t *out)
+{
+       out->si_signo   = in->si_signo;
+       out->si_errno   = in->si_errno;
+       out->si_code    = in->si_code;
+       out->si_pid     = in->si_pid;
+       out->si_uid     = in->si_uid;
+       out->si_status  = in->si_status;
+       out->si_addr    = in->si_addr;
+       out->si_value.sival_ptr = in->si_value.sival_ptr;
+       out->si_band    = in->si_band;                  /* range reduction */
+       out->__pad[0]   = in->pad[0];                   /* mcontext.ss.r1 */
+}
 
 void
-sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_long code)
+sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code)
 {
-        union {
-           struct mcontext32   mctx32;
-           struct mcontext64   mctx64;
-       } mctx;
+       union {
+               struct mcontext_avx32   mctx_avx32;
+               struct mcontext_avx64   mctx_avx64;
+       } mctx_store, *mctxp = &mctx_store;
+
        user_addr_t     ua_sp;
        user_addr_t     ua_fp;
        user_addr_t     ua_cr2;
@@ -117,6 +153,8 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
 
        struct sigacts *ps = p->p_sigacts;
        int oonstack, flavor; 
+       user_addr_t trampact;
+       int sigonstack;
        void * state;
        mach_msg_type_number_t state_count;
 
@@ -124,7 +162,8 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
        struct uthread * ut;
        int stack_size = 0;
        int infostyle = UC_TRAD;
-    
+       boolean_t       sig_avx;
+
        thread = current_thread();
        ut = get_bsdthread_info(thread);
 
@@ -132,15 +171,19 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                infostyle = UC_FLAVOR;
 
        oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
+       trampact = ps->ps_trampact[sig];
+       sigonstack = (ps->ps_sigonstack & sigmask(sig));
 
        /*
         * init siginfo
         */
        proc_unlock(p);
 
-       bzero((caddr_t)&sinfo64, sizeof(user_siginfo_t));
+       bzero((caddr_t)&sinfo64, sizeof(sinfo64));
        sinfo64.si_signo = sig;
-               
+
+       bzero(mctxp, sizeof(*mctxp));
+       sig_avx = ml_fpu_avx_enabled();
 
        if (proc_is64bit(p)) {
                x86_thread_state64_t    *tstate64;
@@ -148,27 +191,33 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
 
                flavor = x86_THREAD_STATE64;
                state_count = x86_THREAD_STATE64_COUNT;
-               state = (void *)&mctx.mctx64.ss;
+               state = (void *)&mctxp->mctx_avx64.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 (sig_avx) {
+                       flavor = x86_AVX_STATE64;
+                       state_count = x86_AVX_STATE64_COUNT;
+               }
+               else {
+                       flavor = x86_FLOAT_STATE64;
+                       state_count = x86_FLOAT_STATE64_COUNT;
+               }
+               state = (void *)&mctxp->mctx_avx64.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;
+               state = (void *)&mctxp->mctx_avx64.es;
                if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
                        goto bad;
 
-               tstate64 = &mctx.mctx64.ss;
+               tstate64 = &mctxp->mctx_avx64.ss;
 
                /* figure out where our new stack lives */
                if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
-                   (ps->ps_sigonstack & sigmask(sig))) {
+                   (sigonstack)) {
                        ua_sp = ut->uu_sigstk.ss_sp;
                        stack_size = ut->uu_sigstk.ss_size;
                        ua_sp += stack_size;
@@ -176,7 +225,7 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                } else {
                        ua_sp = tstate64->rsp;
                }
-               ua_cr2 = mctx.mctx64.es.faultvaddr;
+               ua_cr2 = mctxp->mctx_avx64.es.faultvaddr;
 
                /* The x86_64 ABI defines a 128-byte red zone. */
                ua_sp -= C_64_REDZONE_LEN;
@@ -184,10 +233,10 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                ua_sp -= sizeof (struct user_ucontext64);
                ua_uctxp = ua_sp;                        // someone tramples the first word!
 
-               ua_sp -= sizeof (user_siginfo_t);
+               ua_sp -= sizeof (user64_siginfo_t);
                ua_sip = ua_sp;
 
-               ua_sp -= sizeof (struct mcontext64);
+               ua_sp -= sizeof (struct mcontext_avx64);
                ua_mctxp = ua_sp;
 
                /*
@@ -216,19 +265,19 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                        uctx64.uc_stack.ss_flags |= SS_ONSTACK; 
                uctx64.uc_link = 0;
 
-               uctx64.uc_mcsize = sizeof(struct mcontext64);
+               uctx64.uc_mcsize = sig_avx ? sizeof(struct mcontext_avx64) : 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))) 
+               if (copyout((caddr_t)&mctxp->mctx_avx64, ua_mctxp, sizeof (struct mcontext_avx64))) 
                        goto bad;
 
                sinfo64.pad[0]  = tstate64->rsp;
                sinfo64.si_addr = tstate64->rip;
 
-               tstate64->rip = ps->ps_trampact[sig];
+               tstate64->rip = trampact;
                tstate64->rsp = ua_fp;
                tstate64->rflags = get_eflags_exportmask();
                /*
@@ -250,32 +299,39 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
 
        } else {
                x86_thread_state32_t    *tstate32;
-               struct ucontext         uctx32;
+               struct user_ucontext32  uctx32;
                struct sigframe32       frame32;
 
                flavor = x86_THREAD_STATE32;
                state_count = x86_THREAD_STATE32_COUNT;
-               state = (void *)&mctx.mctx32.ss;
+               state = (void *)&mctxp->mctx_avx32.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 (sig_avx) {
+                       flavor = x86_AVX_STATE32;
+                       state_count = x86_AVX_STATE32_COUNT;
+               }
+               else {
+                       flavor = x86_FLOAT_STATE32;
+                       state_count = x86_FLOAT_STATE32_COUNT;
+               }
+
+               state = (void *)&mctxp->mctx_avx32.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;
+               state = (void *)&mctxp->mctx_avx32.es;
                if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
                        goto bad;
 
-               tstate32 = &mctx.mctx32.ss;
+               tstate32 = &mctxp->mctx_avx32.ss;
 
                /* figure out where our new stack lives */
                if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
-                   (ps->ps_sigonstack & sigmask(sig))) {
+                   (sigonstack)) {
                        ua_sp = ut->uu_sigstk.ss_sp;
                        stack_size = ut->uu_sigstk.ss_size;
                        ua_sp += stack_size;
@@ -283,15 +339,15 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                } else {
                        ua_sp = tstate32->esp;
                }
-               ua_cr2 = mctx.mctx32.es.faultvaddr;
+               ua_cr2 = mctxp->mctx_avx32.es.faultvaddr;
 
-               ua_sp -= sizeof (struct ucontext);
+               ua_sp -= sizeof (struct user_ucontext32);
                ua_uctxp = ua_sp;                        // someone tramples the first word!
 
-               ua_sp -= sizeof (siginfo_t);
+               ua_sp -= sizeof (user32_siginfo_t);
                ua_sip = ua_sp;
 
-               ua_sp -= sizeof (struct mcontext32);
+               ua_sp -= sizeof (struct mcontext_avx32);
                ua_mctxp = ua_sp;
 
                ua_sp -= sizeof (struct sigframe32);
@@ -316,9 +372,9 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                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);
+               frame32.catcher = CAST_DOWN_EXPLICIT(user32_addr_t, ua_catcher);
+               frame32.sinfo = CAST_DOWN_EXPLICIT(user32_addr_t, ua_sip);
+               frame32.uctx = CAST_DOWN_EXPLICIT(user32_addr_t, ua_uctxp);
 
                if (copyout((caddr_t)&frame32, ua_fp, sizeof (frame32))) 
                        goto bad;
@@ -330,21 +386,21 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
 
                uctx32.uc_onstack = oonstack;
                uctx32.uc_sigmask = mask;
-               uctx32.uc_stack.ss_sp = CAST_DOWN(char *, ua_fp);
+               uctx32.uc_stack.ss_sp = CAST_DOWN_EXPLICIT(user32_addr_t, 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_mcsize = sig_avx ? sizeof(struct mcontext_avx32) : sizeof(struct mcontext32);
 
-               uctx32.uc_mcontext = CAST_DOWN(_STRUCT_MCONTEXT32 *, ua_mctxp);
+               uctx32.uc_mcontext = CAST_DOWN_EXPLICIT(user32_addr_t, ua_mctxp);
                
                if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof (uctx32))) 
                        goto bad;
 
-               if (copyout((caddr_t)&mctx.mctx32, ua_mctxp, sizeof (struct mcontext32))) 
+               if (copyout((caddr_t)&mctxp->mctx_avx32, ua_mctxp, sizeof (struct mcontext_avx32))) 
                        goto bad;
 
                sinfo64.pad[0]  = tstate32->esp;
@@ -358,7 +414,6 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                                        sinfo64.si_code = ILL_ILLOPC;
                                        break;
                                default:
-                                       printf("unknown SIGILL code %ld\n", (long) ut->uu_code);
                                        sinfo64.si_code = ILL_NOOP;
                        }
                        break;
@@ -369,7 +424,13 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
 #define FP_OE 3 /* overflow */
 #define FP_UE 4 /* underflow */
 #define FP_PE 5 /* precision */
-                       if (ut->uu_subcode & (1 << FP_ZE)) {
+                       if (ut->uu_code == EXC_I386_DIV) {
+                               sinfo64.si_code = FPE_INTDIV;
+                       }
+                       else if (ut->uu_code == EXC_I386_INTO) {
+                               sinfo64.si_code = FPE_INTOVF;
+                       }
+                       else 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;
@@ -380,8 +441,6 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                        } else if (ut->uu_subcode & (1 << FP_IE)) {
                                sinfo64.si_code = FPE_FLTINV;
                        } else {
-                               printf("unknown SIGFPE code %ld, subcode %lx\n",
-                                      (long) ut->uu_code, (long) ut->uu_subcode);
                                sinfo64.si_code = FPE_NOOP;
                        }
                        break;
@@ -409,7 +468,6 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                                        sinfo64.si_code = SEGV_MAPERR;
                                        break;
                                default:
-                                       printf("unknown SIGSEGV code %ld\n", (long) ut->uu_code);
                                        sinfo64.si_code = FPE_NOOP;
                        }
                                break;
@@ -460,41 +518,82 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                }
        }
        if (proc_is64bit(p)) {
+               user64_siginfo_t sinfo64_user64;
+               
+               bzero((caddr_t)&sinfo64_user64, sizeof(sinfo64_user64));
+                         
+               siginfo_user_to_user64_x86(&sinfo64,&sinfo64_user64);
+
+#if CONFIG_DTRACE
+        bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
+
+        ut->t_dtrace_siginfo.si_signo = sinfo64.si_signo;
+        ut->t_dtrace_siginfo.si_code = sinfo64.si_code;
+        ut->t_dtrace_siginfo.si_pid = sinfo64.si_pid;
+        ut->t_dtrace_siginfo.si_uid = sinfo64.si_uid;
+        ut->t_dtrace_siginfo.si_status = sinfo64.si_status;
+               /* XXX truncates faulting address to void * on K32  */
+        ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo64.si_addr);
+
+               /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
+               switch (sig) {
+               case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
+                       DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
+                       break;
+               default:
+                       break;
+               }
 
                /* XXX truncates catcher address to uintptr_t */
-               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo64,
+               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
                        void (*)(void), CAST_DOWN(sig_t, ua_catcher));
+#endif /* CONFIG_DTRACE */
 
-               if (copyout((caddr_t)&sinfo64, ua_sip, sizeof (sinfo64))) 
-                       goto bad;
+               if (copyout((caddr_t)&sinfo64_user64, ua_sip, sizeof (sinfo64_user64))) 
+                       goto bad;
 
                flavor = x86_THREAD_STATE64;
                state_count = x86_THREAD_STATE64_COUNT;
-               state = (void *)&mctx.mctx64.ss;
+               state = (void *)&mctxp->mctx_avx64.ss;
        } else {
-               x86_thread_state32_t    *tstate32;
-               siginfo_t               sinfo32;
+               x86_thread_state32_t    *tstate32;
+               user32_siginfo_t sinfo32;
+
+               bzero((caddr_t)&sinfo32, sizeof(sinfo32));
+
+               siginfo_user_to_user32_x86(&sinfo64,&sinfo32);
+
+#if CONFIG_DTRACE
+        bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
 
-               bzero((caddr_t)&sinfo32, sizeof(siginfo_t));
+        ut->t_dtrace_siginfo.si_signo = sinfo32.si_signo;
+        ut->t_dtrace_siginfo.si_code = sinfo32.si_code;
+        ut->t_dtrace_siginfo.si_pid = sinfo32.si_pid;
+        ut->t_dtrace_siginfo.si_uid = sinfo32.si_uid;
+        ut->t_dtrace_siginfo.si_status = sinfo32.si_status;
+        ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo32.si_addr);
 
-               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];
+               /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
+               switch (sig) {
+               case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
+                       DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
+                       break;
+               default:
+                       break;
+               }
 
-               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo32,
+               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
                        void (*)(void), CAST_DOWN(sig_t, ua_catcher));
+#endif /* CONFIG_DTRACE */
 
-               if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32))) 
-                       goto bad;
+               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 = &mctxp->mctx_avx32.ss;
+
+               tstate32->eip = CAST_DOWN_EXPLICIT(user32_addr_t, trampact);
+               tstate32->esp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp);
+
                tstate32->eflags = get_eflags_exportmask();
 
                tstate32->cs = USER_CS;
@@ -512,11 +611,15 @@ sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_lo
                goto bad;
        ml_fp_setvalid(FALSE);
 
+       /* Tell the PAL layer about the signal */
+       pal_set_signal_delivery( thread );
+
        proc_lock(p);
 
        return;
 
 bad:
+
        proc_lock(p);
        SIGACTION(p, SIGILL) = SIG_DFL;
        sig = sigmask(SIGILL);
@@ -544,10 +647,11 @@ bad:
 int
 sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
 {
-        union {
-           struct mcontext32   mctx32;
-           struct mcontext64   mctx64;
-       } mctx;
+       union {
+               struct mcontext_avx32   mctx_avx32;
+               struct mcontext_avx64   mctx_avx64;
+       } mctx_store, *mctxp = &mctx_store;
+
        thread_t thread = current_thread();
        struct uthread * ut;
        int     error;
@@ -559,6 +663,8 @@ sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
        mach_msg_type_number_t fs_count;
        unsigned int           fs_flavor;
        void                *  fs;
+       int     rval = EJUSTRETURN;
+       boolean_t       sig_avx;
 
        ut = (struct uthread *)get_bsdthread_info(thread);
 
@@ -574,33 +680,43 @@ sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
                return (0);
        }
 
+       bzero(mctxp, sizeof(*mctxp));
+       sig_avx = ml_fpu_avx_enabled();
+
        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))))
+               if ((error = copyin(uctx64.uc_mcontext64, (void *)&mctxp->mctx_avx64, sizeof (struct mcontext_avx64))))
                        return(error);
 
                onstack = uctx64.uc_onstack & 01;
                ut->uu_sigmask = uctx64.uc_sigmask & ~sigcantmask;
 
-               ts_flavor = x86_THREAD_STATE64;
+               ts_flavor = x86_THREAD_STATE64;
                ts_count  = x86_THREAD_STATE64_COUNT;
-               ts = (void *)&mctx.mctx64.ss;
+               ts = (void *)&mctxp->mctx_avx64.ss;
 
-               fs_flavor = x86_FLOAT_STATE64;
-               fs_count  = x86_FLOAT_STATE64_COUNT;
-               fs = (void *)&mctx.mctx64.fs;
+               if (sig_avx) {
+                       fs_flavor = x86_AVX_STATE64;
+                       fs_count = x86_AVX_STATE64_COUNT;
+               }
+               else {
+                       fs_flavor = x86_FLOAT_STATE64;
+                       fs_count = x86_FLOAT_STATE64_COUNT;
+               }
+
+               fs = (void *)&mctxp->mctx_avx64.fs;
 
       } else {
-               struct ucontext         uctx32;
+               struct user_ucontext32  uctx32;
 
                if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof (uctx32)))) 
                        return(error);
 
-               if ((error = copyin(CAST_USER_ADDR_T(uctx32.uc_mcontext), (void *)&mctx.mctx32, sizeof (struct mcontext32)))) 
+               if ((error = copyin(CAST_USER_ADDR_T(uctx32.uc_mcontext), (void *)&mctxp->mctx_avx32, sizeof (struct mcontext_avx32)))) 
                        return(error);
 
                onstack = uctx32.uc_onstack & 01;
@@ -608,11 +724,18 @@ sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
 
                ts_flavor = x86_THREAD_STATE32;
                ts_count  = x86_THREAD_STATE32_COUNT;
-               ts = (void *)&mctx.mctx32.ss;
+               ts = (void *)&mctxp->mctx_avx32.ss;
 
-               fs_flavor = x86_FLOAT_STATE32;
-               fs_count  = x86_FLOAT_STATE32_COUNT;
-               fs = (void *)&mctx.mctx32.fs;
+               if (sig_avx) {
+                       fs_flavor = x86_AVX_STATE32;
+                       fs_count = x86_AVX_STATE32_COUNT;
+               }
+               else {
+                       fs_flavor = x86_FLOAT_STATE32;
+                       fs_count = x86_FLOAT_STATE32_COUNT;
+               }
+
+               fs = (void *)&mctxp->mctx_avx32.fs;
        }
 
        if (onstack)
@@ -622,20 +745,24 @@ sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
 
        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);
-
+       if (thread_setstatus(thread, ts_flavor, ts, ts_count) != KERN_SUCCESS) {
+               rval = EINVAL;
+               goto error_ret;
+       }
+       
        ml_fp_setvalid(TRUE);
 
-       if (thread_setstatus(thread, fs_flavor, fs, fs_count)  != KERN_SUCCESS)
-               return(EINVAL);
+       if (thread_setstatus(thread, fs_flavor, fs, fs_count)  != KERN_SUCCESS) {
+               rval = EINVAL;
+               goto error_ret;
 
-       return (EJUSTRETURN);
+       }
+error_ret:
+       return rval;
 }