github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/cpu/cpu_s390x.go (about)

     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  // bitIsSet reports whether the bit at index is set. The bit index
    10  // is in big endian order, so bit index 0 is the leftmost bit.
    11  func bitIsSet(bits []uint64, index uint) bool {
    12  	return bits[index/64]&((1<<63)>>(index%64)) != 0
    13  }
    14  
    15  // function is the function code for the named function.
    16  type function uint8
    17  
    18  const (
    19  	// KM{,A,C,CTR} function codes
    20  	aes128 function = 18 // AES-128
    21  	aes192 function = 19 // AES-192
    22  	aes256 function = 20 // AES-256
    23  
    24  	// K{I,L}MD function codes
    25  	sha1   function = 1 // SHA-1
    26  	sha256 function = 2 // SHA-256
    27  	sha512 function = 3 // SHA-512
    28  
    29  	// KLMD function codes
    30  	ghash function = 65 // GHASH
    31  )
    32  
    33  // queryResult contains the result of a Query function
    34  // call. Bits are numbered in big endian order so the
    35  // leftmost bit (the MSB) is at index 0.
    36  type queryResult struct {
    37  	bits [2]uint64
    38  }
    39  
    40  // Has reports whether the given functions are present.
    41  func (q *queryResult) Has(fns ...function) bool {
    42  	if len(fns) == 0 {
    43  		panic("no function codes provided")
    44  	}
    45  	for _, f := range fns {
    46  		if !bitIsSet(q.bits[:], uint(f)) {
    47  			return false
    48  		}
    49  	}
    50  	return true
    51  }
    52  
    53  // facility is a bit index for the named facility.
    54  type facility uint8
    55  
    56  const (
    57  	// mandatory facilities
    58  	zarch  facility = 1  // z architecture mode is active
    59  	stflef facility = 7  // store-facility-list-extended
    60  	ldisp  facility = 18 // long-displacement
    61  	eimm   facility = 21 // extended-immediate
    62  
    63  	// miscellaneous facilities
    64  	dfp    facility = 42 // decimal-floating-point
    65  	etf3eh facility = 30 // extended-translation 3 enhancement
    66  
    67  	// cryptography facilities
    68  	msa  facility = 17  // message-security-assist
    69  	msa3 facility = 76  // message-security-assist extension 3
    70  	msa4 facility = 77  // message-security-assist extension 4
    71  	msa5 facility = 57  // message-security-assist extension 5
    72  	msa8 facility = 146 // message-security-assist extension 8
    73  
    74  	// vector facilities
    75  	ve1 facility = 135 // vector-enhancements 1
    76  
    77  	// Note: vx and highgprs are excluded because they require
    78  	// kernel support and so must be fetched from HWCAP.
    79  )
    80  
    81  // facilityList contains the result of an STFLE call.
    82  // Bits are numbered in big endian order so the
    83  // leftmost bit (the MSB) is at index 0.
    84  type facilityList struct {
    85  	bits [4]uint64
    86  }
    87  
    88  // Has reports whether the given facilities are present.
    89  func (s *facilityList) Has(fs ...facility) bool {
    90  	if len(fs) == 0 {
    91  		panic("no facility bits provided")
    92  	}
    93  	for _, f := range fs {
    94  		if !bitIsSet(s.bits[:], uint(f)) {
    95  			return false
    96  		}
    97  	}
    98  	return true
    99  }
   100  
   101  // The following feature detection functions are defined in cpu_s390x.s.
   102  // They are likely to be expensive to call so the results should be cached.
   103  func stfle() facilityList
   104  func kmQuery() queryResult
   105  func kmcQuery() queryResult
   106  func kmctrQuery() queryResult
   107  func kmaQuery() queryResult
   108  func kimdQuery() queryResult
   109  func klmdQuery() queryResult
   110  
   111  func doinit() {
   112  	options = []option{
   113  		{Name: "zarch", Feature: &S390X.HasZArch},
   114  		{Name: "stfle", Feature: &S390X.HasSTFLE},
   115  		{Name: "ldisp", Feature: &S390X.HasLDisp},
   116  		{Name: "msa", Feature: &S390X.HasMSA},
   117  		{Name: "eimm", Feature: &S390X.HasEImm},
   118  		{Name: "dfp", Feature: &S390X.HasDFP},
   119  		{Name: "etf3eh", Feature: &S390X.HasETF3Enhanced},
   120  		{Name: "vx", Feature: &S390X.HasVX},
   121  		{Name: "ve1", Feature: &S390X.HasVE1},
   122  	}
   123  
   124  	aes := []function{aes128, aes192, aes256}
   125  	facilities := stfle()
   126  
   127  	S390X.HasZArch = facilities.Has(zarch)
   128  	S390X.HasSTFLE = facilities.Has(stflef)
   129  	S390X.HasLDisp = facilities.Has(ldisp)
   130  	S390X.HasEImm = facilities.Has(eimm)
   131  	S390X.HasDFP = facilities.Has(dfp)
   132  	S390X.HasETF3Enhanced = facilities.Has(etf3eh)
   133  	S390X.HasMSA = facilities.Has(msa)
   134  
   135  	if S390X.HasMSA {
   136  		// cipher message
   137  		km, kmc := kmQuery(), kmcQuery()
   138  		S390X.HasAES = km.Has(aes...)
   139  		S390X.HasAESCBC = kmc.Has(aes...)
   140  		if facilities.Has(msa4) {
   141  			kmctr := kmctrQuery()
   142  			S390X.HasAESCTR = kmctr.Has(aes...)
   143  		}
   144  		if facilities.Has(msa8) {
   145  			kma := kmaQuery()
   146  			S390X.HasAESGCM = kma.Has(aes...)
   147  		}
   148  
   149  		// compute message digest
   150  		kimd := kimdQuery() // intermediate (no padding)
   151  		klmd := klmdQuery() // last (padding)
   152  		S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1)
   153  		S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256)
   154  		S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512)
   155  		S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist
   156  	}
   157  	if S390X.HasVX {
   158  		S390X.HasVE1 = facilities.Has(ve1)
   159  	}
   160  }