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