github.com/SandwichDev/go-internals@v0.0.0-20210605002614-12311ac6b2c5/cpu/cpu.go (about) 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 HasSSE2 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 Required bool // whether feature is mandatory and can not be disabled 140 } 141 142 // processOptions enables or disables CPU feature values based on the parsed env string. 143 // The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2... 144 // where feature names is one of the architecture specific list stored in the 145 // cpu packages options variable and values are either 'on' or 'off'. 146 // If env contains cpu.all=off then all cpu features referenced through the options 147 // variable are disabled. Other feature names and values result in warning messages. 148 func processOptions(env string) { 149 field: 150 for env != "" { 151 field := "" 152 i := indexByte(env, ',') 153 if i < 0 { 154 field, env = env, "" 155 } else { 156 field, env = env[:i], env[i+1:] 157 } 158 if len(field) < 4 || field[:4] != "cpu." { 159 continue 160 } 161 i = indexByte(field, '=') 162 if i < 0 { 163 print("GODEBUG: no value specified for \"", field, "\"\n") 164 continue 165 } 166 key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" 167 168 var enable bool 169 switch value { 170 case "on": 171 enable = true 172 case "off": 173 enable = false 174 default: 175 print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n") 176 continue field 177 } 178 179 if key == "all" { 180 for i := range options { 181 options[i].Specified = true 182 options[i].Enable = enable || options[i].Required 183 } 184 continue field 185 } 186 187 for i := range options { 188 if options[i].Name == key { 189 options[i].Specified = true 190 options[i].Enable = enable 191 continue field 192 } 193 } 194 195 print("GODEBUG: unknown cpu feature \"", key, "\"\n") 196 } 197 198 for _, o := range options { 199 if !o.Specified { 200 continue 201 } 202 203 if o.Enable && !*o.Feature { 204 print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n") 205 continue 206 } 207 208 if !o.Enable && o.Required { 209 print("GODEBUG: can not disable \"", o.Name, "\", required CPU feature\n") 210 continue 211 } 212 213 *o.Feature = o.Enable 214 } 215 } 216 217 // indexByte returns the index of the first instance of c in s, 218 // or -1 if c is not present in s. 219 func indexByte(s string, c byte) int { 220 for i := 0; i < len(s); i++ { 221 if s[i] == c { 222 return i 223 } 224 } 225 return -1 226 }