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