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