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) {