Polina Osadcha | 0cf7623 | 2020-07-09 09:47:37 +0300 | [diff] [blame] | 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 | |
| 5 | package cpu |
| 6 | |
| 7 | const cacheLineSize = 256 |
| 8 | |
| 9 | func initOptions() { |
| 10 | options = []option{ |
Bill O'Farrell | 708e7fb | 2020-10-14 19:41:11 -0400 | [diff] [blame] | 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}, |
Polina Osadcha | 0cf7623 | 2020-07-09 09:47:37 +0300 | [diff] [blame] | 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 | } |
Bill O'Farrell | 708e7fb | 2020-10-14 19:41:11 -0400 | [diff] [blame] | 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. |
| 34 | func 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. |
| 39 | type facility uint8 |
| 40 | |
| 41 | const ( |
| 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. |
| 69 | type facilityList struct { |
| 70 | bits [4]uint64 |
| 71 | } |
| 72 | |
| 73 | // Has reports whether the given facilities are present. |
| 74 | func (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. |
| 87 | type function uint8 |
| 88 | |
| 89 | const ( |
| 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. |
| 113 | type queryResult struct { |
| 114 | bits [2]uint64 |
| 115 | } |
| 116 | |
| 117 | // Has reports whether the given functions are present. |
| 118 | func (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 | |
| 130 | func 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 | } |