]> Cypherpunks.ru repositories - gostls13.git/blob - src/internal/cpu/cpu.go
runtime: on arm32, detect whether we have sync instructions
[gostls13.git] / src / internal / cpu / cpu.go
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         HasV7Atomics bool
55         _            CacheLinePad
56 }
57
58 // The booleans in ARM64 contain the correspondingly named cpu feature bit.
59 // The struct is padded to avoid false sharing.
60 var ARM64 struct {
61         _          CacheLinePad
62         HasAES     bool
63         HasPMULL   bool
64         HasSHA1    bool
65         HasSHA2    bool
66         HasSHA512  bool
67         HasCRC32   bool
68         HasATOMICS bool
69         HasCPUID   bool
70         IsNeoverse 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 }