1364 "another thread already is using", kfpu);
1365
1366 if ((kfpu->kfpu_flags & KFPU_F_INITIALIZED) == 0)
1367 kernel_fpu_fpstate_init(kfpu);
1368
1369 kfpu->kfpu_curthread = curthread;
1370 }
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
|
1364 "another thread already is using", kfpu);
1365
1366 if ((kfpu->kfpu_flags & KFPU_F_INITIALIZED) == 0)
1367 kernel_fpu_fpstate_init(kfpu);
1368
1369 kfpu->kfpu_curthread = curthread;
1370 }
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 fpu_ctx_t *pf = &pl->lwp_pcb.pcb_fpu;
1385
1386 kpreempt_disable();
1387 if ((flags & KFPU_USE_LWP) == 0) {
1388 fp_save(pf);
1389 } else {
1390 /*
1391 * For pure kernel threads with an LWP, we can use the
1392 * LWP's pcb_fpu to save/restore context.
1393 */
1394 VERIFY(curthread->t_procp->p_flag & SSYS);
1395 VERIFY(kfpu == NULL);
1396 ASSERT((pf->fpu_flags & FPU_EN) == 0);
1397
1398 /* Always restore the fpu to the initial state. */
1399 if (fp_save_mech == FP_XSAVE)
1400 pf->fpu_xsave_mask = XFEATURE_FP_ALL;
1401 fpinit();
1402 pf->fpu_flags = FPU_EN;
1403 }
1404 pf->fpu_flags |= FPU_KERNEL;
1405 kpreempt_enable();
1406 }
1407
1408 /*
1409 * Set the context operations for kernel FPU usage. Note that this
1410 * cannot be done with pre-emption and interrupts disabled, since
1411 * installctx does a sleeping allocation. We haven't finished
1412 * initializing our kernel FPU state yet, but in the rare case that we
1413 * happen to save/restore before that, no harm is done.
1414 */
1415 installctx(curthread, kfpu, kernel_fpu_ctx_save, kernel_fpu_ctx_restore,
1416 NULL, NULL, NULL, NULL);
1417
1418 curthread->t_flag |= T_KFPU;
1419
1420 if ((flags & KFPU_USE_LWP) == 0) {
1421 /* initialize the kfpu state */
1422 kernel_fpu_ctx_restore(kfpu);
1423 }
1424 }
1425
1426 void
1427 kernel_fpu_end(kfpu_state_t *kfpu, uint_t flags)
1428 {
1429 ulong_t iflags;
1430
1431 if ((curthread->t_flag & T_KFPU) == 0) {
1432 panic("curthread attempting to clear kernel FPU state "
1433 "without using it");
1434 }
1435
1436 /*
1437 * General comments on why the rest of this function is structured the
1438 * way it is. Be aware that there is a lot of subtlety here.
1439 *
1440 * If a user-level thread ever uses the fpu while in the kernel, then
|