github.com/Andyfoo/golang/x/sys@v0.0.0-20190901054642-57c1bf301704/cpu/cpu_linux_s390x.go (about)

     1  // Copyright 2019 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 cacheLineSize = 256
     8  
     9  const (
    10  	// bit mask values from /usr/include/bits/hwcap.h
    11  	hwcap_ZARCH  = 2
    12  	hwcap_STFLE  = 4
    13  	hwcap_MSA    = 8
    14  	hwcap_LDISP  = 16
    15  	hwcap_EIMM   = 32
    16  	hwcap_DFP    = 64
    17  	hwcap_ETF3EH = 256
    18  	hwcap_VX     = 2048
    19  	hwcap_VXE    = 8192
    20  )
    21  
    22  // bitIsSet reports whether the bit at index is set. The bit index
    23  // is in big endian order, so bit index 0 is the leftmost bit.
    24  func bitIsSet(bits []uint64, index uint) bool {
    25  	return bits[index/64]&((1<<63)>>(index%64)) != 0
    26  }
    27  
    28  // function is the code for the named cryptographic function.
    29  type function uint8
    30  
    31  const (
    32  	// KM{,A,C,CTR} function codes
    33  	aes128 function = 18 // AES-128
    34  	aes192 function = 19 // AES-192
    35  	aes256 function = 20 // AES-256
    36  
    37  	// K{I,L}MD function codes
    38  	sha1     function = 1  // SHA-1
    39  	sha256   function = 2  // SHA-256
    40  	sha512   function = 3  // SHA-512
    41  	sha3_224 function = 32 // SHA3-224
    42  	sha3_256 function = 33 // SHA3-256
    43  	sha3_384 function = 34 // SHA3-384
    44  	sha3_512 function = 35 // SHA3-512
    45  	shake128 function = 36 // SHAKE-128
    46  	shake256 function = 37 // SHAKE-256
    47  
    48  	// KLMD function codes
    49  	ghash function = 65 // GHASH
    50  )
    51  
    52  // queryResult contains the result of a Query function
    53  // call. Bits are numbered in big endian order so the
    54  // leftmost bit (the MSB) is at index 0.
    55  type queryResult struct {
    56  	bits [2]uint64
    57  }
    58  
    59  // Has reports whether the given functions are present.
    60  func (q *queryResult) Has(fns ...function) bool {
    61  	if len(fns) == 0 {
    62  		panic("no function codes provided")
    63  	}
    64  	for _, f := range fns {
    65  		if !bitIsSet(q.bits[:], uint(f)) {
    66  			return false
    67  		}
    68  	}
    69  	return true
    70  }
    71  
    72  // facility is a bit index for the named facility.
    73  type facility uint8
    74  
    75  const (
    76  	// cryptography facilities
    77  	msa4 facility = 77  // message-security-assist extension 4
    78  	msa8 facility = 146 // message-security-assist extension 8
    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  func doinit() {
   102  	// test HWCAP bit vector
   103  	has := func(featureMask uint) bool {
   104  		return hwCap&featureMask == featureMask
   105  	}
   106  
   107  	// mandatory
   108  	S390X.HasZARCH = has(hwcap_ZARCH)
   109  
   110  	// optional
   111  	S390X.HasSTFLE = has(hwcap_STFLE)
   112  	S390X.HasLDISP = has(hwcap_LDISP)
   113  	S390X.HasEIMM = has(hwcap_EIMM)
   114  	S390X.HasETF3EH = has(hwcap_ETF3EH)
   115  	S390X.HasDFP = has(hwcap_DFP)
   116  	S390X.HasMSA = has(hwcap_MSA)
   117  	S390X.HasVX = has(hwcap_VX)
   118  	if S390X.HasVX {
   119  		S390X.HasVXE = has(hwcap_VXE)
   120  	}
   121  
   122  	// We need implementations of stfle, km and so on
   123  	// to detect cryptographic features.
   124  	if !haveAsmFunctions() {
   125  		return
   126  	}
   127  
   128  	// optional cryptographic functions
   129  	if S390X.HasMSA {
   130  		aes := []function{aes128, aes192, aes256}
   131  
   132  		// cipher message
   133  		km, kmc := kmQuery(), kmcQuery()
   134  		S390X.HasAES = km.Has(aes...)
   135  		S390X.HasAESCBC = kmc.Has(aes...)
   136  		if S390X.HasSTFLE {
   137  			facilities := stfle()
   138  			if facilities.Has(msa4) {
   139  				kmctr := kmctrQuery()
   140  				S390X.HasAESCTR = kmctr.Has(aes...)
   141  			}
   142  			if facilities.Has(msa8) {
   143  				kma := kmaQuery()
   144  				S390X.HasAESGCM = kma.Has(aes...)
   145  			}
   146  		}
   147  
   148  		// compute message digest
   149  		kimd := kimdQuery() // intermediate (no padding)
   150  		klmd := klmdQuery() // last (padding)
   151  		S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1)
   152  		S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256)
   153  		S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512)
   154  		S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist
   155  		sha3 := []function{
   156  			sha3_224, sha3_256, sha3_384, sha3_512,
   157  			shake128, shake256,
   158  		}
   159  		S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...)
   160  	}
   161  }