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