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  }