github.com/AndrienkoAleksandr/go@v0.0.19/src/intern/cpu/cpu.go (about)

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