1371
1372 /*
1373 * Not all threads may have an active LWP. If they do and we're not
1374 * going to re-use the LWP, then we should go ahead and save the state.
1375 * We must also note that the fpu is now being used by the kernel and
1376 * therefore we do not want to manage the fpu state via the user-level
1377 * thread's context handlers.
1378 *
1379 * We might have already saved once (due to a prior use of the kernel
1380 * FPU or another code path) so FPU_VALID could be set. This is handled
1381 * by fp_save, as is the FPU_EN check.
1382 */
1383 if (pl != NULL) {
1384 kpreempt_disable();
1385 if ((flags & KFPU_USE_LWP) == 0)
1386 fp_save(&pl->lwp_pcb.pcb_fpu);
1387 pl->lwp_pcb.pcb_fpu.fpu_flags |= FPU_KERNEL;
1388 kpreempt_enable();
1389 }
1390
1391 /*
1392 * Set the context operations for kernel FPU usage. Note that this
1393 * cannot be done with pre-emption and interrupts disabled, since
1394 * installctx does a sleeping allocation. We haven't finished
1395 * initializing our kernel FPU state yet, but in the rare case that we
1396 * happen to save/restore before that, no harm is done.
1397 */
1398 installctx(curthread, kfpu, kernel_fpu_ctx_save, kernel_fpu_ctx_restore,
1399 NULL, NULL, NULL, NULL);
1400
1401 curthread->t_flag |= T_KFPU;
1402
1403 if ((flags & KFPU_USE_LWP) == KFPU_USE_LWP) {
1404 /*
1405 * For pure kernel threads with an LWP, we can use the LWP's
1406 * pcb_fpu to save/restore context.
1407 */
1408 fpu_ctx_t *pf = &pl->lwp_pcb.pcb_fpu;
1409
1410 VERIFY(curthread->t_procp->p_flag & SSYS);
1411 VERIFY(kfpu == NULL);
1412 ASSERT((pf->fpu_flags & FPU_EN) == 0);
1413
1414 /* Always restore the fpu to the initial state. */
1415 if (fp_save_mech == FP_XSAVE)
1416 pf->fpu_xsave_mask = XFEATURE_FP_ALL;
1417 fpinit();
1418 pf->fpu_flags = FPU_EN | FPU_KERNEL;
1419 } else {
1420 /* initialize the kfpu state */
1421 kernel_fpu_ctx_restore(kfpu);
1422 }
1423 }
1424
1425 void
1426 kernel_fpu_end(kfpu_state_t *kfpu, uint_t flags)
1427 {
1428 ulong_t iflags;
1429
1430 if ((curthread->t_flag & T_KFPU) == 0) {
1431 panic("curthread attempting to clear kernel FPU state "
1432 "without using it");
1433 }
1434
1435 /*
1436 * General comments on why the rest of this function is structured the
1437 * way it is. Be aware that there is a lot of subtlety here.
1438 *
1439 * If a user-level thread ever uses the fpu while in the kernel, then
1440 * we cannot call fpdisable since that does STTS. That will set the
1441 * ts bit in %cr0 which will cause an exception if anything touches the
1442 * fpu. However, the user-level context switch handler (fpsave_ctxt)
|
1371
1372 /*
1373 * Not all threads may have an active LWP. If they do and we're not
1374 * going to re-use the LWP, then we should go ahead and save the state.
1375 * We must also note that the fpu is now being used by the kernel and
1376 * therefore we do not want to manage the fpu state via the user-level
1377 * thread's context handlers.
1378 *
1379 * We might have already saved once (due to a prior use of the kernel
1380 * FPU or another code path) so FPU_VALID could be set. This is handled
1381 * by fp_save, as is the FPU_EN check.
1382 */
1383 if (pl != NULL) {
1384 kpreempt_disable();
1385 if ((flags & KFPU_USE_LWP) == 0)
1386 fp_save(&pl->lwp_pcb.pcb_fpu);
1387 pl->lwp_pcb.pcb_fpu.fpu_flags |= FPU_KERNEL;
1388 kpreempt_enable();
1389 }
1390
1391 curthread->t_flag |= T_KFPU;
1392
1393 if ((flags & KFPU_USE_LWP) == KFPU_USE_LWP) {
1394 /*
1395 * For pure kernel threads with an LWP, we can use the LWP's
1396 * pcb_fpu to save/restore context.
1397 */
1398 fpu_ctx_t *pf = &pl->lwp_pcb.pcb_fpu;
1399
1400 VERIFY(curthread->t_procp->p_flag & SSYS);
1401 VERIFY(kfpu == NULL);
1402 ASSERT((pf->fpu_flags & FPU_EN) == 0);
1403
1404 /* Always restore the fpu to the initial state. */
1405 if (fp_save_mech == FP_XSAVE)
1406 pf->fpu_xsave_mask = XFEATURE_FP_ALL;
1407 fpinit();
1408 pf->fpu_flags = FPU_EN | FPU_KERNEL;
1409 } else {
1410 /* initialize the kfpu state */
1411 kernel_fpu_ctx_restore(kfpu);
1412 }
1413
1414 /*
1415 * Set the context operations for kernel FPU usage. Note that this
1416 * cannot be done with pre-emption and interrupts disabled, since
1417 * installctx does a sleeping allocation. We haven't finished
1418 * initializing our kernel FPU state yet, but in the rare case that we
1419 * happen to save/restore before that, no harm is done.
1420 */
1421 installctx(curthread, kfpu, kernel_fpu_ctx_save, kernel_fpu_ctx_restore,
1422 NULL, NULL, NULL, NULL);
1423 }
1424
1425 void
1426 kernel_fpu_end(kfpu_state_t *kfpu, uint_t flags)
1427 {
1428 ulong_t iflags;
1429
1430 if ((curthread->t_flag & T_KFPU) == 0) {
1431 panic("curthread attempting to clear kernel FPU state "
1432 "without using it");
1433 }
1434
1435 /*
1436 * General comments on why the rest of this function is structured the
1437 * way it is. Be aware that there is a lot of subtlety here.
1438 *
1439 * If a user-level thread ever uses the fpu while in the kernel, then
1440 * we cannot call fpdisable since that does STTS. That will set the
1441 * ts bit in %cr0 which will cause an exception if anything touches the
1442 * fpu. However, the user-level context switch handler (fpsave_ctxt)
|