summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_misc.c4
-rw-r--r--usr/src/uts/common/disp/thread.c30
-rw-r--r--usr/src/uts/common/fs/zfs/spa_misc.c3
-rw-r--r--usr/src/uts/common/os/kcpc.c5
-rw-r--r--usr/src/uts/common/os/schedctl.c4
-rw-r--r--usr/src/uts/common/sys/proc.h5
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm.c2
-rw-r--r--usr/src/uts/intel/ia32/os/cpc_subr.c4
-rw-r--r--usr/src/uts/intel/ia32/os/fpu.c29
-rw-r--r--usr/src/uts/intel/ia32/os/sundep.c21
-rw-r--r--usr/src/uts/intel/ia32/os/sysi86.c16
-rw-r--r--usr/src/uts/sun4u/os/cpc_subr.c3
-rw-r--r--usr/src/uts/sun4v/os/cpc_subr.c3
13 files changed, 87 insertions, 42 deletions
diff --git a/usr/src/uts/common/brand/lx/os/lx_misc.c b/usr/src/uts/common/brand/lx/os/lx_misc.c
index 726c3c7915..8d48d2ea59 100644
--- a/usr/src/uts/common/brand/lx/os/lx_misc.c
+++ b/usr/src/uts/common/brand/lx/os/lx_misc.c
@@ -121,7 +121,7 @@ lx_exec()
lwpd->br_ntv_stack_current = 0;
installctx(lwptot(lwp), lwp, lx_save, lx_restore, NULL, NULL, lx_save,
- NULL);
+ NULL, NULL);
/*
* clear out the tls array
@@ -499,7 +499,7 @@ lx_initlwp(klwp_t *lwp, void *lwpbd)
lwpd->br_lpid = NULL;
installctx(lwptot(lwp), lwp, lx_save, lx_restore, NULL, NULL,
- lx_save, NULL);
+ lx_save, NULL, NULL);
/*
* Install branded system call hooks for this LWP:
diff --git a/usr/src/uts/common/disp/thread.c b/usr/src/uts/common/disp/thread.c
index bf1f121b67..c9e0216dbe 100644
--- a/usr/src/uts/common/disp/thread.c
+++ b/usr/src/uts/common/disp/thread.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2019 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
*/
#include <sys/types.h>
@@ -1025,7 +1025,28 @@ reapq_add(kthread_t *t)
}
/*
+ * Provide an allocation function for callers of installctx() that, for
+ * reasons of incomplete context-op initialization, must call installctx()
+ * in a kpreempt_disable() block. The caller, therefore, must call this
+ * without being in such a block.
+ */
+struct ctxop *
+installctx_preallocate(void)
+{
+ /*
+ * NOTE: We could ASSERT/VERIFY that we are not in a place where
+ * a KM_SLEEP allocation could block indefinitely.
+ *
+ * ASSERT(curthread->t_preempt == 0);
+ */
+
+ return (kmem_alloc(sizeof (struct ctxop), KM_SLEEP));
+}
+
+/*
* Install thread context ops for the current thread.
+ * The caller can pass in a preallocated struct ctxop, eliminating the need
+ * for the requirement of entering with kernel preemption still enabled.
*/
void
installctx(
@@ -1036,11 +1057,12 @@ installctx(
void (*fork)(void *, void *),
void (*lwp_create)(void *, void *),
void (*exit)(void *),
- void (*free)(void *, int))
+ void (*free)(void *, int),
+ struct ctxop *ctx)
{
- struct ctxop *ctx;
+ if (ctx == NULL)
+ ctx = kmem_alloc(sizeof (struct ctxop), KM_SLEEP);
- ctx = kmem_alloc(sizeof (struct ctxop), KM_SLEEP);
ctx->save_op = save;
ctx->restore_op = restore;
ctx->fork_op = fork;
diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c
index dd44829a43..af87d4611c 100644
--- a/usr/src/uts/common/fs/zfs/spa_misc.c
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c
@@ -322,7 +322,8 @@ int zfs_deadman_enabled = -1;
* the FPU state? This is currently off by default due to stability issues in
* the kernel FPU routines; e.g., see bug 13717.
*/
-int zfs_fpu_enabled = 0;
+/* XXX SmartOS now includes fixes for 13902 and 13915, so re-enable it. */
+int zfs_fpu_enabled = 1;
#endif
/*
diff --git a/usr/src/uts/common/os/kcpc.c b/usr/src/uts/common/os/kcpc.c
index 977d243400..33486aaff3 100644
--- a/usr/src/uts/common/os/kcpc.c
+++ b/usr/src/uts/common/os/kcpc.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2021 Joyent, Inc.
*/
#include <sys/param.h>
@@ -318,7 +319,7 @@ kcpc_bind_thread(kcpc_set_t *set, kthread_t *t, int *subcode)
* Add a device context to the subject thread.
*/
installctx(t, ctx, kcpc_save, kcpc_restore, NULL,
- kcpc_lwp_create, NULL, kcpc_free);
+ kcpc_lwp_create, NULL, kcpc_free, NULL);
/*
* Ask the backend to program the hardware.
@@ -1424,7 +1425,7 @@ kcpc_lwp_create(kthread_t *t, kthread_t *ct)
}
installctx(ct, cctx, kcpc_save, kcpc_restore,
- NULL, kcpc_lwp_create, NULL, kcpc_free);
+ NULL, kcpc_lwp_create, NULL, kcpc_free, NULL);
}
/*
diff --git a/usr/src/uts/common/os/schedctl.c b/usr/src/uts/common/os/schedctl.c
index 18b396a765..34f72995a2 100644
--- a/usr/src/uts/common/os/schedctl.c
+++ b/usr/src/uts/common/os/schedctl.c
@@ -22,7 +22,7 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
*/
#include <sys/types.h>
@@ -113,7 +113,7 @@ schedctl(void)
bzero(ssp, sizeof (*ssp));
installctx(t, ssp, schedctl_save, schedctl_restore,
- schedctl_fork, NULL, NULL, NULL);
+ schedctl_fork, NULL, NULL, NULL, NULL);
thread_lock(t); /* protect against ts_tick and ts_update */
t->t_schedctl = ssp;
diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h
index bb6f62f83f..90007bda1b 100644
--- a/usr/src/uts/common/sys/proc.h
+++ b/usr/src/uts/common/sys/proc.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2018 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
* Copyright 2020 Oxide Computer Company
*/
@@ -720,8 +720,9 @@ extern void thread_free(kthread_t *);
extern void thread_rele(kthread_t *);
extern void thread_join(kt_did_t);
extern int reaper(void);
+extern struct ctxop *installctx_preallocate(void);
extern void installctx(kthread_t *, void *, void (*)(), void (*)(),
- void (*)(), void (*)(), void (*)(), void (*)());
+ void (*)(), void (*)(), void (*)(), void (*)(), struct ctxop *);
extern int removectx(kthread_t *, void *, void (*)(), void (*)(),
void (*)(), void (*)(), void (*)(), void (*)());
extern void savectx(kthread_t *);
diff --git a/usr/src/uts/i86pc/io/vmm/vmm.c b/usr/src/uts/i86pc/io/vmm/vmm.c
index fd37a2a171..c15a1118d8 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm.c
@@ -2223,7 +2223,7 @@ vm_run(struct vm *vm, int vcpuid, const struct vm_entry *entry)
vtc.vtc_vcpuid = vcpuid;
vtc.vtc_status = 0;
installctx(curthread, &vtc, vmm_savectx, vmm_restorectx, NULL, NULL,
- NULL, vmm_freectx);
+ NULL, vmm_freectx, NULL);
error = vm_entry_actions(vm, vcpuid, entry, vme);
if (error != 0) {
diff --git a/usr/src/uts/intel/ia32/os/cpc_subr.c b/usr/src/uts/intel/ia32/os/cpc_subr.c
index a74dfd77bc..71e1ebaeee 100644
--- a/usr/src/uts/intel/ia32/os/cpc_subr.c
+++ b/usr/src/uts/intel/ia32/os/cpc_subr.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2019 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
*/
/*
@@ -169,7 +169,7 @@ kcpc_hw_init(cpu_t *cp)
return;
installctx(t, cp, kcpc_idle_save, kcpc_idle_restore,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
}
void
diff --git a/usr/src/uts/intel/ia32/os/fpu.c b/usr/src/uts/intel/ia32/os/fpu.c
index d648e0552f..9a02806b66 100644
--- a/usr/src/uts/intel/ia32/os/fpu.c
+++ b/usr/src/uts/intel/ia32/os/fpu.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2020 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
* Copyright 2021 RackTop Systems, Inc.
*/
@@ -670,7 +670,7 @@ fp_new_lwp(kthread_id_t t, kthread_id_t ct)
*/
installctx(ct, cfp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
- fp_new_lwp, NULL, fp_free);
+ fp_new_lwp, NULL, fp_free, NULL);
}
/*
@@ -796,6 +796,7 @@ void
fp_exec(void)
{
struct fpu_ctx *fp = &ttolwp(curthread)->lwp_pcb.pcb_fpu;
+ struct ctxop *ctx = installctx_preallocate();
if (fp_save_mech == FP_XSAVE) {
fp->fpu_xsave_mask = XFEATURE_FP_ALL;
@@ -807,7 +808,7 @@ fp_exec(void)
*/
kpreempt_disable();
installctx(curthread, fp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
- fp_new_lwp, NULL, fp_free);
+ fp_new_lwp, NULL, fp_free, ctx);
fpinit();
fp->fpu_flags = FPU_EN;
kpreempt_enable();
@@ -836,7 +837,7 @@ fp_seed(void)
}
installctx(curthread, fp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
- fp_new_lwp, NULL, fp_free);
+ fp_new_lwp, NULL, fp_free, NULL);
fpinit();
/*
@@ -1318,6 +1319,7 @@ void
kernel_fpu_begin(kfpu_state_t *kfpu, uint_t flags)
{
klwp_t *pl = curthread->t_lwp;
+ struct ctxop *ctx;
if ((curthread->t_flag & T_KFPU) != 0) {
panic("curthread attempting to nest kernel FPU states");
@@ -1380,23 +1382,25 @@ kernel_fpu_begin(kfpu_state_t *kfpu, uint_t flags)
* FPU or another code path) so FPU_VALID could be set. This is handled
* by fp_save, as is the FPU_EN check.
*/
+ ctx = installctx_preallocate();
+ kpreempt_disable();
if (pl != NULL) {
- kpreempt_disable();
if ((flags & KFPU_USE_LWP) == 0)
fp_save(&pl->lwp_pcb.pcb_fpu);
pl->lwp_pcb.pcb_fpu.fpu_flags |= FPU_KERNEL;
- kpreempt_enable();
}
/*
- * Set the context operations for kernel FPU usage. Note that this
- * cannot be done with pre-emption and interrupts disabled, since
- * installctx does a sleeping allocation. We haven't finished
- * initializing our kernel FPU state yet, but in the rare case that we
- * happen to save/restore before that, no harm is done.
+ * Set the context operations for kernel FPU usage. Note that this is
+ * done with a preallocated buffer and under kpreempt_disable because
+ * without a preallocated buffer, installctx does a sleeping
+ * allocation. We haven't finished initializing our kernel FPU state
+ * yet, and in the rare case that we happen to save/restore just as
+ * installctx() exits its own kpreempt_enable() internal call, we
+ * guard against restoring an uninitialized buffer (0xbaddcafe).
*/
installctx(curthread, kfpu, kernel_fpu_ctx_save, kernel_fpu_ctx_restore,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, ctx);
curthread->t_flag |= T_KFPU;
@@ -1420,6 +1424,7 @@ kernel_fpu_begin(kfpu_state_t *kfpu, uint_t flags)
/* initialize the kfpu state */
kernel_fpu_ctx_restore(kfpu);
}
+ kpreempt_enable();
}
void
diff --git a/usr/src/uts/intel/ia32/os/sundep.c b/usr/src/uts/intel/ia32/os/sundep.c
index 34e0a03d68..8a5562f4ad 100644
--- a/usr/src/uts/intel/ia32/os/sundep.c
+++ b/usr/src/uts/intel/ia32/os/sundep.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2019 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
@@ -763,7 +763,7 @@ lwp_attach_brand_hdlrs(klwp_t *lwp)
brand_interpositioning_disable, NULL) == 0);
installctx(t, NULL, brand_interpositioning_disable,
brand_interpositioning_enable, NULL, NULL,
- brand_interpositioning_disable, NULL);
+ brand_interpositioning_disable, NULL, NULL);
if (t == curthread) {
kpreempt_disable();
@@ -829,6 +829,7 @@ lwp_installctx(klwp_t *lwp)
#else
void (*restop)(klwp_t *) = lwp_segregs_restore;
#endif
+ struct ctxop *ctx;
/*
* Install the basic lwp context handlers on each lwp.
@@ -844,10 +845,14 @@ lwp_installctx(klwp_t *lwp)
*/
ASSERT(removectx(t, lwp, lwp_segregs_save, restop,
NULL, NULL, NULL, NULL) == 0);
- if (thisthread)
+ if (thisthread) {
+ ctx = installctx_preallocate();
kpreempt_disable();
+ } else {
+ ctx = NULL;
+ }
installctx(t, lwp, lwp_segregs_save, restop,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, ctx);
if (thisthread) {
/*
* Since we're the right thread, set the values in the GDT
@@ -874,10 +879,14 @@ lwp_installctx(klwp_t *lwp)
ASSERT(removectx(t, kstktop,
sep_save, sep_restore, NULL, NULL, NULL, NULL) == 0);
- if (thisthread)
+ if (thisthread) {
+ ctx = installctx_preallocate();
kpreempt_disable();
+ } else {
+ ctx = NULL;
+ }
installctx(t, kstktop,
- sep_save, sep_restore, NULL, NULL, NULL, NULL);
+ sep_save, sep_restore, NULL, NULL, NULL, NULL, ctx);
if (thisthread) {
/*
* We're the right thread, so set the stack pointer
diff --git a/usr/src/uts/intel/ia32/os/sysi86.c b/usr/src/uts/intel/ia32/os/sysi86.c
index bdb66e3e1f..03796bc9e9 100644
--- a/usr/src/uts/intel/ia32/os/sysi86.c
+++ b/usr/src/uts/intel/ia32/os/sysi86.c
@@ -20,12 +20,12 @@
*/
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2018 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
-/* All Rights Reserved */
+/* All Rights Reserved */
/* Copyright (c) 1987, 1988 Microsoft Corporation */
/* All Rights Reserved */
@@ -93,6 +93,9 @@ sysi86(short cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
*/
case SI86V86:
if (arg1 == V86SC_IOPL) {
+#if defined(__xpv)
+ struct ctxop *ctx;
+#endif
struct regs *rp = lwptoregs(ttolwp(curthread));
greg_t oldpl = rp->r_ps & PS_IOPL;
greg_t newpl = arg2 & PS_IOPL;
@@ -105,10 +108,11 @@ sysi86(short cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
secpolicy_sys_config(CRED(), B_FALSE)) != 0)
return (set_errno(error));
#if defined(__xpv)
+ ctx = installctx_preallocate();
kpreempt_disable();
installctx(curthread, NULL, xen_disable_user_iopl,
xen_enable_user_iopl, NULL, NULL,
- xen_disable_user_iopl, NULL);
+ xen_disable_user_iopl, NULL, ctx);
xen_enable_user_iopl();
kpreempt_enable();
#else
@@ -398,14 +402,14 @@ ldt_savectx(proc_t *p)
* selectors when context switching away from a process that
* has a private ldt. Consider the following example:
*
- * Wine creats a ldt descriptor and points a segment register
- * to it.
+ * Wine creats a ldt descriptor and points a segment register
+ * to it.
*
* We then context switch away from wine lwp to kernel
* thread and hit breakpoint in kernel with kmdb
*
* When we continue and resume from kmdb we will #gp
- * fault since kmdb will have saved the stale ldt selector
+ * fault since kmdb will have saved the stale ldt selector
* from wine and will try to restore it but we are no longer in
* the context of the wine process and do not have our
* ldtr register pointing to the private ldt.
diff --git a/usr/src/uts/sun4u/os/cpc_subr.c b/usr/src/uts/sun4u/os/cpc_subr.c
index 5d4b6862d8..5efa580e71 100644
--- a/usr/src/uts/sun4u/os/cpc_subr.c
+++ b/usr/src/uts/sun4u/os/cpc_subr.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2021 Joyent, Inc.
*/
/*
@@ -95,7 +96,7 @@ kcpc_hw_startup_cpu(ushort_t cpflags)
return;
installctx(t, cp, kcpc_idle_save, kcpc_idle_restore, NULL, NULL,
- NULL, NULL);
+ NULL, NULL, NULL);
}
/*
diff --git a/usr/src/uts/sun4v/os/cpc_subr.c b/usr/src/uts/sun4v/os/cpc_subr.c
index f545120f64..558549e9b3 100644
--- a/usr/src/uts/sun4v/os/cpc_subr.c
+++ b/usr/src/uts/sun4v/os/cpc_subr.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2021 Joyent, Inc.
*/
/*
@@ -94,7 +95,7 @@ kcpc_hw_startup_cpu(ushort_t cpflags)
return;
installctx(t, cp, kcpc_idle_save, kcpc_idle_restore, NULL, NULL,
- NULL, NULL);
+ NULL, NULL, NULL);
}
/*