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