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