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