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