Source file src/internal/cpu/cpu.go

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package cpu implements processor feature detection
     6  // used by the Go standard library.
     7  package cpu
     8  
     9  // DebugOptions is set to true by the runtime if the OS supports reading
    10  // GODEBUG early in runtime startup.
    11  // This should not be changed after it is initialized.
    12  var DebugOptions bool
    13  
    14  // CacheLinePad is used to pad structs to avoid false sharing.
    15  type CacheLinePad struct{ _ [CacheLinePadSize]byte }
    16  
    17  // CacheLineSize is the CPU's assumed cache line size.
    18  // There is currently no runtime detection of the real cache line size
    19  // so we use the constant per GOARCH CacheLinePadSize as an approximation.
    20  var CacheLineSize uintptr = CacheLinePadSize
    21  
    22  // The booleans in X86 contain the correspondingly named cpuid feature bit.
    23  // HasAVX and HasAVX2 are only set if the OS does support XMM and YMM registers
    24  // in addition to the cpuid feature bit being set.
    25  // The struct is padded to avoid false sharing.
    26  var X86 struct {
    27  	_            CacheLinePad
    28  	HasAES       bool
    29  	HasADX       bool
    30  	HasAVX       bool
    31  	HasAVX2      bool
    32  	HasBMI1      bool
    33  	HasBMI2      bool
    34  	HasERMS      bool
    35  	HasFMA       bool
    36  	HasOSXSAVE   bool
    37  	HasPCLMULQDQ bool
    38  	HasPOPCNT    bool
    39  	HasRDTSCP    bool
    40  	HasSSE3      bool
    41  	HasSSSE3     bool
    42  	HasSSE41     bool
    43  	HasSSE42     bool
    44  	_            CacheLinePad
    45  }
    46  
    47  // The booleans in ARM contain the correspondingly named cpu feature bit.
    48  // The struct is padded to avoid false sharing.
    49  var ARM struct {
    50  	_        CacheLinePad
    51  	HasVFPv4 bool
    52  	HasIDIVA bool
    53  	_        CacheLinePad
    54  }
    55  
    56  // The booleans in ARM64 contain the correspondingly named cpu feature bit.
    57  // The struct is padded to avoid false sharing.
    58  var ARM64 struct {
    59  	_            CacheLinePad
    60  	HasAES       bool
    61  	HasPMULL     bool
    62  	HasSHA1      bool
    63  	HasSHA2      bool
    64  	HasCRC32     bool
    65  	HasATOMICS   bool
    66  	HasCPUID     bool
    67  	IsNeoverseN1 bool
    68  	IsZeus       bool
    69  	_            CacheLinePad
    70  }
    71  
    72  var MIPS64X struct {
    73  	_      CacheLinePad
    74  	HasMSA bool // MIPS SIMD architecture
    75  	_      CacheLinePad
    76  }
    77  
    78  // For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00,
    79  // since there are no optional categories. There are some exceptions that also
    80  // require kernel support to work (darn, scv), so there are feature bits for
    81  // those as well. The minimum processor requirement is POWER8 (ISA 2.07).
    82  // The struct is padded to avoid false sharing.
    83  var PPC64 struct {
    84  	_        CacheLinePad
    85  	HasDARN  bool // Hardware random number generator (requires kernel enablement)
    86  	HasSCV   bool // Syscall vectored (requires kernel enablement)
    87  	IsPOWER8 bool // ISA v2.07 (POWER8)
    88  	IsPOWER9 bool // ISA v3.00 (POWER9)
    89  	_        CacheLinePad
    90  }
    91  
    92  var S390X struct {
    93  	_         CacheLinePad
    94  	HasZARCH  bool // z architecture mode is active [mandatory]
    95  	HasSTFLE  bool // store facility list extended [mandatory]
    96  	HasLDISP  bool // long (20-bit) displacements [mandatory]
    97  	HasEIMM   bool // 32-bit immediates [mandatory]
    98  	HasDFP    bool // decimal floating point
    99  	HasETF3EH bool // ETF-3 enhanced
   100  	HasMSA    bool // message security assist (CPACF)
   101  	HasAES    bool // KM-AES{128,192,256} functions
   102  	HasAESCBC bool // KMC-AES{128,192,256} functions
   103  	HasAESCTR bool // KMCTR-AES{128,192,256} functions
   104  	HasAESGCM bool // KMA-GCM-AES{128,192,256} functions
   105  	HasGHASH  bool // KIMD-GHASH function
   106  	HasSHA1   bool // K{I,L}MD-SHA-1 functions
   107  	HasSHA256 bool // K{I,L}MD-SHA-256 functions
   108  	HasSHA512 bool // K{I,L}MD-SHA-512 functions
   109  	HasSHA3   bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions
   110  	HasVX     bool // vector facility. Note: the runtime sets this when it processes auxv records.
   111  	HasVXE    bool // vector-enhancements facility 1
   112  	HasKDSA   bool // elliptic curve functions
   113  	HasECDSA  bool // NIST curves
   114  	HasEDDSA  bool // Edwards curves
   115  	_         CacheLinePad
   116  }
   117  
   118  // Initialize examines the processor and sets the relevant variables above.
   119  // This is called by the runtime package early in program initialization,
   120  // before normal init functions are run. env is set by runtime if the OS supports
   121  // cpu feature options in GODEBUG.
   122  func Initialize(env string) {
   123  	doinit()
   124  	processOptions(env)
   125  }
   126  
   127  // options contains the cpu debug options that can be used in GODEBUG.
   128  // Options are arch dependent and are added by the arch specific doinit functions.
   129  // Features that are mandatory for the specific GOARCH should not be added to options
   130  // (e.g. SSE2 on amd64).
   131  var options []option
   132  
   133  // Option names should be lower case. e.g. avx instead of AVX.
   134  type option struct {
   135  	Name      string
   136  	Feature   *bool
   137  	Specified bool // whether feature value was specified in GODEBUG
   138  	Enable    bool // whether feature should be enabled
   139  }
   140  
   141  // processOptions enables or disables CPU feature values based on the parsed env string.
   142  // The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2...
   143  // where feature names is one of the architecture specific list stored in the
   144  // cpu packages options variable and values are either 'on' or 'off'.
   145  // If env contains cpu.all=off then all cpu features referenced through the options
   146  // variable are disabled. Other feature names and values result in warning messages.
   147  func processOptions(env string) {
   148  field:
   149  	for env != "" {
   150  		field := ""
   151  		i := indexByte(env, ',')
   152  		if i < 0 {
   153  			field, env = env, ""
   154  		} else {
   155  			field, env = env[:i], env[i+1:]
   156  		}
   157  		if len(field) < 4 || field[:4] != "cpu." {
   158  			continue
   159  		}
   160  		i = indexByte(field, '=')
   161  		if i < 0 {
   162  			print("GODEBUG: no value specified for \"", field, "\"\n")
   163  			continue
   164  		}
   165  		key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on"
   166  
   167  		var enable bool
   168  		switch value {
   169  		case "on":
   170  			enable = true
   171  		case "off":
   172  			enable = false
   173  		default:
   174  			print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n")
   175  			continue field
   176  		}
   177  
   178  		if key == "all" {
   179  			for i := range options {
   180  				options[i].Specified = true
   181  				options[i].Enable = enable
   182  			}
   183  			continue field
   184  		}
   185  
   186  		for i := range options {
   187  			if options[i].Name == key {
   188  				options[i].Specified = true
   189  				options[i].Enable = enable
   190  				continue field
   191  			}
   192  		}
   193  
   194  		print("GODEBUG: unknown cpu feature \"", key, "\"\n")
   195  	}
   196  
   197  	for _, o := range options {
   198  		if !o.Specified {
   199  			continue
   200  		}
   201  
   202  		if o.Enable && !*o.Feature {
   203  			print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n")
   204  			continue
   205  		}
   206  
   207  		*o.Feature = o.Enable
   208  	}
   209  }
   210  
   211  // indexByte returns the index of the first instance of c in s,
   212  // or -1 if c is not present in s.
   213  func indexByte(s string, c byte) int {
   214  	for i := 0; i < len(s); i++ {
   215  		if s[i] == c {
   216  			return i
   217  		}
   218  	}
   219  	return -1
   220  }
   221  

View as plain text