github.com/FISCO-BCOS/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/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 HasETF3EH 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 HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions 129 HasVX bool // vector facility. Note: the runtime sets this when it processes auxv records. 130 HasVXE bool // vector-enhancements facility 1 131 HasKDSA bool // elliptic curve functions 132 HasECDSA bool // NIST curves 133 HasEDDSA bool // Edwards curves 134 _ CacheLinePad 135 } 136 137 // Initialize examines the processor and sets the relevant variables above. 138 // This is called by the runtime package early in program initialization, 139 // before normal init functions are run. env is set by runtime if the OS supports 140 // cpu feature options in GODEBUG. 141 func Initialize(env string) { 142 doinit() 143 processOptions(env) 144 } 145 146 // options contains the cpu debug options that can be used in GODEBUG. 147 // Options are arch dependent and are added by the arch specific doinit functions. 148 // Features that are mandatory for the specific GOARCH should not be added to options 149 // (e.g. SSE2 on amd64). 150 var options []option 151 152 // Option names should be lower case. e.g. avx instead of AVX. 153 type option struct { 154 Name string 155 Feature *bool 156 Specified bool // whether feature value was specified in GODEBUG 157 Enable bool // whether feature should be enabled 158 Required bool // whether feature is mandatory and can not be disabled 159 } 160 161 // processOptions enables or disables CPU feature values based on the parsed env string. 162 // The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2... 163 // where feature names is one of the architecture specifc list stored in the 164 // cpu packages options variable and values are either 'on' or 'off'. 165 // If env contains cpu.all=off then all cpu features referenced through the options 166 // variable are disabled. Other feature names and values result in warning messages. 167 func processOptions(env string) { 168 field: 169 for env != "" { 170 field := "" 171 i := indexByte(env, ',') 172 if i < 0 { 173 field, env = env, "" 174 } else { 175 field, env = env[:i], env[i+1:] 176 } 177 if len(field) < 4 || field[:4] != "cpu." { 178 continue 179 } 180 i = indexByte(field, '=') 181 if i < 0 { 182 print("GODEBUG: no value specified for \"", field, "\"\n") 183 continue 184 } 185 key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" 186 187 var enable bool 188 switch value { 189 case "on": 190 enable = true 191 case "off": 192 enable = false 193 default: 194 print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n") 195 continue field 196 } 197 198 if key == "all" { 199 for i := range options { 200 options[i].Specified = true 201 options[i].Enable = enable || options[i].Required 202 } 203 continue field 204 } 205 206 for i := range options { 207 if options[i].Name == key { 208 options[i].Specified = true 209 options[i].Enable = enable 210 continue field 211 } 212 } 213 214 print("GODEBUG: unknown cpu feature \"", key, "\"\n") 215 } 216 217 for _, o := range options { 218 if !o.Specified { 219 continue 220 } 221 222 if o.Enable && !*o.Feature { 223 print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n") 224 continue 225 } 226 227 if !o.Enable && o.Required { 228 print("GODEBUG: can not disable \"", o.Name, "\", required CPU feature\n") 229 continue 230 } 231 232 *o.Feature = o.Enable 233 } 234 } 235 236 // indexByte returns the index of the first instance of c in s, 237 // or -1 if c is not present in s. 238 func indexByte(s string, c byte) int { 239 for i := 0; i < len(s); i++ { 240 if s[i] == c { 241 return i 242 } 243 } 244 return -1 245 }