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