1fd86ae68SMitchell Horne /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3fd86ae68SMitchell Horne *
4fd86ae68SMitchell Horne * Copyright (c) 2020 Netflix, Inc
5fd86ae68SMitchell Horne *
6fd86ae68SMitchell Horne * Redistribution and use in source and binary forms, with or without
7fd86ae68SMitchell Horne * modification, are permitted provided that the following conditions
8fd86ae68SMitchell Horne * are met:
9fd86ae68SMitchell Horne * 1. Redistributions of source code must retain the above copyright
10fd86ae68SMitchell Horne * notice, this list of conditions and the following disclaimer,
11fd86ae68SMitchell Horne * without modification.
12fd86ae68SMitchell Horne * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13fd86ae68SMitchell Horne * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14fd86ae68SMitchell Horne * redistribution must be conditioned upon including a substantially
15fd86ae68SMitchell Horne * similar Disclaimer requirement for further binary redistribution.
16fd86ae68SMitchell Horne *
17fd86ae68SMitchell Horne * NO WARRANTY
18fd86ae68SMitchell Horne * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19fd86ae68SMitchell Horne * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20fd86ae68SMitchell Horne * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21fd86ae68SMitchell Horne * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22fd86ae68SMitchell Horne * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23fd86ae68SMitchell Horne * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24fd86ae68SMitchell Horne * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25fd86ae68SMitchell Horne * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26fd86ae68SMitchell Horne * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27fd86ae68SMitchell Horne * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28fd86ae68SMitchell Horne * THE POSSIBILITY OF SUCH DAMAGES.
29fd86ae68SMitchell Horne */
30fd86ae68SMitchell Horne
31fd86ae68SMitchell Horne #include <sys/types.h>
32fd86ae68SMitchell Horne #include <sys/systm.h>
33fd86ae68SMitchell Horne
34fd86ae68SMitchell Horne #include <machine/cpufunc.h>
35fd86ae68SMitchell Horne #include <machine/md_var.h>
36fd86ae68SMitchell Horne #include <x86/cputypes.h>
37fd86ae68SMitchell Horne #include <x86/specialreg.h>
38fd86ae68SMitchell Horne
39fd86ae68SMitchell Horne #include <crypto/openssl/ossl.h>
409a3444d9SMark Johnston #include <crypto/openssl/ossl_aes_gcm.h>
41197ff4c3SKornel Duleba #include <crypto/openssl/ossl_cipher.h>
42fd86ae68SMitchell Horne
43fd86ae68SMitchell Horne /*
44fd86ae68SMitchell Horne * See OPENSSL_ia32cap(3).
45fd86ae68SMitchell Horne *
46fd86ae68SMitchell Horne * [0] = cpu_feature but with a few custom bits
47fd86ae68SMitchell Horne * [1] = cpu_feature2 but with AMD XOP in bit 11
48fd86ae68SMitchell Horne * [2] = cpu_stdext_feature
499ad8dc72SMark Johnston * [3] = cpu_stdext_feature2
50fd86ae68SMitchell Horne */
51fd86ae68SMitchell Horne unsigned int OPENSSL_ia32cap_P[4];
52197ff4c3SKornel Duleba #define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
53197ff4c3SKornel Duleba
54197ff4c3SKornel Duleba ossl_cipher_setkey_t aesni_set_encrypt_key;
55197ff4c3SKornel Duleba ossl_cipher_setkey_t aesni_set_decrypt_key;
56fd86ae68SMitchell Horne
579a3444d9SMark Johnston #ifdef __amd64__
589a3444d9SMark Johnston int ossl_vaes_vpclmulqdq_capable(void);
59*9b1d8728SMark Johnston ossl_cipher_setkey_t ossl_aes_gcm_setkey_aesni;
609a3444d9SMark Johnston ossl_cipher_setkey_t ossl_aes_gcm_setkey_avx512;
619a3444d9SMark Johnston #endif
629a3444d9SMark Johnston
63fd86ae68SMitchell Horne void
ossl_cpuid(struct ossl_softc * sc)64197ff4c3SKornel Duleba ossl_cpuid(struct ossl_softc *sc)
65fd86ae68SMitchell Horne {
66fd86ae68SMitchell Horne uint64_t xcr0;
67fd86ae68SMitchell Horne u_int regs[4];
68fd86ae68SMitchell Horne u_int max_cores;
69fd86ae68SMitchell Horne
70fd86ae68SMitchell Horne /* Derived from OpenSSL_ia32_cpuid. */
71fd86ae68SMitchell Horne
72fd86ae68SMitchell Horne OPENSSL_ia32cap_P[0] = cpu_feature & ~(CPUID_B20 | CPUID_IA64);
73fd86ae68SMitchell Horne if (cpu_vendor_id == CPU_VENDOR_INTEL) {
74fd86ae68SMitchell Horne OPENSSL_ia32cap_P[0] |= CPUID_IA64;
75fd86ae68SMitchell Horne if ((cpu_id & 0xf00) != 0xf00)
76fd86ae68SMitchell Horne OPENSSL_ia32cap_P[0] |= CPUID_B20;
77fd86ae68SMitchell Horne }
78fd86ae68SMitchell Horne
79fd86ae68SMitchell Horne /* Only leave CPUID_HTT on if HTT is present. */
80fd86ae68SMitchell Horne if (cpu_vendor_id == CPU_VENDOR_AMD && cpu_exthigh >= 0x80000008) {
81fd86ae68SMitchell Horne max_cores = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
82fd86ae68SMitchell Horne if (cpu_feature & CPUID_HTT) {
83fd86ae68SMitchell Horne if ((cpu_procinfo & CPUID_HTT_CORES) >> 16 <= max_cores)
84fd86ae68SMitchell Horne OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
85fd86ae68SMitchell Horne }
86fd86ae68SMitchell Horne } else {
87fd86ae68SMitchell Horne if (cpu_high >= 4) {
88fd86ae68SMitchell Horne cpuid_count(4, 0, regs);
89fd86ae68SMitchell Horne max_cores = (regs[0] >> 26) & 0xfff;
90fd86ae68SMitchell Horne } else
91fd86ae68SMitchell Horne max_cores = -1;
92fd86ae68SMitchell Horne }
93fd86ae68SMitchell Horne if (max_cores == 0)
94fd86ae68SMitchell Horne OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
95fd86ae68SMitchell Horne else if ((cpu_procinfo & CPUID_HTT_CORES) >> 16 == 0)
96fd86ae68SMitchell Horne OPENSSL_ia32cap_P[0] &= ~CPUID_HTT;
97fd86ae68SMitchell Horne
98fd86ae68SMitchell Horne OPENSSL_ia32cap_P[1] = cpu_feature2 & ~AMDID2_XOP;
99fd86ae68SMitchell Horne if (cpu_vendor_id == CPU_VENDOR_AMD)
100fd86ae68SMitchell Horne OPENSSL_ia32cap_P[1] |= amd_feature2 & AMDID2_XOP;
101fd86ae68SMitchell Horne
102fd86ae68SMitchell Horne OPENSSL_ia32cap_P[2] = cpu_stdext_feature;
103fd86ae68SMitchell Horne if ((OPENSSL_ia32cap_P[1] & CPUID2_XSAVE) == 0)
104fd86ae68SMitchell Horne OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512F |
105fd86ae68SMitchell Horne CPUID_STDEXT_AVX512DQ);
106fd86ae68SMitchell Horne
107fd86ae68SMitchell Horne /* Disable AVX512F on Skylake-X. */
108fd86ae68SMitchell Horne if ((cpu_id & 0x0fff0ff0) == 0x00050650)
109fd86ae68SMitchell Horne OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512F);
110fd86ae68SMitchell Horne
111fd86ae68SMitchell Horne if (cpu_feature2 & CPUID2_OSXSAVE)
112fd86ae68SMitchell Horne xcr0 = rxcr(0);
113fd86ae68SMitchell Horne else
114fd86ae68SMitchell Horne xcr0 = 0;
115fd86ae68SMitchell Horne
116fd86ae68SMitchell Horne if ((xcr0 & (XFEATURE_AVX512 | XFEATURE_AVX)) !=
117fd86ae68SMitchell Horne (XFEATURE_AVX512 | XFEATURE_AVX))
118fd86ae68SMitchell Horne OPENSSL_ia32cap_P[2] &= ~(CPUID_STDEXT_AVX512VL |
119fd86ae68SMitchell Horne CPUID_STDEXT_AVX512BW | CPUID_STDEXT_AVX512IFMA |
120fd86ae68SMitchell Horne CPUID_STDEXT_AVX512F);
121fd86ae68SMitchell Horne if ((xcr0 & XFEATURE_AVX) != XFEATURE_AVX) {
122fd86ae68SMitchell Horne OPENSSL_ia32cap_P[1] &= ~(CPUID2_AVX | AMDID2_XOP | CPUID2_FMA);
123fd86ae68SMitchell Horne OPENSSL_ia32cap_P[2] &= ~CPUID_STDEXT_AVX2;
124fd86ae68SMitchell Horne }
1259ad8dc72SMark Johnston OPENSSL_ia32cap_P[3] = cpu_stdext_feature2;
126197ff4c3SKornel Duleba
1279a3444d9SMark Johnston if (!AESNI_CAPABLE)
128197ff4c3SKornel Duleba return;
1299a3444d9SMark Johnston
130197ff4c3SKornel Duleba sc->has_aes = true;
131197ff4c3SKornel Duleba ossl_cipher_aes_cbc.set_encrypt_key = aesni_set_encrypt_key;
132197ff4c3SKornel Duleba ossl_cipher_aes_cbc.set_decrypt_key = aesni_set_decrypt_key;
1339a3444d9SMark Johnston
1349a3444d9SMark Johnston #ifdef __amd64__
1359a3444d9SMark Johnston if (ossl_vaes_vpclmulqdq_capable()) {
1369a3444d9SMark Johnston ossl_cipher_aes_gcm.set_encrypt_key =
1379a3444d9SMark Johnston ossl_aes_gcm_setkey_avx512;
1389a3444d9SMark Johnston ossl_cipher_aes_gcm.set_decrypt_key =
1399a3444d9SMark Johnston ossl_aes_gcm_setkey_avx512;
1409a3444d9SMark Johnston sc->has_aes_gcm = true;
141*9b1d8728SMark Johnston } else if ((cpu_feature2 &
142*9b1d8728SMark Johnston (CPUID2_AVX | CPUID2_PCLMULQDQ | CPUID2_MOVBE)) ==
143*9b1d8728SMark Johnston (CPUID2_AVX | CPUID2_PCLMULQDQ | CPUID2_MOVBE)) {
144*9b1d8728SMark Johnston ossl_cipher_aes_gcm.set_encrypt_key = ossl_aes_gcm_setkey_aesni;
145*9b1d8728SMark Johnston ossl_cipher_aes_gcm.set_decrypt_key = ossl_aes_gcm_setkey_aesni;
146*9b1d8728SMark Johnston sc->has_aes_gcm = true;
1479a3444d9SMark Johnston } else {
1489a3444d9SMark Johnston sc->has_aes_gcm = false;
1499a3444d9SMark Johnston }
1509a3444d9SMark Johnston #else
1519a3444d9SMark Johnston sc->has_aes_gcm = false;
1529a3444d9SMark Johnston #endif
153fd86ae68SMitchell Horne }
154