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 go was compiled with GOEXPERIMENT=debugcpu
10 // and GOOS is Linux or Darwin. This variable is linknamed in runtime/proc.go.
11 var debugOptions bool
12 13 var X86 x86
14 15 // "Loads data or instructions from memory to the second-level cache.
16 // To use the streamer, organize the data or instructions in blocks of 128 bytes,
17 // aligned on 128 bytes."
18 // From <IntelĀ® 64 and IA-32 architectures optimization reference manual>,
19 // in section 3.7.3 "Hardware Prefetching for Second-Level Cache"
20 //
21 // In practice, I have found use 128bytes can gain better performance than 64bytes (one cache line).
22 const X86FalseSharingRange = 128
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 _ [X86FalseSharingRange]byte
30 HasCMPXCHG16B bool
31 HasAES bool
32 HasADX bool
33 HasAVX bool
34 HasAVX2 bool
35 HasAVX512F bool
36 HasAVX512DQ bool
37 HasAVX512BW bool
38 HasAVX512VL bool
39 HasBMI1 bool
40 HasBMI2 bool
41 HasERMS bool
42 HasFMA bool
43 HasOSXSAVE bool
44 HasPCLMULQDQ bool
45 HasPOPCNT bool
46 HasSSE2 bool
47 HasSSE3 bool
48 HasSSSE3 bool
49 HasSSE41 bool
50 HasSSE42 bool
51 // The invariant TSC will run at a constant rate in all ACPI P-, C-, and T-states.
52 // This is the architectural behavior moving forward. On processors with
53 // invariant TSC support, the OS may use the TSC for wall clock timer services (instead of ACPI or HPET timers).
54 HasInvariantTSC bool
55 56 Cache Cache
57 58 // TSCFrequency only meaningful when HasInvariantTSC == true.
59 // Unit: Hz.
60 //
61 // Warn:
62 // 1. If it's 0, means failed to get it from frequency table provided by Intel manual.
63 TSCFrequency uint64
64 65 Name string
66 Signature string // DisplayFamily_DisplayModel.
67 Family uint32 // CPU family number.
68 Model uint32 // CPU model number.
69 SteppingID uint32
70 71 _ [X86FalseSharingRange]byte
72 }
73 74 // CPU Cache Size.
75 // -1 if undetected.
76 type Cache struct {
77 L1I int
78 L1D int
79 L2 int
80 L3 int
81 }
82 83 var PPC64 ppc64
84 85 // For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
86 // since there are no optional categories. There are some exceptions that also
87 // require kernel support to work (darn, scv), so there are feature bits for
88 // those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
89 // maintain some of the old feature checks for optional categories for
90 // safety.
91 // The struct is padded to avoid false sharing.
92 type ppc64 struct {
93 _ [CacheLineSize]byte
94 HasVMX bool // Vector unit (Altivec)
95 HasDFP bool // Decimal Floating Point unit
96 HasVSX bool // Vector-scalar unit
97 HasHTM bool // Hardware Transactional Memory
98 HasISEL bool // Integer select
99 HasVCRYPTO bool // Vector cryptography
100 HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
101 HasDARN bool // Hardware random number generator (requires kernel enablement)
102 HasSCV bool // Syscall vectored (requires kernel enablement)
103 IsPOWER8 bool // ISA v2.07 (POWER8)
104 IsPOWER9 bool // ISA v3.00 (POWER9)
105 _ [CacheLineSize]byte
106 }
107 108 var ARM64 arm64
109 110 // The booleans in arm64 contain the correspondingly named cpu feature bit.
111 // The struct is padded to avoid false sharing.
112 type arm64 struct {
113 _ [CacheLineSize]byte
114 HasFP bool
115 HasASIMD bool
116 HasEVTSTRM bool
117 HasAES bool
118 HasPMULL bool
119 HasSHA1 bool
120 HasSHA2 bool
121 HasCRC32 bool
122 HasATOMICS bool
123 HasFPHP bool
124 HasASIMDHP bool
125 HasCPUID bool
126 HasASIMDRDM bool
127 HasJSCVT bool
128 HasFCMA bool
129 HasLRCPC bool
130 HasDCPOP bool
131 HasSHA3 bool
132 HasSM3 bool
133 HasSM4 bool
134 HasASIMDDP bool
135 HasSHA512 bool
136 HasSVE bool
137 HasASIMDFHM bool
138 _ [CacheLineSize]byte
139 }
140 141 var S390X s390x
142 143 type s390x struct {
144 _ [CacheLineSize]byte
145 HasZArch bool // z architecture mode is active [mandatory]
146 HasSTFLE bool // store facility list extended [mandatory]
147 HasLDisp bool // long (20-bit) displacements [mandatory]
148 HasEImm bool // 32-bit immediates [mandatory]
149 HasDFP bool // decimal floating point
150 HasETF3Enhanced bool // ETF-3 enhanced
151 HasMSA bool // message security assist (CPACF)
152 HasAES bool // KM-AES{128,192,256} functions
153 HasAESCBC bool // KMC-AES{128,192,256} functions
154 HasAESCTR bool // KMCTR-AES{128,192,256} functions
155 HasAESGCM bool // KMA-GCM-AES{128,192,256} functions
156 HasGHASH bool // KIMD-GHASH function
157 HasSHA1 bool // K{I,L}MD-SHA-1 functions
158 HasSHA256 bool // K{I,L}MD-SHA-256 functions
159 HasSHA512 bool // K{I,L}MD-SHA-512 functions
160 HasVX bool // vector facility. Note: the runtime sets this when it processes auxv records.
161 _ [CacheLineSize]byte
162 }
163 164 // initialize examines the processor and sets the relevant variables above.
165 // This is called by the runtime package early in program initialization,
166 // before normal init functions are run. env is set by runtime on Linux and Darwin
167 // if go was compiled with GOEXPERIMENT=debugcpu.
168 func init() {
169 doinit()
170 processOptions("")
171 }
172 173 // options contains the cpu debug options that can be used in GODEBUGCPU.
174 // Options are arch dependent and are added by the arch specific doinit functions.
175 // Features that are mandatory for the specific GOARCH should not be added to options
176 // (e.g. SSE2 on amd64).
177 var options []option
178 179 // Option names should be lower case. e.g. avx instead of AVX.
180 type option struct {
181 Name string
182 Feature *bool
183 }
184 185 // processOptions disables CPU feature values based on the parsed env string.
186 // The env string is expected to be of the form feature1=0,feature2=0...
187 // where feature names is one of the architecture specifc list stored in the
188 // cpu packages options variable. If env contains all=0 then all capabilities
189 // referenced through the options variable are disabled. Other feature
190 // names and values other than 0 are silently ignored.
191 func processOptions(env string) {
192 field:
193 for env != "" {
194 field := ""
195 i := indexByte(env, ',')
196 if i < 0 {
197 field, env = env, ""
198 } else {
199 field, env = env[:i], env[i+1:]
200 }
201 i = indexByte(field, '=')
202 if i < 0 {
203 continue
204 }
205 key, value := field[:i], field[i+1:]
206 207 // Only allow turning off CPU features by specifying '0'.
208 if value == "0" {
209 if key == "all" {
210 for _, v := range options {
211 *v.Feature = false
212 }
213 return
214 } else {
215 for _, v := range options {
216 if v.Name == key {
217 *v.Feature = false
218 continue field
219 }
220 }
221 }
222 }
223 }
224 }
225 226 // indexByte returns the index of the first instance of c in s,
227 // or -1 if c is not present in s.
228 func indexByte(s string, c byte) int {
229 for i := 0; i < len(s); i++ {
230 if s[i] == c {
231 return i
232 }
233 }
234 return -1
235 }
236