]> git.ozlabs.org Git - ccan/blob - ccan/cpuid/cpuid.h
cpuid: minor clean up
[ccan] / ccan / cpuid / cpuid.h
1 /*
2  * Copyright (c) 2013, 2015 Ahmed Samy  <f.fallen45@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 #ifndef CCAN_CPUID_H
23 #define CCAN_CPUID_H
24
25 #include <stdbool.h>
26 #include <stdint.h>
27
28 /**
29  * enum cpuid - stuff to get information about from the CPU.
30  *
31  * This is used as a parameter in cpuid().
32  *
33  * %CPUID_VENDORID:
34  *      The CPU's Vendor ID.
35  *
36  * %CPUID_PROCINFO_AND_FEATUREBITS:
37  *      Processor information and feature bits (SSE, etc.).
38  *
39  * %CPUID_CACHE_AND_TLBD_INFO
40  *      Cache and TLBD Information.
41  *      For AMD: Use CPUID_EXTENDED_L2_CACHE_FEATURES
42  *
43  * %CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED:
44  *      Highest extended function supported address.
45  *      Can be like 0x80000008.
46  *
47  * %CPUID_EXTENDED_PROC_INFO_FEATURE_BITS:
48  *      Extended processor information and feature bits (64bit etc.)
49  *
50  * %CPUID_PROC_BRAND_STRING:
51  *      The Processor's brand string.
52  *
53  * %CPUID_L1_CACHE_AND_TLB_IDS:
54  *      L1 Cache and TLB Identifications.
55  *      AMD Only.
56  *
57  * %CPUID_EXTENDED_L2_CACHE_FEATURES:
58  *      Extended L2 Cache features.
59  *
60  * %CPUID_ADV_POWER_MGT_INFO:
61  *      Advaned power management information.
62  *
63  * %CPUID_VIRT_PHYS_ADDR_SIZES:
64  *      Virtual and physical address sizes.
65  */
66
67 typedef enum cpuid {
68         CPUID_VENDORID                                  = 0,
69         CPUID_PROCINFO_AND_FEATUREBITS                  = 1,
70         CPUID_CACHE_AND_TLBD_INFO                       = 2,
71
72         CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED       = 0x80000000,
73         CPUID_EXTENDED_PROC_INFO_FEATURE_BITS           = 0x80000001,
74         CPUID_PROC_BRAND_STRING                         = 0x80000002,
75         CPUID_L1_CACHE_AND_TLB_IDS                      = 0x80000005,
76         CPUID_EXTENDED_L2_CACHE_FEATURES                = 0x80000006,
77         CPUID_ADV_POWER_MGT_INFO                        = 0x80000007,
78         CPUID_VIRT_PHYS_ADDR_SIZES                      = 0x80000008
79 } cpuid_t;
80
81 enum {
82         CPUID_FEAT_ECX_SSE3         = 1 << 0, 
83         CPUID_FEAT_ECX_PCLMUL       = 1 << 1,
84         CPUID_FEAT_ECX_DTES64       = 1 << 2,
85         CPUID_FEAT_ECX_MONITOR      = 1 << 3,  
86         CPUID_FEAT_ECX_DS_CPL       = 1 << 4,  
87         CPUID_FEAT_ECX_VMX          = 1 << 5,  
88         CPUID_FEAT_ECX_SMX          = 1 << 6,  
89         CPUID_FEAT_ECX_EST          = 1 << 7,  
90         CPUID_FEAT_ECX_TM2          = 1 << 8,  
91         CPUID_FEAT_ECX_SSSE3        = 1 << 9,  
92         CPUID_FEAT_ECX_CID          = 1 << 10,
93         CPUID_FEAT_ECX_FMA          = 1 << 12,
94         CPUID_FEAT_ECX_CX16         = 1 << 13, 
95         CPUID_FEAT_ECX_ETPRD        = 1 << 14, 
96         CPUID_FEAT_ECX_PDCM         = 1 << 15, 
97         CPUID_FEAT_ECX_DCA          = 1 << 18, 
98         CPUID_FEAT_ECX_SSE4_1       = 1 << 19, 
99         CPUID_FEAT_ECX_SSE4_2       = 1 << 20, 
100         CPUID_FEAT_ECX_x2APIC       = 1 << 21, 
101         CPUID_FEAT_ECX_MOVBE        = 1 << 22, 
102         CPUID_FEAT_ECX_POPCNT       = 1 << 23, 
103         CPUID_FEAT_ECX_AES          = 1 << 25, 
104         CPUID_FEAT_ECX_XSAVE        = 1 << 26, 
105         CPUID_FEAT_ECX_OSXSAVE      = 1 << 27, 
106         CPUID_FEAT_ECX_AVX          = 1 << 28,
107
108         CPUID_FEAT_ECX_ALL          = CPUID_FEAT_ECX_SSE3 | CPUID_FEAT_ECX_PCLMUL | CPUID_FEAT_ECX_DTES64
109                                         | CPUID_FEAT_ECX_MONITOR | CPUID_FEAT_ECX_DS_CPL | CPUID_FEAT_ECX_VMX
110                                         | CPUID_FEAT_ECX_SMX | CPUID_FEAT_ECX_EST | CPUID_FEAT_ECX_TM2
111                                         | CPUID_FEAT_ECX_SSSE3 | CPUID_FEAT_ECX_CID | CPUID_FEAT_ECX_FMA
112                                         | CPUID_FEAT_ECX_CX16 | CPUID_FEAT_ECX_ETPRD | CPUID_FEAT_ECX_PDCM
113                                         | CPUID_FEAT_ECX_DCA | CPUID_FEAT_ECX_SSE4_1 | CPUID_FEAT_ECX_SSE4_2
114                                         | CPUID_FEAT_ECX_x2APIC | CPUID_FEAT_ECX_MOVBE | CPUID_FEAT_ECX_POPCNT
115                                         | CPUID_FEAT_ECX_AES | CPUID_FEAT_ECX_XSAVE | CPUID_FEAT_ECX_OSXSAVE
116                                         | CPUID_FEAT_ECX_AVX,
117
118         CPUID_FEAT_EDX_FPU          = 1 << 0,  
119         CPUID_FEAT_EDX_VME          = 1 << 1,  
120         CPUID_FEAT_EDX_DE           = 1 << 2,  
121         CPUID_FEAT_EDX_PSE          = 1 << 3,  
122         CPUID_FEAT_EDX_TSC          = 1 << 4,  
123         CPUID_FEAT_EDX_MSR          = 1 << 5,  
124         CPUID_FEAT_EDX_PAE          = 1 << 6,  
125         CPUID_FEAT_EDX_MCE          = 1 << 7,  
126         CPUID_FEAT_EDX_CX8          = 1 << 8,  
127         CPUID_FEAT_EDX_APIC         = 1 << 9,  
128         CPUID_FEAT_EDX_SEP          = 1 << 11, 
129         CPUID_FEAT_EDX_MTRR         = 1 << 12, 
130         CPUID_FEAT_EDX_PGE          = 1 << 13, 
131         CPUID_FEAT_EDX_MCA          = 1 << 14, 
132         CPUID_FEAT_EDX_CMOV         = 1 << 15, 
133         CPUID_FEAT_EDX_PAT          = 1 << 16, 
134         CPUID_FEAT_EDX_PSE36        = 1 << 17, 
135         CPUID_FEAT_EDX_PSN          = 1 << 18, 
136         CPUID_FEAT_EDX_CLF          = 1 << 19, 
137         CPUID_FEAT_EDX_DTES         = 1 << 21, 
138         CPUID_FEAT_EDX_ACPI         = 1 << 22, 
139         CPUID_FEAT_EDX_MMX          = 1 << 23, 
140         CPUID_FEAT_EDX_FXSR         = 1 << 24, 
141         CPUID_FEAT_EDX_SSE          = 1 << 25, 
142         CPUID_FEAT_EDX_SSE2         = 1 << 26, 
143         CPUID_FEAT_EDX_SS           = 1 << 27, 
144         CPUID_FEAT_EDX_HTT          = 1 << 28, 
145         CPUID_FEAT_EDX_TM1          = 1 << 29, 
146         CPUID_FEAT_EDX_IA64         = 1 << 30,
147         CPUID_FEAT_EDX_PBE          = 1 << 31,
148
149         CPUID_FEAT_EDX_ALL          = CPUID_FEAT_EDX_FPU | CPUID_FEAT_EDX_VME | CPUID_FEAT_EDX_DE
150                                         | CPUID_FEAT_EDX_PSE | CPUID_FEAT_EDX_TSC | CPUID_FEAT_EDX_MSR
151                                         | CPUID_FEAT_EDX_PAE | CPUID_FEAT_EDX_MCE | CPUID_FEAT_EDX_CX8
152                                         | CPUID_FEAT_EDX_APIC | CPUID_FEAT_EDX_SEP | CPUID_FEAT_EDX_MTRR
153                                         | CPUID_FEAT_EDX_PGE | CPUID_FEAT_EDX_MCA | CPUID_FEAT_EDX_CMOV
154                                         | CPUID_FEAT_EDX_PAT | CPUID_FEAT_EDX_PSE36 | CPUID_FEAT_EDX_PSN
155                                         | CPUID_FEAT_EDX_CLF | CPUID_FEAT_EDX_DTES | CPUID_FEAT_EDX_ACPI
156                                         | CPUID_FEAT_EDX_MMX | CPUID_FEAT_EDX_FXSR | CPUID_FEAT_EDX_SSE
157                                         | CPUID_FEAT_EDX_SSE2 | CPUID_FEAT_EDX_SS | CPUID_FEAT_EDX_HTT
158                                         | CPUID_FEAT_EDX_TM1 | CPUID_FEAT_EDX_IA64 | CPUID_FEAT_EDX_PBE
159 };
160
161 enum {
162         CPUID_EXTFEAT_ECX_LAHF_LM               = 1 << 0,
163         CPUID_EXTFEAT_ECX_CMP_LEGACY            = 1 << 1,
164         CPUID_EXTFEAT_ECX_SVM                   = 1 << 2,
165         CPUID_EXTFEAT_ECX_EXTAPIC               = 1 << 3,
166         CPUID_EXTFEAT_ECX_CR8_LEGACY            = 1 << 4,
167         CPUID_EXTFEAT_ECX_ABM                   = 1 << 5,
168         CPUID_EXTFEAT_ECX_SSE4A                 = 1 << 6,
169         CPUID_EXTFEAT_ECX_MISALIGNSSE           = 1 << 7,
170         CPUID_EXTFEAT_ECX_3DNOWPREFETCH         = 1 << 8,
171         CPUID_EXTFEAT_ECX_OSVW                  = 1 << 9,
172         CPUID_EXTFEAT_ECX_IBS                   = 1 << 10,
173         CPUID_EXTFEAT_ECX_XOP                   = 1 << 11,
174         CPUID_EXTFEAT_ECX_SKINIT                = 1 << 12,
175         CPUID_EXTFEAT_ECX_WDT                   = 1 << 13,
176         CPUID_EXTFEAT_ECX_LWP                   = 1 << 15,
177         CPUID_EXTFEAT_ECX_FMA4                  = 1 << 16,
178         CPUID_EXTFEAT_ECX_TCE                   = 1 << 17,
179         CPUID_EXTFEAT_ECX_NODEIDE_MSR           = 1 << 19,
180         CPUID_EXTFEAT_ECX_TBM                   = 1 << 21,
181         CPUID_EXTFEAT_ECX_TOPOEXT               = 1 << 22,
182         CPUID_EXTFEAT_ECX_PERFXTR_CORE          = 1 << 23,
183         CPUID_EXTFEAT_ECX_PERFCTR_NB            = 1 << 24,
184
185         CPUID_EXTFEAT_EDX_FPU                   = 1 << 0,
186         CPUID_EXTFEAT_EDX_VME                   = 1 << 1,
187         CPUID_EXTFEAT_EDX_DE                    = 1 << 2,
188         CPUID_EXTFEAT_EDX_PSE                   = 1 << 3,
189         CPUID_EXTFEAT_EDX_TSC                   = 1 << 4,
190         CPUID_EXTFEAT_EDX_MSR                   = 1 << 5,
191         CPUID_EXTFEAT_EDX_PAE                   = 1 << 6,
192         CPUID_EXTFEAT_EDX_MCE                   = 1 << 7,
193         CPUID_EXTFEAT_EDX_CX8                   = 1 << 8,
194         CPUID_EXTFEAT_EDX_APIC                  = 1 << 9,
195         CPUID_EXTFEAT_EDX_SYSCALL               = 1 << 11,
196         CPUID_EXTFEAT_EDX_MTRR                  = 1 << 12,
197         CPUID_EXTFEAT_EDX_PGE                   = 1 << 13,
198         CPUID_EXTFEAT_EDX_MCA                   = 1 << 14,
199         CPUID_EXTFEAT_EDX_CMOV                  = 1 << 15,
200         CPUID_EXTFEAT_EDX_PAT                   = 1 << 16,
201         CPUID_EXTFEAT_EDX_PSE36                 = 1 << 17,
202         CPUID_EXTFEAT_EDX_MP                    = 1 << 19,
203         CPUID_EXTFEAT_EDX_NX                    = 1 << 20,
204         CPUID_EXTFEAT_EDX_MMXEXT                = 1 << 22,
205         CPUID_EXTFEAT_EDX_MMX                   = 1 << 23,
206         CPUID_EXTFEAT_EDX_FXSR                  = 1 << 24,
207         CPUID_EXTFEAT_EDX_FXSR_OPT              = 1 << 25,
208         CPUID_EXTFEAT_EDX_PDPE1GB               = 1 << 26,
209         CPUID_EXTFEAT_EDX_RDTSCP                = 1 << 27,
210         CPUID_EXTFEAT_EDX_LM                    = 1 << 29,
211         CPUID_EXTFEAT_EDX_3DNOWEXT              = 1 << 30,
212         CPUID_EXTFEAT_EDX_3DNOW                 = 1 << 31
213 };
214
215 typedef enum cputype {
216         CT_NONE,
217         CT_AMDK5,
218         CT_AMD,
219         CT_CENTAUR,
220         CT_CYRIX,
221         CT_INTEL,
222         CT_TRANSMETA,
223         CT_NATIONAL_SEMICONDUCTOR,
224         CT_NEXGEN,
225         CT_RISE,
226         CT_SIS,
227         CT_UMC,
228         CT_VIA,
229         CT_VORTEX,
230         CT_KVM
231 } cputype_t;
232
233 static char const *const c_cpunames[] = {
234         "Nooooooooone",
235         "AMDisbetter!",
236         "AuthenticAMD",
237         "CentaurHauls",
238         "CyrixInstead",
239         "GenuineIntel",
240         "TransmetaCPU",
241         "GeniuneTMx86",
242         "Geode by NSC",
243         "NexGenDriven",
244         "RiseRiseRise",
245         "SiS SiS SiS ",
246         "UMC UMC UMC ",
247         "VIA VIA VIA ",
248         "Vortex86 SoC",
249         "KVMKVMKVMKVM"
250 };
251
252 #if defined(__i386__) || defined(__i386) || defined(__x86_64) \
253         || defined(_M_AMD64) || defined(__M_X64)
254
255 /**
256  * cpuid_get_cpu_type - Get CPU Type
257  *
258  * Returns the CPU Type as cputype_t.
259  *
260  * See also: cpuid_get_cpu_type_string()
261  */
262 cputype_t cpuid_get_cpu_type(void);
263
264 static inline bool is_intel_cpu(void)
265 {
266         return cpuid_get_cpu_type() == CT_INTEL;
267 }
268
269 static inline bool is_amd_cpu(void)
270 {
271         return cpuid_get_cpu_type() == CT_AMDK5 || cpuid_get_cpu_type() == CT_AMD;
272 }
273
274 static inline const char *cpuid_get_name(void)
275 {
276         return c_cpunames[(int)cpuid_get_cpu_type()];
277 }
278
279 /**
280  * cpuid_is_supported - test if the CPUID instruction is supported
281  *
282  * CPUID is not supported by old CPUS.
283  *
284  * Returns true if the cpuid instruction is supported, false otherwise.
285  *
286  * See also: cpuid()
287  */
288 bool cpuid_is_supported(void);
289
290 /**
291  * cpuid_highest_ext_func_supported - Get the highest extended function supported
292  *
293  *
294  * Returns the highest extended function supported.
295  *
296  * This is the same as calling:
297  *      cpuid(CPUID_HIGHEST_EEXTENDED_FUNCTION_SUPPORTED, &highest);
298  *
299  * This is made visible to the linker because it's easier to call it
300  * instead of calling cpuid with less type-checking.  cpuid calls this.
301  *
302  * See also: cpuid()
303  */
304 uint32_t cpuid_highest_ext_func_supported(void);
305
306 /**
307  * cpuid - Get Some information from the CPU.
308  *
309  * This function expects buf to be a valid pointer to a string/int/...
310  * depending on the requested information.
311  *
312  * For CPUID_VENDOR_ID:
313  *      Returns a string into buf.
314  *
315  * For CPUID_PROCINFO_AND_FEATUREBITS:
316  *      buf[0]: Stepping
317  *      buf[1]: Model
318  *      buf[2]: Family
319  *      buf[3]: Extended Model
320  *      buf[4]: Extended Family
321  *      buf[5]: Brand Index
322  *      buf[6]: CL Flush Line Size
323  *      buf[7]: Logical Processors
324  *      buf[8]: Initial APICID
325  *
326  * For CPUID_L1_CACHE_AND_TLB_IDS:
327  *      buf[0] to buf[3]: 2M+4M page TLB info
328  *              0: Inst count
329  *              1: Inst Assoc
330  *              2: Data Count
331  *              3: Data Assoc
332  *      buf[4] to buf[7]: 4k page TLB info
333  *              0: Inst count
334  *              1: Inst Assoc
335  *              2: Data Count
336  *              3: Data Assoc
337  *      buf[8] to buf[11]: L1 data cache information
338  *              0: Line Size
339  *              1: LinesPerTag
340  *              2: Associativity
341  *              3: CacheSize
342  *      buf[12] to buf[15]: L1 instruction cache info
343  *              0: Line Size
344  *              1: LinesPerTag
345  *              2: Associativity
346  *              3: CacheSize
347  *
348  * For CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED:
349  *      Returns the highest supported function in *buf (expects an integer ofc)
350  *
351  * For CPUID_EXTENDED_PROC_INFO_FEATURE_BITS:
352  *      Returns them in buf[0] and buf[1].
353  *
354  * For CPUID_EXTENDED_L2_CACHE_FEATURES:
355  *      buf[0]: Line size
356  *      buf[1]: Associativity
357  *      buf[2]: Cache size.
358  *
359  * For CPUID_VIRT_PHYS_ADDR_SIZES:
360  *      buf[0]: Physical
361  *      buf[1]: Virtual
362  *
363  * For CPUID_PROC_BRAND_STRING:
364  *      Have a char array with at least 48 bytes assigned to it.
365  *
366  * If an invalid flag has been passed a 0xbaadf00d is returned in *buf.
367  */
368 void cpuid(cpuid_t request, uint32_t *buf);
369
370 /**
371  * cpuid_write_info - Write specified CPU information to a file.
372  * @info: Bit set of information to write.
373  * @featureset: Bit set of features to write.
374  * @outfile: Output filename (Max 256).
375  *
376  * If @outfile is NULL, a name is choosen in the following format:
377  *      CPUVENDOR_PROCESSORBRAND.cpuid
378  *
379  * Returns true on success, false otherwise.
380  *
381  * Example usage:
382  *      if (!cpuid_write_info(CPUID_VENDORID | CPUID_PROC_BRAND_STRING,
383  *                              CPUID_FEAT_ECX_SSE3 | CPUID_FEAT_EDX_FPU,
384  *                              "cpuinfo.cpuid"))
385  *              ... error ...
386  */
387 bool cpuid_write_info(uint32_t info, uint32_t featureset, const char *outfile);
388
389 /**
390  * cpuid_test_feature - Test if @feature is available
391  *
392  * Returns true if feature is supported, false otherwise.
393  *
394  * The feature parameter must be >= CPUID_EXTENDED_PROC_INFO_FEATURE_BITS
395  *  and <= CPUID_VIRT_PHYS_ADDR_SIZES.
396  */
397 bool cpuid_test_feature(cpuid_t feature);
398
399 /**
400  * cpuid_has_feature - Test if @feature is supported
401  *
402  * Test if the CPU supports MMX/SSE* etc.
403  * This is split into two parts:
404  *      cpuid_has_ecxfeature and
405  *      cpuid_has_edxfeature.
406  * See the enum for more information.
407  *
408  *
409  * Returns true if the feature is available, false otherwise.
410  */
411 bool cpuid_has_ecxfeature(int feature);
412 bool cpuid_has_edxfeature(int feature);
413
414 /**
415  * cpuid_has_extfeature - Test if @extfeature is supported
416  * @extfeature: the extended feature to test.
417  *
418  * This is split into two parts:
419  *      cpuid_has_ecxfeature_ext and
420  *      cpuid_has_edxfeature_ext.
421  * See the enum for more information.
422  *
423  * Test if the CPU supports this feature.
424  * Returns true on success, false otherwise.
425  */
426 bool cpuid_has_ecxfeature_ext(int extfeature);
427 bool cpuid_has_edxfeature_ext(int extfeature);
428
429 #else
430 #include <ccan/build_assert/build_assert.h>
431
432 #define cpuid_get_cpu_type()                            BUILD_ASSERT_OR_ZERO(0)
433 #define cpuid_get_cpu_type_string()                     BUILD_ASSERT_OR_ZERO(0)
434
435 #define cpuid_is_supported()                            BUILD_ASSERT_OR_ZERO(0)
436 #define cpuid(info, buf)                                BUILD_ASSERT_OR_ZERO(0)
437 #define cpuid_write_info(info, featureset, outfile)     BUILD_ASSERT_OR_ZERO(0)
438
439 #define cpuid_highest_ext_func_supported()              BUILD_ASSERT_OR_ZERO(0)
440 #define cpuid_test_feature(feature)                     BUILD_ASSERT_OR_ZERO(0)
441 #define cpuid_has_ecxfeature(feature)                   BUILD_ASSERT_OR_ZERO(0)
442 #define cpuid_has_edxfeature(feature)                   BUILD_ASSERT_OR_ZERO(0)
443
444 #endif
445 #endif