cpu_s390x.mx raw
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
6
7 const CacheLinePadSize = 256
8
9 var HWCap uint
10
11 // bitIsSet reports whether the bit at index is set. The bit index
12 // is in big endian order, so bit index 0 is the leftmost bit.
13 func bitIsSet(bits []uint64, index uint) bool {
14 return bits[index/64]&((1<<63)>>(index%64)) != 0
15 }
16
17 // function is the function code for the named function.
18 type function uint8
19
20 const (
21 // KM{,A,C,CTR} function codes
22 aes128 function = 18 // AES-128
23 aes192 function = 19 // AES-192
24 aes256 function = 20 // AES-256
25
26 // K{I,L}MD function codes
27 sha1 function = 1 // SHA-1
28 sha256 function = 2 // SHA-256
29 sha512 function = 3 // SHA-512
30 sha3_224 function = 32 // SHA3-224
31 sha3_256 function = 33 // SHA3-256
32 sha3_384 function = 34 // SHA3-384
33 sha3_512 function = 35 // SHA3-512
34 shake128 function = 36 // SHAKE-128
35 shake256 function = 37 // SHAKE-256
36
37 // KLMD function codes
38 ghash function = 65 // GHASH
39 )
40
41 const (
42 // KDSA function codes
43 ecdsaVerifyP256 function = 1 // NIST P256
44 ecdsaVerifyP384 function = 2 // NIST P384
45 ecdsaVerifyP521 function = 3 // NIST P521
46 ecdsaSignP256 function = 9 // NIST P256
47 ecdsaSignP384 function = 10 // NIST P384
48 ecdsaSignP521 function = 11 // NIST P521
49 eddsaVerifyEd25519 function = 32 // Curve25519
50 eddsaVerifyEd448 function = 36 // Curve448
51 eddsaSignEd25519 function = 40 // Curve25519
52 eddsaSignEd448 function = 44 // Curve448
53 )
54
55 // queryResult contains the result of a Query function
56 // call. Bits are numbered in big endian order so the
57 // leftmost bit (the MSB) is at index 0.
58 type queryResult struct {
59 bits [2]uint64
60 }
61
62 // Has reports whether the given functions are present.
63 func (q *queryResult) Has(fns ...function) bool {
64 if len(fns) == 0 {
65 panic("no function codes provided")
66 }
67 for _, f := range fns {
68 if !bitIsSet(q.bits[:], uint(f)) {
69 return false
70 }
71 }
72 return true
73 }
74
75 // facility is a bit index for the named facility.
76 type facility uint8
77
78 const (
79 // mandatory facilities
80 zarch facility = 1 // z architecture mode is active
81 stflef facility = 7 // store-facility-list-extended
82 ldisp facility = 18 // long-displacement
83 eimm facility = 21 // extended-immediate
84
85 // miscellaneous facilities
86 dfp facility = 42 // decimal-floating-point
87 etf3eh facility = 30 // extended-translation 3 enhancement
88
89 // cryptography facilities
90 msa facility = 17 // message-security-assist
91 msa3 facility = 76 // message-security-assist extension 3
92 msa4 facility = 77 // message-security-assist extension 4
93 msa5 facility = 57 // message-security-assist extension 5
94 msa8 facility = 146 // message-security-assist extension 8
95 msa9 facility = 155 // message-security-assist extension 9
96
97 // vector facilities
98 vxe facility = 135 // vector-enhancements 1
99
100 // Note: vx requires kernel support
101 // and so must be fetched from HWCAP.
102
103 hwcap_VX = 1 << 11 // vector facility
104 )
105
106 // facilityList contains the result of an STFLE call.
107 // Bits are numbered in big endian order so the
108 // leftmost bit (the MSB) is at index 0.
109 type facilityList struct {
110 bits [4]uint64
111 }
112
113 // Has reports whether the given facilities are present.
114 func (s *facilityList) Has(fs ...facility) bool {
115 if len(fs) == 0 {
116 panic("no facility bits provided")
117 }
118 for _, f := range fs {
119 if !bitIsSet(s.bits[:], uint(f)) {
120 return false
121 }
122 }
123 return true
124 }
125
126 // The following feature detection functions are defined in cpu_s390x.s.
127 // They are likely to be expensive to call so the results should be cached.
128 func stfle() facilityList
129 func kmQuery() queryResult
130 func kmcQuery() queryResult
131 func kmctrQuery() queryResult
132 func kmaQuery() queryResult
133 func kimdQuery() queryResult
134 func klmdQuery() queryResult
135 func kdsaQuery() queryResult
136
137 func doinit() {
138 options = []option{
139 {Name: "zarch", Feature: &S390X.HasZARCH},
140 {Name: "stfle", Feature: &S390X.HasSTFLE},
141 {Name: "ldisp", Feature: &S390X.HasLDISP},
142 {Name: "msa", Feature: &S390X.HasMSA},
143 {Name: "eimm", Feature: &S390X.HasEIMM},
144 {Name: "dfp", Feature: &S390X.HasDFP},
145 {Name: "etf3eh", Feature: &S390X.HasETF3EH},
146 {Name: "vx", Feature: &S390X.HasVX},
147 {Name: "vxe", Feature: &S390X.HasVXE},
148 {Name: "kdsa", Feature: &S390X.HasKDSA},
149 }
150
151 aes := []function{aes128, aes192, aes256}
152 facilities := stfle()
153
154 S390X.HasZARCH = facilities.Has(zarch)
155 S390X.HasSTFLE = facilities.Has(stflef)
156 S390X.HasLDISP = facilities.Has(ldisp)
157 S390X.HasEIMM = facilities.Has(eimm)
158 S390X.HasDFP = facilities.Has(dfp)
159 S390X.HasETF3EH = facilities.Has(etf3eh)
160 S390X.HasMSA = facilities.Has(msa)
161
162 if S390X.HasMSA {
163 // cipher message
164 km, kmc := kmQuery(), kmcQuery()
165 S390X.HasAES = km.Has(aes...)
166 S390X.HasAESCBC = kmc.Has(aes...)
167 if facilities.Has(msa4) {
168 kmctr := kmctrQuery()
169 S390X.HasAESCTR = kmctr.Has(aes...)
170 }
171 if facilities.Has(msa8) {
172 kma := kmaQuery()
173 S390X.HasAESGCM = kma.Has(aes...)
174 }
175
176 // compute message digest
177 kimd := kimdQuery() // intermediate (no padding)
178 klmd := klmdQuery() // last (padding)
179 S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1)
180 S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256)
181 S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512)
182 S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist
183 sha3 := []function{
184 sha3_224, sha3_256, sha3_384, sha3_512,
185 shake128, shake256,
186 }
187 S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...)
188 S390X.HasKDSA = facilities.Has(msa9) // elliptic curves
189 if S390X.HasKDSA {
190 kdsa := kdsaQuery()
191 S390X.HasECDSA = kdsa.Has(ecdsaVerifyP256, ecdsaSignP256, ecdsaVerifyP384, ecdsaSignP384, ecdsaVerifyP521, ecdsaSignP521)
192 S390X.HasEDDSA = kdsa.Has(eddsaVerifyEd25519, eddsaSignEd25519, eddsaVerifyEd448, eddsaSignEd448)
193 }
194 }
195
196 S390X.HasVX = isSet(HWCap, hwcap_VX)
197
198 if S390X.HasVX {
199 S390X.HasVXE = facilities.Has(vxe)
200 }
201 }
202
203 func isSet(hwc uint, value uint) bool {
204 return hwc&value != 0
205 }
206