Coverage Report

Created: 2026-07-22 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-fastmath/wolfssl/wolfcrypt/cpuid.h
Line
Count
Source
1
/* cpuid.h
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
23
24
#ifndef WOLF_CRYPT_CPUID_H
25
#define WOLF_CRYPT_CPUID_H
26
27
28
#include <wolfssl/wolfcrypt/types.h>
29
30
31
#ifdef __cplusplus
32
    extern "C" {
33
#endif
34
35
#if (defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \
36
    defined(WOLFSSL_AESNI) || defined(WOLFSSL_SP_X86_64_ASM)) && \
37
    !defined(WOLFSSL_NO_ASM)
38
    #define HAVE_CPUID
39
    #define HAVE_CPUID_INTEL
40
#endif
41
#if (defined(WOLFSSL_AARCH64_BUILD) || (defined(__aarch64__) && \
42
     defined(WOLFSSL_ARMASM))) && !defined(WOLFSSL_NO_ASM)
43
    #define HAVE_CPUID
44
    #define HAVE_CPUID_AARCH64
45
#endif
46
#if defined(WOLFSSL_PPC64_ASM) && !defined(WOLFSSL_NO_ASM)
47
    #define HAVE_CPUID
48
    #define HAVE_CPUID_PPC64
49
#endif
50
51
#define WC_CPUID_INITIALIZER 0xffffffffU
52
typedef word32 cpuid_flags_t;
53
#if !defined(WOLFSSL_NO_ATOMICS) && !defined(SINGLE_THREADED)
54
    typedef wolfSSL_Atomic_Uint cpuid_flags_atomic_t;
55
    #define WC_CPUID_ATOMIC_INITIALIZER \
56
        WOLFSSL_ATOMIC_INITIALIZER(WC_CPUID_INITIALIZER)
57
#else
58
    typedef word32 cpuid_flags_atomic_t;
59
    #define WC_CPUID_ATOMIC_INITIALIZER WC_CPUID_INITIALIZER
60
#endif
61
62
#ifdef HAVE_CPUID_INTEL
63
64
    #define CPUID_AVX1   0x0001
65
    #define CPUID_AVX2   0x0002
66
    #define CPUID_RDRAND 0x0004
67
    #define CPUID_RDSEED 0x0008
68
    #define CPUID_BMI2   0x0010   /* MULX, RORX */
69
    #define CPUID_AESNI  0x0020
70
    #define CPUID_ADX    0x0040   /* ADCX, ADOX */
71
    #define CPUID_MOVBE  0x0080   /* Move and byte swap */
72
    #define CPUID_BMI1   0x0100   /* ANDN */
73
    #define CPUID_SHA    0x0200   /* SHA-1 and SHA-256 instructions */
74
    #define CPUID_VAES   0x0400
75
    #define CPUID_AVX512 0x0800
76
    #define CPUID_INTEL  0x1000   /* CPU vendor is GenuineIntel */
77
    /* CPU vendor is AuthenticAMD.  Detected and exposed via IS_CPU_AMD() for
78
     * future vendor-specific dispatch; no current caller relies on it. */
79
    #define CPUID_AMD    0x2000
80
81
    #define IS_INTEL_AVX1(f)    (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_AVX1)
82
    #define IS_INTEL_AVX2(f)    (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_AVX2)
83
    #define IS_INTEL_RDRAND(f)  (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_RDRAND)
84
    #define IS_INTEL_RDSEED(f)  (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_RDSEED)
85
    #define IS_INTEL_BMI2(f)    (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_BMI2)
86
    #define IS_INTEL_AESNI(f)   (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_AESNI)
87
    #define IS_INTEL_ADX(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_ADX)
88
    #define IS_INTEL_MOVBE(f)   (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_MOVBE)
89
    #define IS_INTEL_BMI1(f)    (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_BMI1)
90
    #define IS_INTEL_SHA(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SHA)
91
    #define IS_INTEL_VAES(f)    (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_VAES)
92
    #define IS_INTEL_AVX512(f)  (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_AVX512)
93
    #define IS_CPU_INTEL(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_INTEL)
94
    #define IS_CPU_AMD(f)       (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_AMD)
95
96
#elif defined(HAVE_CPUID_AARCH64)
97
98
    #define CPUID_AES         0x0001    /* AES enc/dec */
99
    #define CPUID_PMULL       0x0002    /* Carryless multiplication */
100
    #define CPUID_SHA256      0x0004    /* SHA-256 digest */
101
    #define CPUID_SHA512      0x0008    /* SHA-512 digest */
102
    #define CPUID_RDM         0x0010    /* SQRDMLAH and SQRDMLSH */
103
    #define CPUID_SHA3        0x0020    /* SHA-3 digest */
104
    #define CPUID_SM3         0x0040    /* SM3 digest */
105
    #define CPUID_SM4         0x0080    /* SM4 enc/dec */
106
    #define CPUID_SB          0x0100    /* Speculation barrier */
107
    #define CPUID_ASIMD       0x0200    /* ASIMD - NEON */
108
    #define CPUID_SVE         0x0400    /* Scalable Vector Extension */
109
    #define CPUID_SME         0x0800    /* Scalable Matrix Extension */
110
111
    #define IS_AARCH64_AES(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_AES)
112
    #define IS_AARCH64_PMULL(f)   (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_PMULL)
113
    #define IS_AARCH64_SHA256(f)  (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SHA256)
114
    #define IS_AARCH64_SHA512(f)  (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SHA512)
115
    #define IS_AARCH64_RDM(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_RDM)
116
    #define IS_AARCH64_SHA3(f)    (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SHA3)
