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 HasSHA3 bool 74 HasCRC32 bool 75 HasATOMICS bool 76 HasCPUID bool 77 HasDIT bool 78 IsNeoverse bool 79 _ CacheLinePad 80 } 81 82 // The booleans in Loong64 contain the correspondingly named cpu feature bit. 83 // The struct is padded to avoid false sharing. 84 var Loong64 struct { 85 _ CacheLinePad 86 HasLSX bool // support 128-bit vector extension 87 HasLASX bool // support 256-bit vector extension 88 HasCRC32 bool // support CRC instruction 89 HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} 90 HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction 91 _ CacheLinePad 92 } 93 94 var MIPS64X struct { 95 _ CacheLinePad 96 HasMSA bool // MIPS SIMD architecture 97 _ CacheLinePad 98 } 99 100 // For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00, 101 // since there are no optional categories. There are some exceptions that also 102 // require kernel support to work (darn, scv), so there are feature bits for 103 // those as well. The minimum processor requirement is POWER8 (ISA 2.07). 104 // The struct is padded to avoid false sharing. 105 var PPC64 struct { 106 _ CacheLinePad 107 HasDARN bool // Hardware random number generator (requires kernel enablement) 108 HasSCV bool // Syscall vectored (requires kernel enablement) 109 IsPOWER8 bool // ISA v2.07 (POWER8) 110 IsPOWER9 bool // ISA v3.00 (POWER9) 111 IsPOWER10 bool // ISA v3.1 (POWER10) 112 _ CacheLinePad 113 } 114 115 var S390X struct { 116 _ CacheLinePad 117 HasZARCH bool // z architecture mode is active [mandatory] 118 HasSTFLE bool // store facility list extended [mandatory] 119 HasLDISP bool // long (20-bit) displacements [mandatory] 120 HasEIMM bool // 32-bit immediates [mandatory] 121 HasDFP bool // decimal floating point 122 HasETF3EH bool // ETF-3 enhanced 123 HasMSA bool // message security assist (CPACF) 124 HasAES bool // KM-AES{128,192,256} functions 125 HasAESCBC bool // KMC-AES{128,192,256} functions 126 HasAESCTR bool // KMCTR-AES{128,192,256} functions 127 HasAESGCM bool // KMA-GCM-AES{128,192,256} functions 128 HasGHASH bool // KIMD-GHASH function 129 HasSHA1 bool // K{I,L}MD-SHA-1 functions 130 HasSHA256 bool // K{I,L}MD-SHA-256 functions 131 HasSHA512 bool // K{I,L}MD-SHA-512 functions 132 HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions 133 HasVX bool // vector facility. Note: the runtime sets this when it processes auxv records. 134 HasVXE bool // vector-enhancements facility 1 135 HasKDSA bool // elliptic curve functions 136 HasECDSA bool // NIST curves 137 HasEDDSA bool // Edwards curves 138 _ CacheLinePad 139 } 140 141 // RISCV64 contains the supported CPU features and performance characteristics for riscv64 142 // platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate 143 // the presence of RISC-V extensions. 144 // The struct is padded to avoid false sharing. 145 var RISCV64 struct { 146 _ CacheLinePad 147 HasFastMisaligned bool // Fast misaligned accesses 148 HasV bool // Vector extension compatible with RVV 1.0 149 HasZbb bool // Basic bit-manipulation extension 150 _ CacheLinePad 151 } 152 153 // CPU feature variables are accessed by assembly code in various packages. 154 //go:linkname X86 155 //go:linkname ARM 156 //go:linkname ARM64 157 //go:linkname Loong64 158 //go:linkname MIPS64X 159 //go:linkname PPC64 160 //go:linkname S390X 161 //go:linkname RISCV64 162 163 // Initialize examines the processor and sets the relevant variables above. 164 // This is called by the runtime package early in program initialization, 165 // before normal init functions are run. env is set by runtime if the OS supports 166 // cpu feature options in GODEBUG. 167 func Initialize(env string) { 168 doinit() 169 processOptions(env) 170 } 171 172 // options contains the cpu debug options that can be used in GODEBUG. 173 // Options are arch dependent and are added by the arch specific doinit functions. 174 // Features that are mandatory for the specific GOARCH should not be added to options 175 // (e.g. SSE2 on amd64). 176 var options []option 177 178 // Option names should be lower case. e.g. avx instead of AVX. 179 type option struct { 180 Name string 181 Feature *bool 182 Specified bool // whether feature value was specified in GODEBUG 183 Enable bool // whether feature should be enabled 184 } 185 186 // processOptions enables or disables CPU feature values based on the parsed env string. 187 // The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2... 188 // where feature names is one of the architecture specific list stored in the 189 // cpu packages options variable and values are either 'on' or 'off'. 190 // If env contains cpu.all=off then all cpu features referenced through the options 191 // variable are disabled. Other feature names and values result in warning messages. 192 func processOptions(env string) { 193 field: 194 for env != "" { 195 field := "" 196 i := indexByte(env, ',') 197 if i < 0 { 198 field, env = env, "" 199 } else { 200 field, env = env[:i], env[i+1:] 201 } 202 if len(field) < 4 || field[:4] != "cpu." { 203 continue 204 } 205 i = indexByte(field, '=') 206 if i < 0 { 207 print("GODEBUG: no value specified for \"", field, "\"\n") 208 continue 209 } 210 key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" 211 212 var enable bool 213 switch value { 214 case "on": 215 enable = true 216 case "off": 217 enable = false 218 default: 219 print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n") 220 continue field 221 } 222 223 if key == "all" { 224 for i := range options { 225 options[i].Specified = true 226 options[i].Enable = enable 227 } 228 continue field 229 } 230 231 for i := range options { 232 if options[i].Name == key { 233 options[i].Specified = true 234 options[i].Enable = enable 235 continue field 236 } 237 } 238 239 print("GODEBUG: unknown cpu feature \"", key, "\"\n") 240 } 241 242 for _, o := range options { 243 if !o.Specified { 244 continue 245 } 246 247 if o.Enable && !*o.Feature { 248 print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n") 249 continue 250 } 251 252 *o.Feature = o.Enable 253 } 254 } 255 256 // indexByte returns the index of the first instance of c in s, 257 // or -1 if c is not present in s. 258 // indexByte is semantically the same as [strings.IndexByte]. 259 // We copy this function because "internal/cpu" should not have external dependencies. 260 func indexByte(s string, c byte) int { 261 for i := 0; i < len(s); i++ { 262 if s[i] == c { 263 return i 264 } 265 } 266 return -1 267 } 268