github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/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 var X86 x86 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 type x86 struct { 29 _ CacheLinePad 30 HasAES bool 31 HasADX bool 32 HasAVX bool 33 HasAVX2 bool 34 HasBMI1 bool 35 HasBMI2 bool 36 HasERMS bool 37 HasFMA bool 38 HasOSXSAVE bool 39 HasPCLMULQDQ bool 40 HasPOPCNT bool 41 HasSSE2 bool 42 HasSSE3 bool 43 HasSSSE3 bool 44 HasSSE41 bool 45 HasSSE42 bool 46 _ CacheLinePad 47 } 48 49 var PPC64 ppc64 50 51 // For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00, 52 // since there are no optional categories. There are some exceptions that also 53 // require kernel support to work (darn, scv), so there are feature bits for 54 // those as well. The minimum processor requirement is POWER8 (ISA 2.07). 55 // The struct is padded to avoid false sharing. 56 type ppc64 struct { 57 _ CacheLinePad 58 HasDARN bool // Hardware random number generator (requires kernel enablement) 59 HasSCV bool // Syscall vectored (requires kernel enablement) 60 IsPOWER8 bool // ISA v2.07 (POWER8) 61 IsPOWER9 bool // ISA v3.00 (POWER9) 62 _ CacheLinePad 63 } 64 65 var ARM arm 66 67 // The booleans in arm contain the correspondingly named cpu feature bit. 68 // The struct is padded to avoid false sharing. 69 type arm struct { 70 _ CacheLinePad 71 HasVFPv4 bool 72 HasIDIVA bool 73 _ CacheLinePad 74 } 75 76 var ARM64 arm64 77 78 // The booleans in arm64 contain the correspondingly named cpu feature bit. 79 // The struct is padded to avoid false sharing. 80 type arm64 struct { 81 _ CacheLinePad 82 HasFP bool 83 HasASIMD bool 84 HasEVTSTRM bool 85 HasAES bool 86 HasPMULL bool 87 HasSHA1 bool 88 HasSHA2 bool 89 HasCRC32 bool 90 HasATOMICS bool 91 HasFPHP bool 92 HasASIMDHP bool 93 HasCPUID bool 94 HasASIMDRDM bool 95 HasJSCVT bool 96 HasFCMA bool 97 HasLRCPC bool 98 HasDCPOP bool 99 HasSHA3 bool 100 HasSM3 bool 101 HasSM4 bool 102 HasASIMDDP bool 103 HasSHA512 bool 104 HasSVE bool 105 HasASIMDFHM bool 106 _ CacheLinePad 107 } 108 109 var S390X s390x 110 111 type s390x struct { 112 _ CacheLinePad 113 HasZArch bool // z architecture mode is active [mandatory] 114 HasSTFLE bool // store facility list extended [mandatory] 115 HasLDisp bool // long (20-bit) displacements [mandatory] 116 HasEImm bool // 32-bit immediates [mandatory] 117 HasDFP bool // decimal floating point 118 HasETF3Enhanced bool // ETF-3 enhanced 119 HasMSA bool // message security assist (CPACF) 120 HasAES bool // KM-AES{128,192,256} functions 121 HasAESCBC bool // KMC-AES{128,192,256} functions 122 HasAESCTR bool // KMCTR-AES{128,192,256} functions 123 HasAESGCM bool // KMA-GCM-AES{128,192,256} functions 124 HasGHASH bool // KIMD-GHASH function 125 HasSHA1 bool // K{I,L}MD-SHA-1 functions 126 HasSHA256 bool // K{I,L}MD-SHA-256 functions 127 HasSHA512 bool // K{I,L}MD-SHA-512 functions 128 HasVX bool // vector facility. Note: the runtime sets this when it processes auxv records. 129 HasVE1 bool // vector-enhancement 1 130 _ CacheLinePad 131 } 132 133 // Initialize examines the processor and sets the relevant variables above. 134 // This is called by the runtime package early in program initialization, 135 // before normal init functions are run. env is set by runtime if the OS supports 136 // cpu feature options in GODEBUG. 137 func Initialize(env string) { 138 doinit() 139 processOptions(env) 140 } 141 142 // options contains the cpu debug options that can be used in GODEBUG. 143 // Options are arch dependent and are added by the arch specific doinit functions. 144 // Features that are mandatory for the specific GOARCH should not be added to options 145 // (e.g. SSE2 on amd64). 146 var options []option 147 148 // Option names should be lower case. e.g. avx instead of AVX. 149 type option struct { 150 Name string 151 Feature *bool 152 Specified bool // whether feature value was specified in GODEBUG 153 Enable bool // whether feature should be enabled 154 Required bool // whether feature is mandatory and can not be disabled 155 } 156 157 // processOptions enables or disables CPU feature values based on the parsed env string. 158 // The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2... 159 // where feature names is one of the architecture specifc list stored in the 160 // cpu packages options variable and values are either 'on' or 'off'. 161 // If env contains cpu.all=off then all cpu features referenced through the options 162 // variable are disabled. Other feature names and values result in warning messages. 163 func processOptions(env string) { 164 field: 165 for env != "" { 166 field := "" 167 i := indexByte(env, ',') 168 if i < 0 { 169 field, env = env, "" 170 } else { 171 field, env = env[:i], env[i+1:] 172 } 173 if len(field) < 4 || field[:4] != "cpu." { 174 continue 175 } 176 i = indexByte(field, '=') 177 if i < 0 { 178 print("GODEBUG: no value specified for \"", field, "\"\n") 179 continue 180 } 181 key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" 182 183 var enable bool 184 switch value { 185 case "on": 186 enable = true 187 case "off": 188 enable = false 189 default: 190 print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n") 191 continue field 192 } 193 194 if key == "all" { 195 for i := range options { 196 options[i].Specified = true 197 options[i].Enable = enable || options[i].Required 198 } 199 continue field 200 } 201 202 for i := range options { 203 if options[i].Name == key { 204 options[i].Specified = true 205 options[i].Enable = enable 206 continue field 207 } 208 } 209 210 print("GODEBUG: unknown cpu feature \"", key, "\"\n") 211 } 212 213 for _, o := range options { 214 if !o.Specified { 215 continue 216 } 217 218 if o.Enable && !*o.Feature { 219 print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n") 220 continue 221 } 222 223 if !o.Enable && o.Required { 224 print("GODEBUG: can not disable \"", o.Name, "\", required CPU feature\n") 225 continue 226 } 227 228 *o.Feature = o.Enable 229 } 230 } 231 232 // indexByte returns the index of the first instance of c in s, 233 // or -1 if c is not present in s. 234 func indexByte(s string, c byte) int { 235 for i := 0; i < len(s); i++ { 236 if s[i] == c { 237 return i 238 } 239 } 240 return -1 241 }