Print this page
    
15254 %ymm registers not restored after signal handler
15367 x86 getfpregs() summons corrupting %xmm ghosts
15333 want x86 /proc xregs support (libc_db, libproc, mdb, etc.)
15336 want libc functions for extended ucontext_t
15334 want ps_lwphandle-specific reg routines
15328 FPU_CW_INIT mistreats reserved bit
15335 i86pc fpu_subr.c isn't really platform-specific
15332 setcontext(2) isn't actually noreturn
15331 need <sys/stdalign.h>
Change-Id: I7060aa86042dfb989f77fc3323c065ea2eafa9ad
Conflicts:
    usr/src/uts/common/fs/proc/prcontrol.c
    usr/src/uts/intel/os/archdep.c
    usr/src/uts/intel/sys/ucontext.h
    usr/src/uts/intel/syscall/getcontext.c
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/i86pc/os/fpu_subr.c
          +++ new/usr/src/uts/intel/os/fpu_subr.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  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  /*
  23   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright (c) 2018, Joyent, Inc.
  25   25   */
  26   26  
  27   27  /*
  28   28   * Floating point configuration.
  29   29   */
  30   30  
  31   31  #include <sys/types.h>
  32   32  #include <sys/regset.h>
  33   33  #include <sys/privregs.h>
  34   34  #include <sys/x86_archext.h>
  35   35  #include <sys/archsystm.h>
  36   36  #include <sys/fp.h>
  37   37  #include <sys/cmn_err.h>
  38   38  #include <sys/exec.h>
  39   39  
  40   40  #define XMM_ALIGN       16
  41   41  
  42   42  /*
  43   43   * See section 10.5.1 in the Intel 64 and IA-32 Architectures Software
  44   44   * Developer’s Manual, Volume 1.
  45   45   */
  46   46  #define FXSAVE_ALIGN    16
  47   47  
  48   48  /*
  49   49   * See section 13.4 in the Intel 64 and IA-32 Architectures Software
  50   50   * Developer’s Manual, Volume 1.
  51   51   */
  52   52  #define XSAVE_ALIGN     64
  53   53  
  54   54  /*
  
    | 
      ↓ open down ↓ | 
    54 lines elided | 
    
      ↑ open up ↑ | 
  
  55   55   * If fpu_exists is non-zero, fpu_probe will attempt to use any
  56   56   * hardware FPU (subject to other constraints, see below).  If
  57   57   * fpu_exists is zero, fpu_probe will report that there is no
  58   58   * FPU even if there is one.
  59   59   */
  60   60  int fpu_exists = 1;
  61   61  
  62   62  int fp_kind = FP_387;
  63   63  
  64   64  /*
  65      - * The kind of FPU we advertise to rtld so it knows what to do on context
  66      - * switch.
  67      - */
  68      -int fp_elf = AT_386_FPINFO_FXSAVE;
  69      -
  70      -/*
  71      - * Mechanism to save FPU state.
  72      - */
  73      -int fp_save_mech = FP_FXSAVE;
  74      -
  75      -/*
  76   65   * The variable fpu_ignored is provided to allow other code to
  77   66   * determine whether emulation is being done because there is
  78   67   * no FPU or because of an override requested via /etc/system.
  79   68   */
  80   69  int fpu_ignored = 0;
  81   70  
  82   71  /*
  83   72   * Used by ppcopy and ppzero to determine whether or not to use the
  84   73   * SSE-based pagecopy and pagezero routines
  85   74   */
  86   75  int use_sse_pagecopy = 0;
  87   76  int use_sse_pagezero = 0;
  88   77  int use_sse_copy = 0;
  89   78  
  90   79  #if defined(__xpv)
  91   80  
  92   81  /*
  93   82   * Use of SSE or otherwise is forcibly configured for us by the hypervisor.
  94   83   */
  95   84  
  96   85  #define ENABLE_SSE()
  97   86  #define DISABLE_SSE()
  98   87  
  99   88  #else   /* __xpv */
 100   89  
 101   90  #define ENABLE_SSE()    setcr4(CR4_ENABLE_SSE_FLAGS(getcr4()))
 102   91  #define DISABLE_SSE()   setcr4(CR4_DISABLE_SSE_FLAGS(getcr4()))
 103   92  
 104   93  #endif  /* __xpv */
 105   94  
 106   95  /*
 107   96   * Try and figure out what kind of FP capabilities we have, and
 108   97   * set up the control registers accordingly.
 109   98   */
 110   99  void
 111  100  fpu_probe(void)
 112  101  {
 113  102          if (fpu_initial_probe() != 0)
 114  103                  goto nofpu;
 115  104  
 116  105          if (fpu_exists == 0) {
 117  106                  fpu_ignored = 1;
 118  107                  goto nofpu;
 119  108          }
 120  109  
 121  110  #ifndef __xpv
 122  111          /*
 123  112           * Check and see if the fpu is present by looking
 124  113           * at the "extension type" bit.  (While this used to
 125  114           * indicate a 387DX coprocessor in days gone by,
 126  115           * it's forced on by modern implementations for
 127  116           * compatibility.)
 128  117           */
 129  118          if ((getcr0() & CR0_ET) == 0)
 130  119                  goto nofpu;
 131  120  #endif
 132  121  
 133  122          /* Use the more complex exception clearing code if necessary */
 134  123          if (cpuid_need_fp_excp_handling())
 135  124                  fpsave_ctxt = fpxsave_excp_clr_ctxt;
 136  125  
 137  126          /*
 138  127           * SSE and SSE2 are required for the 64-bit ABI.
 139  128           *
 140  129           * If they're not present, we can in principal run
 141  130           * 32-bit userland, though 64-bit processes will be hosed.
 142  131           *
 143  132           * (Perhaps we should complain more about this case!)
 144  133           */
 145  134          if (is_x86_feature(x86_featureset, X86FSET_SSE) &&
 146  135              is_x86_feature(x86_featureset, X86FSET_SSE2)) {
 147  136                  fp_kind |= __FP_SSE;
 148  137                  ENABLE_SSE();
 149  138  
 150  139                  if (is_x86_feature(x86_featureset, X86FSET_AVX)) {
 151  140                          ASSERT(is_x86_feature(x86_featureset, X86FSET_XSAVE));
 152  141                          fp_kind |= __FP_AVX;
 153  142                  }
 154  143  
 155  144                  if (is_x86_feature(x86_featureset, X86FSET_XSAVE)) {
 156  145                          fp_save_mech = FP_XSAVE;
 157  146                          fp_elf = AT_386_FPINFO_XSAVE;
 158  147                          if (is_x86_feature(x86_featureset, X86FSET_XSAVEOPT)) {
 159  148                                  /*
 160  149                                   * Use the more complex exception
 161  150                                   * clearing code if necessary.
 162  151                                   */
 163  152                                  if (cpuid_need_fp_excp_handling()) {
 164  153                                          fpsave_ctxt = xsaveopt_excp_clr_ctxt;
 165  154                                          fp_elf = AT_386_FPINFO_XSAVE_AMD;
 166  155                                  } else {
 167  156                                          fpsave_ctxt = xsaveopt_ctxt;
 168  157                                  }
 169  158                                  xsavep = xsaveopt;
 170  159                          } else {
 171  160                                  /*
 172  161                                   * Use the more complex exception
 173  162                                   * clearing code if necessary.
 174  163                                   */
 175  164                                  if (cpuid_need_fp_excp_handling()) {
 176  165                                          fpsave_ctxt = xsave_excp_clr_ctxt;
 177  166                                          fp_elf = AT_386_FPINFO_XSAVE_AMD;
 178  167                                  } else {
 179  168                                          fpsave_ctxt = xsave_ctxt;
 180  169                                  }
 181  170                          }
 182  171                          fprestore_ctxt = xrestore_ctxt;
 183  172                          fpsave_cachep = kmem_cache_create("xsave_cache",
 184  173                              cpuid_get_xsave_size(), XSAVE_ALIGN,
 185  174                              NULL, NULL, NULL, NULL, NULL, 0);
 186  175                  } else {
 187  176                          /* fp_save_mech defaults to FP_FXSAVE */
 188  177                          fpsave_cachep = kmem_cache_create("fxsave_cache",
 189  178                              sizeof (struct fxsave_state), FXSAVE_ALIGN,
 190  179                              NULL, NULL, NULL, NULL, NULL, 0);
 191  180                          fp_elf = AT_386_FPINFO_FXSAVE;
 192  181                  }
 193  182          }
 194  183  
 195  184          if (is_x86_feature(x86_featureset, X86FSET_SSE2)) {
 196  185                  use_sse_pagecopy = use_sse_pagezero = use_sse_copy = 1;
 197  186          }
 198  187  
 199  188          if (fp_kind & __FP_SSE) {
 200  189                  struct fxsave_state *fx;
 201  190                  uint8_t fxsave_state[sizeof (struct fxsave_state) + XMM_ALIGN];
 202  191  
 203  192                  /*
 204  193                   * Extract the mxcsr mask from our first fxsave
 205  194                   */
 206  195                  fx = (void *)(((uintptr_t)(&fxsave_state[0]) +
 207  196                      XMM_ALIGN) & ~(XMM_ALIGN - 1ul));
 208  197  
 209  198                  fx->fx_mxcsr_mask = 0;
 210  199                  fxsave_insn(fx);
 211  200                  if (fx->fx_mxcsr_mask != 0) {
 212  201                          /*
 213  202                           * Override default mask initialized in fpu.c
 214  203                           */
 215  204                          sse_mxcsr_mask = fx->fx_mxcsr_mask;
 216  205                  }
 217  206          }
 218  207  
 219  208          setcr0(CR0_ENABLE_FPU_FLAGS(getcr0()));
  
    | 
      ↓ open down ↓ | 
    134 lines elided | 
    
      ↑ open up ↑ | 
  
 220  209          return;
 221  210  
 222  211          /*
 223  212           * No FPU hardware present
 224  213           */
 225  214  nofpu:
 226  215          setcr0(CR0_DISABLE_FPU_FLAGS(getcr0()));
 227  216          DISABLE_SSE();
 228  217          fp_kind = FP_NO;
 229  218          fpu_exists = 0;
 230      -}
 231      -
 232      -/*
 233      - * Fill in FPU information that is required by exec.
 234      - */
 235      -void
 236      -fpu_auxv_info(int *typep, size_t *lenp)
 237      -{
 238      -        *typep = fp_elf;
 239      -        switch (fp_save_mech) {
 240      -        case FP_FXSAVE:
 241      -                *lenp = sizeof (struct fxsave_state);
 242      -                break;
 243      -        case FP_XSAVE:
 244      -                *lenp = cpuid_get_xsave_size();
 245      -                break;
 246      -        default:
 247      -                *lenp = 0;
 248      -                break;
 249      -        }
 250  219  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX