Source file src/internal/cpu/cpu_s390x.go

     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  

View as plain text