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