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