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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/intel/ia32/os/fpu.c
          +++ new/usr/src/uts/intel/ia32/os/fpu.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2020 Joyent, Inc.
       23 + * Copyright 2021 Joyent, Inc.
  24   24   * Copyright 2021 RackTop Systems, Inc.
  25   25   */
  26   26  
  27   27  /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
  28   28  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
  29   29  /*              All Rights Reserved                             */
  30   30  
  31   31  /*      Copyright (c) 1987, 1988 Microsoft Corporation          */
  32   32  /*              All Rights Reserved                             */
  33   33  
↓ open down ↓ 629 lines elided ↑ open up ↑
 663  663                  panic("Invalid fp_save_mech");
 664  664                  /*NOTREACHED*/
 665  665          }
 666  666  
 667  667          /*
 668  668           * Mark that both the parent and child need to have the FPU cleaned up
 669  669           * before returning to user land.
 670  670           */
 671  671  
 672  672          installctx(ct, cfp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
 673      -            fp_new_lwp, NULL, fp_free);
      673 +            fp_new_lwp, NULL, fp_free, NULL);
 674  674  }
 675  675  
 676  676  /*
 677  677   * Free any state associated with floating point context.
 678  678   * Fp_free can be called in three cases:
 679  679   * 1) from reaper -> thread_free -> freectx-> fp_free
 680  680   *      fp context belongs to a thread on deathrow
 681  681   *      nothing to do,  thread will never be resumed
 682  682   *      thread calling ctxfree is reaper
 683  683   *
↓ open down ↓ 105 lines elided ↑ open up ↑
 789  789  /*
 790  790   * Reset the FPU such that it is in a valid state for a new thread that is
 791  791   * coming out of exec. The FPU will be in a usable state at this point. At this
 792  792   * point we know that the FPU state has already been allocated and if this
 793  793   * wasn't an init process, then it will have had fp_free() previously called.
 794  794   */
 795  795  void
 796  796  fp_exec(void)
 797  797  {
 798  798          struct fpu_ctx *fp = &ttolwp(curthread)->lwp_pcb.pcb_fpu;
      799 +        struct ctxop *ctx = installctx_preallocate();
 799  800  
 800  801          if (fp_save_mech == FP_XSAVE) {
 801  802                  fp->fpu_xsave_mask = XFEATURE_FP_ALL;
 802  803          }
 803  804  
 804  805          /*
 805  806           * Make sure that we're not preempted in the middle of initializing the
 806  807           * FPU on CPU.
 807  808           */
 808  809          kpreempt_disable();
 809  810          installctx(curthread, fp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
 810      -            fp_new_lwp, NULL, fp_free);
      811 +            fp_new_lwp, NULL, fp_free, ctx);
 811  812          fpinit();
 812  813          fp->fpu_flags = FPU_EN;
 813  814          kpreempt_enable();
 814  815  }
 815  816  
 816  817  
 817  818  /*
 818  819   * Seeds the initial state for the current thread.  The possibilities are:
 819  820   *      1. Another process has modified the FPU state before we have done any
 820  821   *         initialization: Load the FPU state from the LWP state.
↓ open down ↓ 8 lines elided ↑ open up ↑
 829  830          ASSERT((fp->fpu_flags & FPU_EN) == 0);
 830  831  
 831  832          /*
 832  833           * Always initialize a new context and initialize the hardware.
 833  834           */
 834  835          if (fp_save_mech == FP_XSAVE) {
 835  836                  fp->fpu_xsave_mask = XFEATURE_FP_ALL;
 836  837          }
 837  838  
 838  839          installctx(curthread, fp, fpsave_ctxt, fprestore_ctxt, fp_new_lwp,
 839      -            fp_new_lwp, NULL, fp_free);
      840 +            fp_new_lwp, NULL, fp_free, NULL);
 840  841          fpinit();
 841  842  
 842  843          /*
 843  844           * If FPU_VALID is set, it means someone has modified registers via
 844  845           * /proc.  In this case, restore the current lwp's state.
 845  846           */
 846  847          if (fp->fpu_flags & FPU_VALID)
 847  848                  fp_restore(fp);
 848  849  
 849  850          ASSERT((fp->fpu_flags & FPU_VALID) == 0);
