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,28 ****
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
! * Copyright 2020 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 */
--- 18,28 ----
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
! * 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,678 ****
* 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);
}
/*
* Free any state associated with floating point context.
* Fp_free can be called in three cases:
--- 668,678 ----
* 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, NULL);
}
/*
* Free any state associated with floating point context.
* Fp_free can be called in three cases:
*** 794,803 ****
--- 794,804 ----
*/
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,815 ****
* 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);
fpinit();
fp->fpu_flags = FPU_EN;
kpreempt_enable();
}
--- 806,816 ----
* 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, ctx);
fpinit();
fp->fpu_flags = FPU_EN;
kpreempt_enable();
}
*** 834,844 ****
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);
fpinit();
/*
* If FPU_VALID is set, it means someone has modified registers via
* /proc. In this case, restore the current lwp's state.
--- 835,845 ----
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, 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,1325 ****
--- 1317,1327 ----
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,1404 ****
*
* 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) {
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.
*/
installctx(curthread, kfpu, kernel_fpu_ctx_save, kernel_fpu_ctx_restore,
! NULL, NULL, NULL, NULL);
curthread->t_flag |= T_KFPU;
if ((flags & KFPU_USE_LWP) == KFPU_USE_LWP) {
/*
--- 1380,1408 ----
*
* 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.
*/
! 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;
}
/*
! * 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, ctx);
curthread->t_flag |= T_KFPU;
if ((flags & KFPU_USE_LWP) == KFPU_USE_LWP) {
/*
*** 1418,1427 ****
--- 1422,1432 ----
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)
{