// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package cpu const CacheLinePadSize = 256 var HWCap uint // bitIsSet reports whether the bit at index is set. The bit index // is in big endian order, so bit index 0 is the leftmost bit. func bitIsSet(bits []uint64, index uint) bool { return bits[index/64]&((1<<63)>>(index%64)) != 0 } // function is the function code for the named function. type function uint8 const ( // KM{,A,C,CTR} function codes aes128 function = 18 // AES-128 aes192 function = 19 // AES-192 aes256 function = 20 // AES-256 // K{I,L}MD function codes sha1 function = 1 // SHA-1 sha256 function = 2 // SHA-256 sha512 function = 3 // SHA-512 sha3_224 function = 32 // SHA3-224 sha3_256 function = 33 // SHA3-256 sha3_384 function = 34 // SHA3-384 sha3_512 function = 35 // SHA3-512 shake128 function = 36 // SHAKE-128 shake256 function = 37 // SHAKE-256 // KLMD function codes ghash function = 65 // GHASH ) const ( // KDSA function codes ecdsaVerifyP256 function = 1 // NIST P256 ecdsaVerifyP384 function = 2 // NIST P384 ecdsaVerifyP521 function = 3 // NIST P521 ecdsaSignP256 function = 9 // NIST P256 ecdsaSignP384 function = 10 // NIST P384 ecdsaSignP521 function = 11 // NIST P521 eddsaVerifyEd25519 function = 32 // Curve25519 eddsaVerifyEd448 function = 36 // Curve448 eddsaSignEd25519 function = 40 // Curve25519 eddsaSignEd448 function = 44 // Curve448 ) // queryResult contains the result of a Query function // call. Bits are numbered in big endian order so the // leftmost bit (the MSB) is at index 0. type queryResult struct { bits [2]uint64 } // Has reports whether the given functions are present. func (q *queryResult) Has(fns ...function) bool { if len(fns) == 0 { panic("no function codes provided") } for _, f := range fns { if !bitIsSet(q.bits[:], uint(f)) { return false } } return true } // facility is a bit index for the named facility. type facility uint8 const ( // mandatory facilities zarch facility = 1 // z architecture mode is active stflef facility = 7 // store-facility-list-extended ldisp facility = 18 // long-displacement eimm facility = 21 // extended-immediate // miscellaneous facilities dfp facility = 42 // decimal-floating-point etf3eh facility = 30 // extended-translation 3 enhancement // cryptography facilities msa facility = 17 // message-security-assist msa3 facility = 76 // message-security-assist extension 3 msa4 facility = 77 // message-security-assist extension 4 msa5 facility = 57 // message-security-assist extension 5 msa8 facility = 146 // message-security-assist extension 8 msa9 facility = 155 // message-security-assist extension 9 // vector facilities vxe facility = 135 // vector-enhancements 1 // Note: vx requires kernel support // and so must be fetched from HWCAP. hwcap_VX = 1 << 11 // vector facility ) // facilityList contains the result of an STFLE call. // Bits are numbered in big endian order so the // leftmost bit (the MSB) is at index 0. type facilityList struct { bits [4]uint64 } // Has reports whether the given facilities are present. func (s *facilityList) Has(fs ...facility) bool { if len(fs) == 0 { panic("no facility bits provided") } for _, f := range fs { if !bitIsSet(s.bits[:], uint(f)) { return false } } return true } // The following feature detection functions are defined in cpu_s390x.s. // They are likely to be expensive to call so the results should be cached. func stfle() facilityList func kmQuery() queryResult func kmcQuery() queryResult func kmctrQuery() queryResult func kmaQuery() queryResult func kimdQuery() queryResult func klmdQuery() queryResult func kdsaQuery() queryResult func doinit() { options = []option{ {Name: "zarch", Feature: &S390X.HasZARCH}, {Name: "stfle", Feature: &S390X.HasSTFLE}, {Name: "ldisp", Feature: &S390X.HasLDISP}, {Name: "msa", Feature: &S390X.HasMSA}, {Name: "eimm", Feature: &S390X.HasEIMM}, {Name: "dfp", Feature: &S390X.HasDFP}, {Name: "etf3eh", Feature: &S390X.HasETF3EH}, {Name: "vx", Feature: &S390X.HasVX}, {Name: "vxe", Feature: &S390X.HasVXE}, {Name: "kdsa", Feature: &S390X.HasKDSA}, } aes := []function{aes128, aes192, aes256} facilities := stfle() S390X.HasZARCH = facilities.Has(zarch) S390X.HasSTFLE = facilities.Has(stflef) S390X.HasLDISP = facilities.Has(ldisp) S390X.HasEIMM = facilities.Has(eimm) S390X.HasDFP = facilities.Has(dfp) S390X.HasETF3EH = facilities.Has(etf3eh) S390X.HasMSA = facilities.Has(msa) if S390X.HasMSA { // cipher message km, kmc := kmQuery(), kmcQuery() S390X.HasAES = km.Has(aes...) S390X.HasAESCBC = kmc.Has(aes...) if facilities.Has(msa4) { kmctr := kmctrQuery() S390X.HasAESCTR = kmctr.Has(aes...) } if facilities.Has(msa8) { kma := kmaQuery() S390X.HasAESGCM = kma.Has(aes...) } // compute message digest kimd := kimdQuery() // intermediate (no padding) klmd := klmdQuery() // last (padding) S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist sha3 := []function{ sha3_224, sha3_256, sha3_384, sha3_512, shake128, shake256, } S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) S390X.HasKDSA = facilities.Has(msa9) // elliptic curves if S390X.HasKDSA { kdsa := kdsaQuery() S390X.HasECDSA = kdsa.Has(ecdsaVerifyP256, ecdsaSignP256, ecdsaVerifyP384, ecdsaSignP384, ecdsaVerifyP521, ecdsaSignP521) S390X.HasEDDSA = kdsa.Has(eddsaVerifyEd25519, eddsaSignEd25519, eddsaVerifyEd448, eddsaSignEd448) } } S390X.HasVX = isSet(HWCap, hwcap_VX) if S390X.HasVX { S390X.HasVXE = facilities.Has(vxe) } } func isSet(hwc uint, value uint) bool { return hwc&value != 0 }