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