Print this page
13902 Fix for 13717 may break 8-disk raidz2
13915 installctx() blocking allocate causes problems
Portions contributed by: Jerry Jelinek <gjelinek@gmail.com>
Change-Id: I934d69946cec42630fc541fa8c7385b862b69ca2
@@ -18,11 +18,11 @@
*
* CDDL HEADER END
*/
/*
* 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.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
@@ -668,11 +668,11 @@
* Mark that both the parent and child need to have the FPU cleaned up
* before returning to user land.
*/
installctx(ct, cfp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
- fp_new_lwp, NULL, fp_free);
+ fp_new_lwp, NULL, fp_free, NULL);
}
/*
* Free any state associated with floating point context.
* Fp_free can be called in three cases:
@@ -794,10 +794,11 @@
*/
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;
}
@@ -805,11 +806,11 @@
* Make sure that we're not preempted in the middle of initializing the
* FPU on CPU.
*/
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();
}
@@ -834,11 +835,11 @@
if (fp_save_mech == FP_XSAVE) {
fp->fpu_xsave_mask = XFEATURE_FP_ALL;
}
installctx(curthread, fp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
- fp_new_lwp, NULL, fp_free);
+ fp_new_lwp, NULL, fp_free, NULL);
fpinit();
/*
* If FPU_VALID is set, it means someone has modified registers via
* /proc. In this case, restore the current lwp's state.
@@ -1316,10 +1317,11 @@
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");
}
@@ -1378,27 +1380,29 @@
*
* We might have already saved once (due to a prior use of the kernel
* FPU or another code path) so FPU_VALID could be set. This is handled
* by fp_save, as is the FPU_EN check.
*/
- if (pl != NULL) {
+ ctx = installctx_preallocate();
kpreempt_disable();
+ if (pl != NULL) {
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;
if ((flags & KFPU_USE_LWP) == KFPU_USE_LWP) {
/*
@@ -1418,10 +1422,11 @@
pf->fpu_flags = FPU_EN | FPU_KERNEL;
} else {
/* initialize the kfpu state */
kernel_fpu_ctx_restore(kfpu);
}
+ kpreempt_enable();
}
void
kernel_fpu_end(kfpu_state_t *kfpu, uint_t flags)
{