xref: /linux-6.15/lib/zstd/common/cpu.h (revision 65d1f550)
1*65d1f550SNick Terrell /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
2e0c1b49fSNick Terrell /*
3*65d1f550SNick Terrell  * Copyright (c) Meta Platforms, Inc. and affiliates.
4e0c1b49fSNick Terrell  * All rights reserved.
5e0c1b49fSNick Terrell  *
6e0c1b49fSNick Terrell  * This source code is licensed under both the BSD-style license (found in the
7e0c1b49fSNick Terrell  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
8e0c1b49fSNick Terrell  * in the COPYING file in the root directory of this source tree).
9e0c1b49fSNick Terrell  * You may select, at your option, one of the above-listed licenses.
10e0c1b49fSNick Terrell  */
11e0c1b49fSNick Terrell 
12e0c1b49fSNick Terrell #ifndef ZSTD_COMMON_CPU_H
13e0c1b49fSNick Terrell #define ZSTD_COMMON_CPU_H
14e0c1b49fSNick Terrell 
15e0c1b49fSNick Terrell /*
16e0c1b49fSNick Terrell  * Implementation taken from folly/CpuId.h
17e0c1b49fSNick Terrell  * https://github.com/facebook/folly/blob/master/folly/CpuId.h
18e0c1b49fSNick Terrell  */
19e0c1b49fSNick Terrell 
20e0c1b49fSNick Terrell #include "mem.h"
21e0c1b49fSNick Terrell 
22e0c1b49fSNick Terrell 
23e0c1b49fSNick Terrell typedef struct {
24e0c1b49fSNick Terrell     U32 f1c;
25e0c1b49fSNick Terrell     U32 f1d;
26e0c1b49fSNick Terrell     U32 f7b;
27e0c1b49fSNick Terrell     U32 f7c;
28e0c1b49fSNick Terrell } ZSTD_cpuid_t;
29e0c1b49fSNick Terrell 
ZSTD_cpuid(void)30e0c1b49fSNick Terrell MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
31e0c1b49fSNick Terrell     U32 f1c = 0;
32e0c1b49fSNick Terrell     U32 f1d = 0;
33e0c1b49fSNick Terrell     U32 f7b = 0;
34e0c1b49fSNick Terrell     U32 f7c = 0;
35e0c1b49fSNick Terrell #if defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
36e0c1b49fSNick Terrell     /* The following block like the normal cpuid branch below, but gcc
37e0c1b49fSNick Terrell      * reserves ebx for use of its pic register so we must specially
38e0c1b49fSNick Terrell      * handle the save and restore to avoid clobbering the register
39e0c1b49fSNick Terrell      */
40e0c1b49fSNick Terrell     U32 n;
41e0c1b49fSNick Terrell     __asm__(
42e0c1b49fSNick Terrell         "pushl %%ebx\n\t"
43e0c1b49fSNick Terrell         "cpuid\n\t"
44e0c1b49fSNick Terrell         "popl %%ebx\n\t"
45e0c1b49fSNick Terrell         : "=a"(n)
46e0c1b49fSNick Terrell         : "a"(0)
47e0c1b49fSNick Terrell         : "ecx", "edx");
48e0c1b49fSNick Terrell     if (n >= 1) {
49e0c1b49fSNick Terrell       U32 f1a;
50e0c1b49fSNick Terrell       __asm__(
51e0c1b49fSNick Terrell           "pushl %%ebx\n\t"
52e0c1b49fSNick Terrell           "cpuid\n\t"
53e0c1b49fSNick Terrell           "popl %%ebx\n\t"
54e0c1b49fSNick Terrell           : "=a"(f1a), "=c"(f1c), "=d"(f1d)
55e0c1b49fSNick Terrell           : "a"(1));
56e0c1b49fSNick Terrell     }
57e0c1b49fSNick Terrell     if (n >= 7) {
58e0c1b49fSNick Terrell       __asm__(
59e0c1b49fSNick Terrell           "pushl %%ebx\n\t"
60e0c1b49fSNick Terrell           "cpuid\n\t"
61e0c1b49fSNick Terrell           "movl %%ebx, %%eax\n\t"
62e0c1b49fSNick Terrell           "popl %%ebx"
63e0c1b49fSNick Terrell           : "=a"(f7b), "=c"(f7c)
64e0c1b49fSNick Terrell           : "a"(7), "c"(0)
65e0c1b49fSNick Terrell           : "edx");
66e0c1b49fSNick Terrell     }
67e0c1b49fSNick Terrell #elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
68e0c1b49fSNick Terrell     U32 n;
69e0c1b49fSNick Terrell     __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
70e0c1b49fSNick Terrell     if (n >= 1) {
71e0c1b49fSNick Terrell       U32 f1a;
72e0c1b49fSNick Terrell       __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
73e0c1b49fSNick Terrell     }
74e0c1b49fSNick Terrell     if (n >= 7) {
75e0c1b49fSNick Terrell       U32 f7a;
76e0c1b49fSNick Terrell       __asm__("cpuid"
77e0c1b49fSNick Terrell               : "=a"(f7a), "=b"(f7b), "=c"(f7c)
78e0c1b49fSNick Terrell               : "a"(7), "c"(0)
79e0c1b49fSNick Terrell               : "edx");
80e0c1b49fSNick Terrell     }
81e0c1b49fSNick Terrell #endif
82e0c1b49fSNick Terrell     {
83e0c1b49fSNick Terrell         ZSTD_cpuid_t cpuid;
84e0c1b49fSNick Terrell         cpuid.f1c = f1c;
85e0c1b49fSNick Terrell         cpuid.f1d = f1d;
86e0c1b49fSNick Terrell         cpuid.f7b = f7b;
87e0c1b49fSNick Terrell         cpuid.f7c = f7c;
88e0c1b49fSNick Terrell         return cpuid;
89e0c1b49fSNick Terrell     }
90e0c1b49fSNick Terrell }
91e0c1b49fSNick Terrell 
92e0c1b49fSNick Terrell #define X(name, r, bit)                                                        \
93e0c1b49fSNick Terrell   MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) {                 \
94e0c1b49fSNick Terrell     return ((cpuid.r) & (1U << bit)) != 0;                                     \
95e0c1b49fSNick Terrell   }
96e0c1b49fSNick Terrell 
97e0c1b49fSNick Terrell /* cpuid(1): Processor Info and Feature Bits. */
98e0c1b49fSNick Terrell #define C(name, bit) X(name, f1c, bit)
99e0c1b49fSNick Terrell   C(sse3, 0)
100e0c1b49fSNick Terrell   C(pclmuldq, 1)
101e0c1b49fSNick Terrell   C(dtes64, 2)
102e0c1b49fSNick Terrell   C(monitor, 3)
103e0c1b49fSNick Terrell   C(dscpl, 4)
104e0c1b49fSNick Terrell   C(vmx, 5)
105e0c1b49fSNick Terrell   C(smx, 6)
106e0c1b49fSNick Terrell   C(eist, 7)
107e0c1b49fSNick Terrell   C(tm2, 8)
108e0c1b49fSNick Terrell   C(ssse3, 9)
109e0c1b49fSNick Terrell   C(cnxtid, 10)
110e0c1b49fSNick Terrell   C(fma, 12)
111e0c1b49fSNick Terrell   C(cx16, 13)
112e0c1b49fSNick Terrell   C(xtpr, 14)
113e0c1b49fSNick Terrell   C(pdcm, 15)
114e0c1b49fSNick Terrell   C(pcid, 17)
115e0c1b49fSNick Terrell   C(dca, 18)
116e0c1b49fSNick Terrell   C(sse41, 19)
117e0c1b49fSNick Terrell   C(sse42, 20)
118e0c1b49fSNick Terrell   C(x2apic, 21)
119e0c1b49fSNick Terrell   C(movbe, 22)
120e0c1b49fSNick Terrell   C(popcnt, 23)
121e0c1b49fSNick Terrell   C(tscdeadline, 24)
122e0c1b49fSNick Terrell   C(aes, 25)
123e0c1b49fSNick Terrell   C(xsave, 26)
124e0c1b49fSNick Terrell   C(osxsave, 27)
125e0c1b49fSNick Terrell   C(avx, 28)
126e0c1b49fSNick Terrell   C(f16c, 29)
127e0c1b49fSNick Terrell   C(rdrand, 30)
128e0c1b49fSNick Terrell #undef C
129e0c1b49fSNick Terrell #define D(name, bit) X(name, f1d, bit)
130e0c1b49fSNick Terrell   D(fpu, 0)
131e0c1b49fSNick Terrell   D(vme, 1)
132e0c1b49fSNick Terrell   D(de, 2)
133e0c1b49fSNick Terrell   D(pse, 3)
134e0c1b49fSNick Terrell   D(tsc, 4)
135e0c1b49fSNick Terrell   D(msr, 5)
136e0c1b49fSNick Terrell   D(pae, 6)
137e0c1b49fSNick Terrell   D(mce, 7)
138e0c1b49fSNick Terrell   D(cx8, 8)
139e0c1b49fSNick Terrell   D(apic, 9)
140e0c1b49fSNick Terrell   D(sep, 11)
141e0c1b49fSNick Terrell   D(mtrr, 12)
142e0c1b49fSNick Terrell   D(pge, 13)
143e0c1b49fSNick Terrell   D(mca, 14)
144e0c1b49fSNick Terrell   D(cmov, 15)
145e0c1b49fSNick Terrell   D(pat, 16)
146e0c1b49fSNick Terrell   D(pse36, 17)
147e0c1b49fSNick Terrell   D(psn, 18)
148e0c1b49fSNick Terrell   D(clfsh, 19)
149e0c1b49fSNick Terrell   D(ds, 21)
150e0c1b49fSNick Terrell   D(acpi, 22)
151e0c1b49fSNick Terrell   D(mmx, 23)
152e0c1b49fSNick Terrell   D(fxsr, 24)
153e0c1b49fSNick Terrell   D(sse, 25)
154e0c1b49fSNick Terrell   D(sse2, 26)
155e0c1b49fSNick Terrell   D(ss, 27)
156e0c1b49fSNick Terrell   D(htt, 28)
157e0c1b49fSNick Terrell   D(tm, 29)
158e0c1b49fSNick Terrell   D(pbe, 31)
159e0c1b49fSNick Terrell #undef D
160e0c1b49fSNick Terrell 
161e0c1b49fSNick Terrell /* cpuid(7): Extended Features. */
162e0c1b49fSNick Terrell #define B(name, bit) X(name, f7b, bit)
163e0c1b49fSNick Terrell   B(bmi1, 3)
164e0c1b49fSNick Terrell   B(hle, 4)
165e0c1b49fSNick Terrell   B(avx2, 5)
166e0c1b49fSNick Terrell   B(smep, 7)
167e0c1b49fSNick Terrell   B(bmi2, 8)
168e0c1b49fSNick Terrell   B(erms, 9)
169e0c1b49fSNick Terrell   B(invpcid, 10)
170e0c1b49fSNick Terrell   B(rtm, 11)
171e0c1b49fSNick Terrell   B(mpx, 14)
172e0c1b49fSNick Terrell   B(avx512f, 16)
173e0c1b49fSNick Terrell   B(avx512dq, 17)
174e0c1b49fSNick Terrell   B(rdseed, 18)
175e0c1b49fSNick Terrell   B(adx, 19)
176e0c1b49fSNick Terrell   B(smap, 20)
177e0c1b49fSNick Terrell   B(avx512ifma, 21)
178e0c1b49fSNick Terrell   B(pcommit, 22)
179e0c1b49fSNick Terrell   B(clflushopt, 23)
180e0c1b49fSNick Terrell   B(clwb, 24)
181e0c1b49fSNick Terrell   B(avx512pf, 26)
182e0c1b49fSNick Terrell   B(avx512er, 27)
183e0c1b49fSNick Terrell   B(avx512cd, 28)
184e0c1b49fSNick Terrell   B(sha, 29)
185e0c1b49fSNick Terrell   B(avx512bw, 30)
186e0c1b49fSNick Terrell   B(avx512vl, 31)
187e0c1b49fSNick Terrell #undef B
188e0c1b49fSNick Terrell #define C(name, bit) X(name, f7c, bit)
189e0c1b49fSNick Terrell   C(prefetchwt1, 0)
190e0c1b49fSNick Terrell   C(avx512vbmi, 1)
191e0c1b49fSNick Terrell #undef C
192e0c1b49fSNick Terrell 
193e0c1b49fSNick Terrell #undef X
194e0c1b49fSNick Terrell 
195e0c1b49fSNick Terrell #endif /* ZSTD_COMMON_CPU_H */
196