• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "crypt_utils.h"
17 #ifdef __x86_64__
18 
19 #include <cpuid.h>
20 #include "securec.h"
21 
22 
23 CpuInstrSupportState g_cpuState = {0};
24 
25 /* Obtain whether the CPU supports the SIMD instruction set through the cpuid instruction. */
GetCpuId(uint32_t eax,uint32_t ecx,uint32_t cpuId[CPU_ID_OUT_U32_CNT])26 void GetCpuId(uint32_t eax, uint32_t ecx, uint32_t cpuId[CPU_ID_OUT_U32_CNT])
27 {
28     uint32_t eaxOut, ebxOut, ecxOut, edxOut;
29 
30     __asm("cpuid": "=a"(eaxOut), "=b"(ebxOut), "=c"(ecxOut), "=d"(edxOut): "a"(eax), "c"(ecx):);
31 
32     cpuId[EAX_OUT_IDX] = eaxOut;
33     cpuId[EBX_OUT_IDX] = ebxOut;
34     cpuId[ECX_OUT_IDX] = ecxOut;
35     cpuId[EDX_OUT_IDX] = edxOut;
36 }
37 
38 /* Obtain whether the OS supports the SIMD instruction set by using the xgetbv instruction. */
GetExCtl(uint32_t ecx)39 static uint32_t GetExCtl(uint32_t ecx)
40 {
41     uint32_t ret = 0;
42 
43     __asm("xgetbv": "=a"(ret): "c"(ecx):);
44 
45     return ret;
46 }
47 
48 
IsSupportBMI1(void)49 bool IsSupportBMI1(void)
50 {
51     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_BMI;
52 }
53 
IsSupportMOVBE(void)54 bool IsSupportMOVBE(void)
55 {
56     return g_cpuState.code1Out[ECX_OUT_IDX] & bit_MOVBE;
57 }
58 
IsSupportBMI2(void)59 bool IsSupportBMI2(void)
60 {
61     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_BMI2;
62 }
63 
IsSupportADX(void)64 bool IsSupportADX(void)
65 {
66     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_ADX;
67 }
68 
IsSupportSSE(void)69 bool IsSupportSSE(void)
70 {
71     return g_cpuState.code1Out[EDX_OUT_IDX] & bit_SSE;
72 }
73 
IsSupportSSE2(void)74 bool IsSupportSSE2(void)
75 {
76     return g_cpuState.code1Out[EDX_OUT_IDX] & bit_SSE2;
77 }
78 
IsSupportAVX(void)79 bool IsSupportAVX(void)
80 {
81     return g_cpuState.code1Out[ECX_OUT_IDX] & bit_AVX;
82 }
83 
IsSupportAES(void)84 bool IsSupportAES(void)
85 {
86     return g_cpuState.code1Out[ECX_OUT_IDX] & bit_AES;
87 }
88 
IsSupportSSE3(void)89 bool IsSupportSSE3(void)
90 {
91     return g_cpuState.code1Out[ECX_OUT_IDX] & bit_SSE3;
92 }
93 
IsSupportAVX2(void)94 bool IsSupportAVX2(void)
95 {
96     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_AVX2;
97 }
98 
IsSupportAVX512F(void)99 bool IsSupportAVX512F(void)
100 {
101     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_AVX512F;
102 }
103 
IsSupportAVX512DQ(void)104 bool IsSupportAVX512DQ(void)
105 {
106     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_AVX512DQ;
107 }
108 
IsSupportAVX512VL(void)109 bool IsSupportAVX512VL(void)
110 {
111     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_AVX512VL;
112 }
113 
IsSupportAVX512BW(void)114 bool IsSupportAVX512BW(void)
115 {
116     return g_cpuState.code7Out[EBX_OUT_IDX] & bit_AVX512BW;
117 }
118 
IsSupportXSAVE(void)119 bool IsSupportXSAVE(void)
120 {
121     return g_cpuState.code1Out[ECX_OUT_IDX] & bit_XSAVE;
122 }
123 
IsSupportOSXSAVE(void)124 bool IsSupportOSXSAVE(void)
125 {
126     return g_cpuState.code1Out[ECX_OUT_IDX] & bit_OSXSAVE;
127 }
128 
IsOSSupportAVX(void)129 bool IsOSSupportAVX(void)
130 {
131     return g_cpuState.osSupportAVX;
132 }
133 
IsOSSupportAVX512(void)134 bool IsOSSupportAVX512(void)
135 {
136     return g_cpuState.osSupportAVX512;
137 }
138 
139 
140 /* ARM */
141 #elif defined(__arm__) || defined (__arm) || defined(__aarch64__)
142 #include "crypt_arm.h"
143 uint32_t g_cryptArmCpuInfo = 0;
144 
145 #if defined(HITLS_CRYPTO_NO_AUXVAL)
146 #include <setjmp.h>
147 #include <signal.h>
148 
149 static jmp_buf g_jump_buffer;
150 
signal_handler(int sig)151 void signal_handler(int sig)
152 {
153     (void)sig;
154     longjmp(g_jump_buffer, 1);
155 }
156 
getarmcap(void)157 void getarmcap(void)
158 {
159     struct sigaction sa, old_sa;
160 
161     sa.sa_handler = signal_handler;
162     sigemptyset(&sa.sa_mask);
163     sa.sa_flags = 0;
164     sigaction(SIGILL, &sa, &old_sa);
165 
166     // NEON
167     if (setjmp(g_jump_buffer) == 0) {
168 #if defined(__ARM_NEON) || defined(__aarch64__)
169         __asm__ volatile ("ORR v0.16b, v0.16b, v0.16b" : : : "v0");
170         g_cryptArmCpuInfo |= CRYPT_ARM_NEON;
171 #endif
172 #if defined(__aarch64__)
173         // AES
174         if (setjmp(g_jump_buffer) == 0) {
175             __asm__ volatile ("aese v0.16b, v0.16b" : : : "v0");
176             g_cryptArmCpuInfo |= CRYPT_ARM_AES;
177         }
178         // PMULL
179         if (setjmp(g_jump_buffer) == 0) {
180             __asm__ volatile ("pmull v0.1q, v0.1d, v0.1d" : : : "v0");
181             g_cryptArmCpuInfo |= CRYPT_ARM_PMULL;
182         }
183         // SHA1
184         if (setjmp(g_jump_buffer) == 0) {
185             __asm__ volatile ("sha1h s0, s0" : : : "s0");
186             g_cryptArmCpuInfo |= CRYPT_ARM_SHA1;
187         }
188         // SHA256
189         if (setjmp(g_jump_buffer) == 0) {
190             __asm__ volatile ("sha256su0 v0.4s, v0.4s" : : : "v0");
191             g_cryptArmCpuInfo |= CRYPT_ARM_SHA256;
192         }
193         // SHA512
194         if (setjmp(g_jump_buffer) == 0) {
195             __asm__ volatile ("sha512su0 v0.2d, v0.2d" : : : "v0");
196             g_cryptArmCpuInfo |= CRYPT_ARM_SHA512;
197         }
198 #endif
199     }
200 
201     sigaction(SIGILL, &old_sa, NULL);
202 }
203 #else
204 
205 #include <sys/auxv.h>
206 
207 static bool g_supportNEON = {0};
208 
IsSupportAES(void)209 bool IsSupportAES(void)
210 {
211     return g_cryptArmCpuInfo & CRYPT_ARM_AES;
212 }
213 
IsSupportPMULL(void)214 bool IsSupportPMULL(void)
215 {
216     return g_cryptArmCpuInfo & CRYPT_ARM_PMULL;
217 }
218 
IsSupportSHA1(void)219 bool IsSupportSHA1(void)
220 {
221     return g_cryptArmCpuInfo & CRYPT_ARM_SHA1;
222 }
223 
IsSupportSHA256(void)224 bool IsSupportSHA256(void)
225 {
226     return g_cryptArmCpuInfo & CRYPT_ARM_SHA256;
227 }
228 
IsSupportNEON(void)229 bool IsSupportNEON(void)
230 {
231     return g_supportNEON;
232 }
233 
234 #if defined(__aarch64__)
IsSupportSHA512(void)235 bool IsSupportSHA512(void)
236 {
237     return g_cryptArmCpuInfo & CRYPT_ARM_SHA512;
238 }
239 #endif // __aarch64__
240 
241 #endif // HITLS_CRYPTO_NO_AUXVAL
242 #endif // x86_64 || __arm__ || __arm || __aarch64__
243 
GetCpuInstrSupportState(void)244 void GetCpuInstrSupportState(void)
245 {
246 #ifdef __x86_64__
247     uint32_t cpuId[CPU_ID_OUT_U32_CNT];
248     uint64_t xcr0;
249 
250     /* SIMD CPU support */
251     GetCpuId(0x1, 0, cpuId);
252     (void)memcpy_s(g_cpuState.code1Out, CPU_ID_OUT_U32_CNT * sizeof(uint32_t), cpuId,
253         CPU_ID_OUT_U32_CNT * sizeof(uint32_t));
254 
255     GetCpuId(0x7, 0, cpuId);
256     (void)memcpy_s(g_cpuState.code7Out, CPU_ID_OUT_U32_CNT * sizeof(uint32_t), cpuId,
257         CPU_ID_OUT_U32_CNT * sizeof(uint32_t));
258 
259     /* SIMD OS support */
260     if (IsSupportXSAVE() && IsSupportOSXSAVE()) {
261         xcr0 = GetExCtl(0);
262         bool sse = xcr0 & XCR0_BIT_SSE;
263         bool avx = xcr0 & XCR0_BIT_AVX;
264         g_cpuState.osSupportAVX = sse && avx;
265         bool opmask = xcr0 & XCR0_BIT_OPMASK;
266         bool zmmLow = xcr0 & XCR0_BIT_ZMM_LOW;
267         bool zmmHigh = xcr0 & XCR0_BIT_ZMM_HIGH;
268         g_cpuState.osSupportAVX512 = opmask && zmmLow && zmmHigh;
269     }
270 #elif defined(__arm__) || defined (__arm) || defined(__aarch64__)
271 #if defined(HITLS_CRYPTO_NO_AUXVAL)
272     getarmcap();
273 #else // HITLS_CRYPTO_NO_AUXVAL
274     g_supportNEON = getauxval(CRYPT_CAP) & CRYPT_ARM_NEON;
275     if (g_supportNEON) {
276         g_cryptArmCpuInfo = (uint32_t)getauxval(CRYPT_CE);
277     }
278 #endif // HITLS_CRYPTO_NO_AUXVAL
279 #endif // defined(__arm__) || defined (__arm) || defined(__aarch64__)
280 }