117
    #define IS_AARCH64_SM3(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SM3)
118
    #define IS_AARCH64_SM4(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SM4)
119
    #define IS_AARCH64_SB(f)      (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SB)
120
    #define IS_AARCH64_ASIMD(f)   (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_ASIMD)
121
    #define IS_AARCH64_SVE(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SVE)
122
    #define IS_AARCH64_SME(f)     (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_SME)
123
124
#elif defined(HAVE_CPUID_PPC64)
125
126
    #define CPUID_ALTIVEC     0x0001    /* VMX / AltiVec */
127
    #define CPUID_VSX         0x0002    /* Vector-Scalar Extension */
128
    #define CPUID_ARCH_2_07   0x0004    /* POWER8 / PowerISA 2.07 */
129
    #define CPUID_VEC_CRYPTO  0x0008    /* Vector crypto: vshasigmaw, vcipher,
130
                                         * vpmsumd, ... */
131
    #define CPUID_ARCH_3_00   0x0010    /* POWER9 / PowerISA 3.0 */
132
    #define CPUID_ARCH_3_1    0x0020    /* POWER10 / PowerISA 3.1 */
133
134
    #define IS_PPC64_ALTIVEC(f)    \
135
        (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_ALTIVEC)
136
    #define IS_PPC64_VSX(f)        \
137
        (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_VSX)
138
    #define IS_PPC64_ARCH_2_07(f)  \
139
        (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_ARCH_2_07)
140
    #define IS_PPC64_VEC_CRYPTO(f) \
141
        (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_VEC_CRYPTO)
142
    #define IS_PPC64_ARCH_3_00(f)  \
143
        (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_ARCH_3_00)
144
    #define IS_PPC64_ARCH_3_1(f)   \
145
        (WOLFSSL_ATOMIC_COERCE_UINT(f) & CPUID_ARCH_3_1)
146
147
#endif
148
149
#ifdef HAVE_CPUID
150
    cpuid_flags_t cpuid_get_flags(void);
151
152
    /* Idempotent flag getter -- fast, but return value (whether updated) is not
153
     * strictly reliable.
154
     */
155
0
    static WC_INLINE int cpuid_get_flags_ex(cpuid_flags_t *flags) {
156
0
        if (*flags == WC_CPUID_INITIALIZER) {
157
0
            *flags = cpuid_get_flags();
158
0
            return 1;
159
0
        }
160
0
        else
161
0
            return 0;
162
0
    }
Unexecuted instantiation: aes.c:cpuid_get_flags_ex
Unexecuted instantiation: chacha.c:cpuid_get_flags_ex
Unexecuted instantiation: poly1305.c:cpuid_get_flags_ex
Unexecuted instantiation: random.c:cpuid_get_flags_ex
Unexecuted instantiation: sha256.c:cpuid_get_flags_ex
Unexecuted instantiation: sha512.c:cpuid_get_flags_ex
Unexecuted instantiation: sm3.c:cpuid_get_flags_ex
Unexecuted instantiation: wc_port.c:cpuid_get_flags_ex
Unexecuted instantiation: wc_mlkem_poly.c:cpuid_get_flags_ex
163
164
    /* Strictly race-free flag getter -- slow, but the return value is strictly
165
     * accurate.
166
     */
167
0
    static WC_INLINE int cpuid_get_flags_atomic(cpuid_flags_atomic_t *flags) {
168
0
        #ifdef WOLFSSL_BSDKM
169
0
        if (WOLFSSL_ATOMIC_LOAD_UINT(*flags) == WC_CPUID_INITIALIZER) {
170
0
        #else
171
0
        if (WOLFSSL_ATOMIC_LOAD(*flags) == WC_CPUID_INITIALIZER) {
172
0
        #endif /* WOLFSSL_BSDKM */
173
0
            cpuid_flags_t old_cpuid_flags = WC_CPUID_INITIALIZER;
174
0
            return wolfSSL_Atomic_Uint_CompareExchange
175
0
                (flags, &old_cpuid_flags, cpuid_get_flags());
176
0
        }
177
0
        else
178
0
            return 0;
179
0
    }
Unexecuted instantiation: aes.c:cpuid_get_flags_atomic
Unexecuted instantiation: chacha.c:cpuid_get_flags_atomic
Unexecuted instantiation: poly1305.c:cpuid_get_flags_atomic
Unexecuted instantiation: random.c:cpuid_get_flags_atomic
Unexecuted instantiation: sha256.c:cpuid_get_flags_atomic
Unexecuted instantiation: sha512.c:cpuid_get_flags_atomic
Unexecuted instantiation: sm3.c:cpuid_get_flags_atomic
Unexecuted instantiation: wc_port.c:cpuid_get_flags_atomic
Unexecuted instantiation: wc_mlkem_poly.c:cpuid_get_flags_atomic
180
181
    /* Public APIs to modify flags. */
182
183
    #ifdef WOLFSSL_API_PREFIX_MAP
184
        #define cpuid_select_flags wc_cpuid_select_flags
185
        #define cpuid_set_flag wc_cpuid_set_flag
186
        #define cpuid_clear_flag wc_cpuid_clear_flag
187
    #endif /* WOLFSSL_API_PREFIX_MAP */
188
189
    WOLFSSL_API void cpuid_select_flags(cpuid_flags_t flags);
190
    WOLFSSL_API void cpuid_set_flag(cpuid_flags_t flag);
191
    WOLFSSL_API void cpuid_clear_flag(cpuid_flags_t flag);
192
193
#endif
194
195
#ifdef __cplusplus
196
    }   /* extern "C" */
197
#endif
198
199
200
#endif /* WOLF_CRYPT_CPUID_H */