↓ open down ↓ 461 lines elided ↑ open up ↑
1311 1312  {
1312 1313          if ((curthread->t_flag & T_KFPU) != 0) {
1313 1314                  panic("curthread swtch-ing while the kernel is using the FPU");
1314 1315          }
1315 1316  }
1316 1317  
1317 1318  void
1318 1319  kernel_fpu_begin(kfpu_state_t *kfpu, uint_t flags)
1319 1320  {
1320 1321          klwp_t *pl = curthread->t_lwp;
     1322 +        struct ctxop *ctx;
1321 1323  
1322 1324          if ((curthread->t_flag & T_KFPU) != 0) {
1323 1325                  panic("curthread attempting to nest kernel FPU states");
1324 1326          }
1325 1327  
1326 1328          /* KFPU_USE_LWP and KFPU_NO_STATE are mutually exclusive. */
1327 1329          ASSERT((flags & (KFPU_USE_LWP | KFPU_NO_STATE)) !=
1328 1330              (KFPU_USE_LWP | KFPU_NO_STATE));
1329 1331  
1330 1332          if ((flags & KFPU_NO_STATE) == KFPU_NO_STATE) {
↓ open down ↓ 42 lines elided ↑ open up ↑
1373 1375           * Not all threads may have an active LWP. If they do and we're not
1374 1376           * going to re-use the LWP, then we should go ahead and save the state.
1375 1377           * We must also note that the fpu is now being used by the kernel and
1376 1378           * therefore we do not want to manage the fpu state via the user-level
1377 1379           * thread's context handlers.
1378 1380           *
1379 1381           * We might have already saved once (due to a prior use of the kernel
1380 1382           * FPU or another code path) so FPU_VALID could be set. This is handled
1381 1383           * by fp_save, as is the FPU_EN check.
1382 1384           */
     1385 +        ctx = installctx_preallocate();
     1386 +        kpreempt_disable();
1383 1387          if (pl != NULL) {
1384      -                kpreempt_disable();
1385 1388                  if ((flags & KFPU_USE_LWP) == 0)
1386 1389                          fp_save(&pl->lwp_pcb.pcb_fpu);
1387 1390                  pl->lwp_pcb.pcb_fpu.fpu_flags |= FPU_KERNEL;
1388      -                kpreempt_enable();
1389 1391          }
1390 1392  
1391 1393          /*
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.
     1394 +         * Set the context operations for kernel FPU usage. Note that this is
     1395 +         * done with a preallocated buffer and under kpreempt_disable because
     1396 +         * without a preallocated buffer, installctx does a sleeping
     1397 +         * allocation. We haven't finished initializing our kernel FPU state
     1398 +         * yet, and in the rare case that we happen to save/restore just as
     1399 +         * installctx() exits its own kpreempt_enable() internal call, we
     1400 +         * guard against restoring an uninitialized buffer (0xbaddcafe).
1397 1401           */
1398 1402          installctx(curthread, kfpu, kernel_fpu_ctx_save, kernel_fpu_ctx_restore,
1399      -            NULL, NULL, NULL, NULL);
     1403 +            NULL, NULL, NULL, NULL, ctx);
1400 1404  
1401 1405          curthread->t_flag |= T_KFPU;
1402 1406  
1403 1407          if ((flags & KFPU_USE_LWP) == KFPU_USE_LWP) {
1404 1408                  /*
1405 1409                   * For pure kernel threads with an LWP, we can use the LWP's
1406 1410                   * pcb_fpu to save/restore context.
1407 1411                   */
1408 1412                  fpu_ctx_t *pf = &pl->lwp_pcb.pcb_fpu;
1409 1413  
↓ open down ↓ 3 lines elided ↑ open up ↑
1413 1417  
1414 1418                  /* Always restore the fpu to the initial state. */
1415 1419                  if (fp_save_mech == FP_XSAVE)
1416 1420                          pf->fpu_xsave_mask = XFEATURE_FP_ALL;
1417 1421                  fpinit();
1418 1422                  pf->fpu_flags = FPU_EN | FPU_KERNEL;
1419 1423          } else {
1420 1424                  /* initialize the kfpu state */
1421 1425                  kernel_fpu_ctx_restore(kfpu);
1422 1426          }
     1427 +        kpreempt_enable();
1423 1428  }
1424 1429  
1425 1430  void
1426 1431  kernel_fpu_end(kfpu_state_t *kfpu, uint_t flags)
1427 1432  {
1428 1433          ulong_t iflags;
1429 1434  
1430 1435          if ((curthread->t_flag & T_KFPU) == 0) {
1431 1436                  panic("curthread attempting to clear kernel FPU state "
1432 1437                      "without using it");
↓ open down ↓ 87 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX