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 import _ "unsafe" // for linkname
10 11 // DebugOptions is set to true by the runtime if the OS supports reading
12 // GODEBUG early in runtime startup.
13 // This should not be changed after it is initialized.
14 var DebugOptions bool
15 16 // CacheLinePad is used to pad structs to avoid false sharing.
17 type CacheLinePad struct{ _ [CacheLinePadSize]byte }
18 19 // CacheLineSize is the CPU's assumed cache line size.
20 // There is currently no runtime detection of the real cache line size
21 // so we use the constant per GOARCH CacheLinePadSize as an approximation.
22 var CacheLineSize uintptr = CacheLinePadSize
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 var X86 struct {
29 _ CacheLinePad
30 HasAES bool
31 HasADX bool
32 HasAVX bool
33 HasAVX2 bool
34 HasAVX512F bool
35 HasAVX512BW bool
36 HasAVX512VL bool
37 HasBMI1 bool
38 HasBMI2 bool
39 HasERMS bool
40 HasFSRM bool
41 HasFMA bool
42 HasOSXSAVE bool
43 HasPCLMULQDQ bool
44 HasPOPCNT bool
45 HasRDTSCP bool
46 HasSHA bool
47 HasSSE3 bool
48 HasSSSE3 bool
49 HasSSE41 bool
50 HasSSE42 bool
51 _ CacheLinePad
52 }
53 54 // The booleans in ARM contain the correspondingly named cpu feature bit.
55 // The struct is padded to avoid false sharing.
56 var ARM struct {
57 _ CacheLinePad
58 HasVFPv4 bool
59 HasIDIVA bool
60 HasV7Atomics bool
61 _ CacheLinePad
62 }
63 64 // The booleans in ARM64 contain the correspondingly named cpu feature bit.
65 // The struct is padded to avoid false sharing.
66 var ARM64 struct {
67 _ CacheLinePad
68 HasAES bool
69 HasPMULL bool
70 HasSHA1 bool
71 HasSHA2 bool
72 HasSHA512 bool
73 HasSHA3 bool
74 HasCRC32 bool
75 HasATOMICS bool
76 HasCPUID bool
77 HasDIT bool
78 IsNeoverse bool
79 _ CacheLinePad
80 }
81 82 // The booleans in Loong64 contain the correspondingly named cpu feature bit.
83 // The struct is padded to avoid false sharing.
84 var Loong64 struct {
85 _ CacheLinePad
86 HasLSX bool // support 128-bit vector extension
87 HasLASX bool // support 256-bit vector extension
88 HasCRC32 bool // support CRC instruction
89 HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D}
90 HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction
91 _ CacheLinePad
92 }
93 94 var MIPS64X struct {
95 _ CacheLinePad
96 HasMSA bool // MIPS SIMD architecture
97 _ CacheLinePad
98 }
99 100 // For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00,
101 // since there are no optional categories. There are some exceptions that also
102 // require kernel support to work (darn, scv), so there are feature bits for
103 // those as well. The minimum processor requirement is POWER8 (ISA 2.07).
104 // The struct is padded to avoid false sharing.
105 var PPC64 struct {
106 _ CacheLinePad
107 HasDARN bool // Hardware random number generator (requires kernel enablement)
108 HasSCV bool // Syscall vectored (requires kernel enablement)
109 IsPOWER8 bool // ISA v2.07 (POWER8)
110 IsPOWER9 bool // ISA v3.00 (POWER9)
111 IsPOWER10 bool // ISA v3.1 (POWER10)
112 _ CacheLinePad
113 }
114 115 var S390X struct {
116 _ CacheLinePad
117 HasZARCH bool // z architecture mode is active [mandatory]
118 HasSTFLE bool // store facility list extended [mandatory]
119 HasLDISP bool // long (20-bit) displacements [mandatory]
120 HasEIMM bool // 32-bit immediates [mandatory]
121 HasDFP bool // decimal floating point
122 HasETF3EH bool // ETF-3 enhanced
123 HasMSA bool // message security assist (CPACF)
124 HasAES bool // KM-AES{128,192,256} functions
125 HasAESCBC bool // KMC-AES{128,192,256} functions
126 HasAESCTR bool // KMCTR-AES{128,192,256} functions
127 HasAESGCM bool // KMA-GCM-AES{128,192,256} functions
128 HasGHASH bool // KIMD-GHASH function
129 HasSHA1 bool // K{I,L}MD-SHA-1 functions
130 HasSHA256 bool // K{I,L}MD-SHA-256 functions
131 HasSHA512 bool // K{I,L}MD-SHA-512 functions
132 HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions
133 HasVX bool // vector facility. Note: the runtime sets this when it processes auxv records.
134 HasVXE bool // vector-enhancements facility 1
135 HasKDSA bool // elliptic curve functions
136 HasECDSA bool // NIST curves
137 HasEDDSA bool // Edwards curves
138 _ CacheLinePad
139 }
140 141 // RISCV64 contains the supported CPU features and performance characteristics for riscv64
142 // platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate
143 // the presence of RISC-V extensions.
144 // The struct is padded to avoid false sharing.
145 var RISCV64 struct {
146 _ CacheLinePad
147 HasFastMisaligned bool // Fast misaligned accesses
148 HasV bool // Vector extension compatible with RVV 1.0
149 HasZbb bool // Basic bit-manipulation extension
150 _ CacheLinePad
151 }
152 153 // CPU feature variables are accessed by assembly code in various packages.
154 //go:linkname X86
155 //go:linkname ARM
156 //go:linkname ARM64
157 //go:linkname Loong64
158 //go:linkname MIPS64X
159 //go:linkname PPC64
160 //go:linkname S390X
161 //go:linkname RISCV64
162 163 // Initialize examines the processor and sets the relevant variables above.
164 // This is called by the runtime package early in program initialization,
165 // before normal init functions are run. env is set by runtime if the OS supports
166 // cpu feature options in GODEBUG.
167 func Initialize(env []byte) {
168 doinit()
169 processOptions(env)
170 }
171 172 // options contains the cpu debug options that can be used in GODEBUG.
173 // Options are arch dependent and are added by the arch specific doinit functions.
174 // Features that are mandatory for the specific GOARCH should not be added to options
175 // (e.g. SSE2 on amd64).
176 var options []option
177 178 // Option names should be lower case. e.g. avx instead of AVX.
179 type option struct {
180 Name []byte
181 Feature *bool
182 Specified bool // whether feature value was specified in GODEBUG
183 Enable bool // whether feature should be enabled
184 }
185 186 // processOptions enables or disables CPU feature values based on the parsed env string.
187 // The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2...
188 // where feature names is one of the architecture specific list stored in the
189 // cpu packages options variable and values are either 'on' or 'off'.
190 // If env contains cpu.all=off then all cpu features referenced through the options
191 // variable are disabled. Other feature names and values result in warning messages.
192 func processOptions(env []byte) {
193 field:
194 for env != "" {
195 field := ""
196 i := indexByte(env, ',')
197 if i < 0 {
198 field, env = env, ""
199 } else {
200 field, env = env[:i], env[i+1:]
201 }
202 if len(field) < 4 || field[:4] != "cpu." {
203 continue
204 }
205 i = indexByte(field, '=')
206 if i < 0 {
207 print("GODEBUG: no value specified for \"", field, "\"\n")
208 continue
209 }
210 key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on"
211 212 var enable bool
213 switch value {
214 case "on":
215 enable = true
216 case "off":
217 enable = false
218 default:
219 print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n")
220 continue field
221 }
222 223 if key == "all" {
224 for i := range options {
225 options[i].Specified = true
226 options[i].Enable = enable
227 }
228 continue field
229 }
230 231 for i := range options {
232 if options[i].Name == key {
233 options[i].Specified = true
234 options[i].Enable = enable
235 continue field
236 }
237 }
238 239 print("GODEBUG: unknown cpu feature \"", key, "\"\n")
240 }
241 242 for _, o := range options {
243 if !o.Specified {
244 continue
245 }
246 247 if o.Enable && !*o.Feature {
248 print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n")
249 continue
250 }
251 252 *o.Feature = o.Enable
253 }
254 }
255 256 // indexByte returns the index of the first instance of c in s,
257 // or -1 if c is not present in s.
258 // indexByte is semantically the same as [strings.IndexByte].
259 // We copy this function because "internal/cpu" should not have external dependencies.
260 func indexByte(s []byte, c byte) int {
261 for i := 0; i < len(s); i++ {
262 if s[i] == c {
263 return i
264 }
265 }
266 return -1
267 }
268