Print this page

        

@@ -18,10 +18,13 @@
  *
  * CDDL HEADER END
  */
 
 /*
+ * Copyright 2015 Joyent, Inc.
+ */
+/*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */

@@ -48,10 +51,11 @@
 #include <sys/errno.h>
 #include <sys/archsystm.h>
 #include <sys/schedctl.h>
 #include <sys/debug.h>
 #include <sys/sysmacros.h>
+#include <sys/sdt.h>
 
 /*
  * This is a wrapper around copyout_noerr that returns a guaranteed error code.
  * Because we're using copyout_noerr(), we need to bound the time we're under an
  * on_fault/no_fault and attempt to do so only while we're actually copying data

@@ -189,11 +193,19 @@
         if (fpu_en)
                 getfpregs(lwp, &ucp->uc_mcontext.fpregs);
         else
                 ucp->uc_flags &= ~UC_FPU;
 
+        if (mask != NULL) {
+                /*
+                 * Save signal mask.
+                 */
         sigktou(mask, &ucp->uc_sigmask);
+        } else {
+                ucp->uc_flags &= ~UC_SIGMASK;
+                bzero(&ucp->uc_sigmask, sizeof (ucp->uc_sigmask));
+        }
 
         /*
          * Determine if we need to get the reset of the xsave context out here.
          * If the thread doesn't actually have the FPU enabled, then we don't
          * actually need to do this. We also don't have to if it wasn't

@@ -218,10 +230,19 @@
                     savecontext_copyout);
         } else {
                 ret = fpu_signal_copyout(lwp, ucp->uc_xsave, copyout);
         }
 
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_savecontext != NULL) {
+                /*
+                 * Allow the brand the chance to modify the context we
+                 * saved:
+                 */
+                /* XXX KEBE SAYS FIX ME! */
+                BROP(p)->b_savecontext(ucp);
+        }
+
         return (ret);
 }
 
 /*
  * Restore user context.

@@ -229,11 +250,23 @@
 void
 restorecontext(ucontext_t *ucp)
 {
         kthread_t *t = curthread;
         klwp_t *lwp = ttolwp(t);
+        proc_t *p = lwptoproc(lwp);
 
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_restorecontext != NULL) {
+                /*
+                 * Allow the brand the chance to modify the context before
+                 * we restore it:
+                 */
+                BROP(p)->b_restorecontext(ucp);
+        }
+
+        DTRACE_PROBE3(oldcontext__set, klwp_t *, lwp,
+            uintptr_t, lwp->lwp_oldcontext,
+            uintptr_t, (uintptr_t)ucp->uc_link);
         lwp->lwp_oldcontext = (uintptr_t)ucp->uc_link;
 
         if (ucp->uc_flags & UC_STACK) {
                 if (ucp->uc_stack.ss_flags == SS_ONSTACK)
                         lwp->lwp_sigaltstack = ucp->uc_stack;

@@ -288,10 +321,11 @@
         ucontext_t uc;
         ucontext_t *ucp;
         klwp_t *lwp = ttolwp(curthread);
         void *fpu = NULL;
         stack_t dummy_stk;
+        proc_t *p = lwptoproc(lwp);
         int ret;
 
         /*
          * In future releases, when the ucontext structure grows,
          * getcontext should be modified to only return the fields

@@ -352,11 +386,11 @@
                         exit(CLD_EXITED, 0);
                 /*
                  * Don't copyin filler or floating state unless we need it.
                  * The ucontext_t struct and fields are specified in the ABI.
                  */
-                if (copyin(ucp, &uc, offsetof(ucontext_t, uc_filler) -
+                if (copyin(ucp, &uc, offsetof(ucontext_t, uc_brand_data) -
                     sizeof (uc.uc_mcontext.fpregs))) {
                         return (set_errno(EFAULT));
                 }
                 if (uc.uc_flags & UC_SIGMASK)
                         SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);

@@ -365,10 +399,19 @@
                     copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
                     sizeof (uc.uc_mcontext.fpregs))) {
                         return (set_errno(EFAULT));
                 }
 
+                /*
+                 * If this is a branded process, copy in the brand-private
+                 * data:
+                 */
+                if (PROC_IS_BRANDED(p) && copyin(&ucp->uc_brand_data,
+                    &uc.uc_brand_data, sizeof (uc.uc_brand_data)) != 0) {
+                        return (set_errno(EFAULT));
+                }
+
                 uc.uc_xsave = 0;
                 if ((uc.uc_flags & UC_XSAVE) != 0) {
                         int ret;
 
                         if (copyin(&ucp->uc_xsave, &uc.uc_xsave,

@@ -482,11 +525,19 @@
         if (fpu_en)
                 getfpregs32(lwp, &ucp->uc_mcontext.fpregs);
         else
                 ucp->uc_flags &= ~UC_FPU;
 
+        if (mask != NULL) {
+                /*
+                 * Save signal mask.
+                 */
         sigktou(mask, &ucp->uc_sigmask);
+        } else {
+                ucp->uc_flags &= ~UC_SIGMASK;
+                bzero(&ucp->uc_sigmask, sizeof (ucp->uc_sigmask));
+        }
 
         if (!need_xsave || !fpu_en) {
                 return (0);
         }
 

@@ -505,10 +556,20 @@
                 ret = fpu_signal_copyout(lwp, uaddr, savecontext_copyout);
         } else {
                 ret = fpu_signal_copyout(lwp, uaddr, copyout);
         }
 
+
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_savecontext32 != NULL) {
+                /*
+                 * Allow the brand the chance to modify the context we
+                 * saved:
+                 */
+                /* XXX KEBE SAYS FIX ME */
+                BROP(p)->b_savecontext32(ucp);
+        }
+
         return (ret);
 }
 
 int
 getsetcontext32(int flag, void *arg)

@@ -517,10 +578,11 @@
         ucontext_t ucnat;
         ucontext32_t *ucp;
         klwp_t *lwp = ttolwp(curthread);
         caddr32_t ustack32;
         stack32_t dummy_stk32;
+        proc_t *p = lwptoproc(lwp);
         int ret;
 
         switch (flag) {
         default:
                 return (set_errno(EINVAL));

@@ -557,11 +619,11 @@
 
         case SETCONTEXT:
                 ucp = arg;
                 if (ucp == NULL)
                         exit(CLD_EXITED, 0);
-                if (copyin(ucp, &uc, offsetof(ucontext32_t, uc_filler) -
+                if (copyin(ucp, &uc, offsetof(ucontext32_t, uc_brand_data) -
                     sizeof (uc.uc_mcontext.fpregs))) {
                         return (set_errno(EFAULT));
                 }
                 if (uc.uc_flags & UC_SIGMASK)
                         SIGSET_BRAND_TO_NATIVE(&uc.uc_sigmask);

@@ -568,10 +630,19 @@
                 if ((uc.uc_flags & UC_FPU) &&
                     copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
                     sizeof (uc.uc_mcontext.fpregs))) {
                         return (set_errno(EFAULT));
                 }
+
+                /*
+                 * If this is a branded process, copy in the brand-private
+                 * data:
+                 */
+                if (PROC_IS_BRANDED(p) && copyin(&ucp->uc_brand_data,
+                    &uc.uc_brand_data, sizeof (uc.uc_brand_data)) != 0) {
+                        return (set_errno(EFAULT));
+                }
 
                 uc.uc_xsave = 0;
                 if ((uc.uc_flags & UC_XSAVE) != 0 &&
                     copyin(&ucp->uc_xsave, &uc.uc_xsave,
                     sizeof (uc.uc_xsave)) != 0) {