resetting manifest requested domain to floor
[platform/upstream/x86info.git] / features.c
1 /*
2  *  (C) 2001-2010 Dave Jones.
3  *
4  *  Licensed under the terms of the GNU GPL License version 2.
5  *
6  *  Feature flag decoding.
7  */
8
9 #include <stdio.h>
10 #include <signal.h>
11 #include <setjmp.h>
12 #include "x86info.h"
13
14 static void flag_decode(unsigned long reg, const char * reg_desc, const char *flags[], const char *flags_desc[])
15 {
16         unsigned int i;
17
18         for (i = 0; i < 32; i++) {
19                 if (reg & (1<<i)) {
20                         if (!verbose) {
21                             if (flags[i])
22                                     printf(" %s", flags[i]);
23                             else
24                                     printf(" [%s:%u]", reg_desc, i);
25                         } else {
26                             if (flags[i])
27                                     printf(" %-8s", flags[i]);
28                             else
29                                     printf(" [%s:%u]     ", reg_desc, i);
30                             if (flags_desc)
31                                     printf("\t%s\n", flags_desc[i]);
32                             else
33                                     printf("\n");
34                         }
35                 }
36         }
37 }
38
39
40 void get_feature_flags(struct cpudata *cpu)
41 {
42         unsigned int eax, ebx, ecx, edx;
43
44         cpuid(cpu->number, 0x00000001, &eax, &ebx, &ecx, &edx);
45         cpu->flags_ecx = ecx;
46         cpu->flags_edx = edx;
47         if (cpu->maxei >= 0x80000001) {
48                 cpuid(cpu->number, 0x80000001, &eax, &ebx, &ecx, &edx);
49                 cpu->eflags_ecx = ecx;
50                 cpu->eflags_edx = edx;
51         }
52 }
53
54 void show_extra_intel_flags(struct cpudata *cpu)
55 {
56         unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
57         /* CPUID 0x00000006 EAX flags */
58         const char *intel_cpuid_06_eax_flags[] = {
59                 "dts", "ida", "arat", NULL, "pln", "ecmd", "ptm", NULL,
60                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
61                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
62                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
63         };
64         const char *intel_cpuid_06_eax_flags_desc[] = {
65                 "Digital temperature sensor supported",                 // 0
66                 "Intel Dynamic Acceleration Technology (Turbo Boost)",  // 1
67                 "Always Running APIC Timer",                            // 2
68                 NULL,                                                   // 3
69                 "Power limit notification controls",                    // 4
70                 "Clock modulation duty cycle extension",                // 5
71                 "Package thermal management",                           // 6
72                 NULL,                                                   // 7
73                 NULL,                                                   // 8
74                 NULL,                                                   // 9
75                 NULL,                                                   // 10
76                 NULL,                                                   // 11
77                 NULL,                                                   // 12
78                 NULL,                                                   // 13
79                 NULL,                                                   // 14
80                 NULL,                                                   // 15
81                 NULL,                                                   // 16
82                 NULL,                                                   // 17
83                 NULL,                                                   // 18
84                 NULL,                                                   // 19
85                 NULL,                                                   // 20
86                 NULL,                                                   // 21
87                 NULL,                                                   // 22
88                 NULL,                                                   // 23
89                 NULL,                                                   // 24
90                 NULL,                                                   // 25
91                 NULL,                                                   // 26
92                 NULL,                                                   // 27
93                 NULL,                                                   // 28
94                 NULL,                                                   // 29
95                 NULL,                                                   // 30
96                 NULL                                                    // 31
97         };
98
99         /* CPUID 0x80000007 EDX flags */
100         const char *intel_cpuid_80000007_edx_flags[] = {
101                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
102                 "nonstop_tsc", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
103                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
104                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
105         };
106         const char *intel_cpuid_80000007_edx_flags_desc[] = {
107                 NULL,                                                   // 0
108                 NULL,                                                   // 1
109                 NULL,                                                   // 2
110                 NULL,                                                   // 3
111                 NULL,                                                   // 4
112                 NULL,                                                   // 5
113                 NULL,                                                   // 6
114                 NULL,                                                   // 7
115                 "Invariant/nonstop/constant TSC",                       // 8
116                 NULL,                                                   // 9
117                 NULL,                                                   // 10
118                 NULL,                                                   // 11
119                 NULL,                                                   // 12
120                 NULL,                                                   // 13
121                 NULL,                                                   // 14
122                 NULL,                                                   // 15
123                 NULL,                                                   // 16
124                 NULL,                                                   // 17
125                 NULL,                                                   // 18
126                 NULL,                                                   // 19
127                 NULL,                                                   // 20
128                 NULL,                                                   // 21
129                 NULL,                                                   // 22
130                 NULL,                                                   // 23
131                 NULL,                                                   // 24
132                 NULL,                                                   // 25
133                 NULL,                                                   // 26
134                 NULL,                                                   // 27
135                 NULL,                                                   // 28
136                 NULL,                                                   // 29
137                 NULL,                                                   // 30
138                 NULL                                                    // 31
139         };
140
141         // Intel CPUID 0x06
142         if (cpu->cpuid_level >= 0x06) {
143                 cpuid(cpu->number, 0x06, &eax, &ebx, &ecx, &edx);
144                 flag_decode(eax, "6:eax", intel_cpuid_06_eax_flags, intel_cpuid_06_eax_flags_desc);
145         }
146         // Intel CPUID 0x80000007
147         if (cpu->maxei >= 0x80000007) {
148                 cpuid(cpu->number, 0x80000007, &eax, &ebx, &ecx, &edx);
149                 flag_decode(edx, "80000007:edx", intel_cpuid_80000007_edx_flags, intel_cpuid_80000007_edx_flags_desc);
150         }
151 }
152
153 static void decode_feature_flags(struct cpudata *cpu)
154 {
155         unsigned int eax, ebx, ecx, edx;
156
157         /* CPUID 0x00000001 EDX flags */
158         const char *generic_cap_flags[] = {
159                 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
160                 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
161                 "pat", "pse36", "psn", "clflsh", NULL, "ds", "acpi", "mmx",
162                 "fxsr", "sse", "sse2", "ss", "ht", "tm", NULL, "pbe"
163         };
164         const char *generic_cap_flags_desc[] = {
165                 "Onboard FPU",                                          // 0
166                 "Virtual Mode Extensions",                              // 1
167                 "Debugging Extensions",                                 // 2
168                 "Page Size Extensions",                                 // 3
169                 "Time Stamp Counter",                                   // 4
170                 "Model-Specific Registers",                             // 5
171                 "Physical Address Extensions",                          // 6
172                 "Machine Check Exception",                              // 7
173                 "CMPXCHG8 instruction",                                 // 8
174                 "Onboard APIC",                                         // 9
175                 NULL,                                                   // 10
176                 "SYSENTER/SYSEXIT instructions",                        // 11
177                 "Memory Type Range Registers",                          // 12
178                 "Page Global Enable",                                   // 13
179                 "Machine Check Architecture",                           // 14
180                 "CMOV instruction",                                     // 15
181                 "Page Attribute Table",                                 // 16
182                 "36-bit PSEs",                                          // 17
183                 "Processor serial number",      /* reserved on AMD */   // 18
184                 "CLFLUSH instruction",                                  // 19
185                 NULL,                                                   // 20
186                 "Debug Trace Store",            /* reserved on AMD */   // 21
187                 "ACPI via MSR",                 /* reserved on AMD */   // 22
188                 "MMX support",                                          // 23
189                 "FXSAVE and FXRSTOR instructions",                      // 24
190                 "SSE support",                                          // 25
191                 "SSE2 support",                                         // 26
192                 "CPU self snoop",               /* reserved on AMD */   // 27
193                 "Hyper-Threading",                                      // 28
194                 "Thermal Monitor",              /* reserved on AMD */   // 29
195                 NULL,                                                   // 30
196                 "Pending Break Enable"          /* reserved on AMD */   // 31
197         };
198         /* CPUID 0x00000001 ECX flags */
199         const char *intel_cap_generic_ecx_flags[] = {
200                 "sse3", "pclmuldq", "dtes64", "monitor", "ds-cpl", "vmx", "smx", "est",
201                 "tm2", "ssse3", "cid", NULL, "fma", "cx16", "xTPR", "pdcm",
202                 NULL, "pcid", "dca", "sse4_1", "sse4_2", "x2apic", "movbe", "popcnt",
203                 "tsc-deadline", "aes", "xsave", "osxsave", "avx", NULL, NULL, NULL
204         };
205         const char *intel_cap_generic_ecx_flags_desc[] = {
206                 "Streaming SIMD Extensions 3",              // 0
207                 "PCLMULDQ Instruction",                     // 1
208                 "64-Bit Debug Store",                       // 2
209                 "MONITOR/MWAIT",                            // 3
210                 "CPL Qualified Debug Store",                // 4
211                 "Virtual Machine Extensions",               // 5
212                 "Safer Mode Extensions",                    // 6
213                 "Enhanced Intel SpeedStep Technology",      // 7
214                 "Thermal Monitor 2",                        // 8
215                 "Supplemental Streaming SIMD Extensions 3", // 9
216                 "L1 Context ID",                            // 10
217                 NULL,                                       // 11
218                 "Fused Multiply Add",                       // 12
219                 "CMPXCHG16B",                               // 13
220                 "xTPR Update Control",                      // 14
221                 "Perfmon and Debug Capability",             // 15
222                 NULL,                                       // 16
223                 "Process-context identifiers",              // 17
224                 "Direct Cache Access",                      // 18
225                 "Streaming SIMD Extensions 4.1",            // 19
226                 "Streaming SIMD Extensions 4.2",            // 20
227                 "Extended xAPIC Support",                   // 21
228                 "MOVBE Instruction",                        // 22
229                 "POPCNT Instruction",                       // 23
230                 "TSC Deadline support",                     // 24
231                 "AES Instruction",                          // 25
232                 "XSAVE/XSTOR States",                       // 26
233                 "OS-Enabled Extended State Management",     // 27
234                 "AVX instruction extensions",               // 28
235                 NULL,                                       // 29
236                 NULL,                                       // 30
237                 NULL                                        // 31
238         };
239         /* CPUID 0x80000001 EDX flags */
240         const char *intel_cap_extended_edx_flags[] = {
241                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
242                 NULL, NULL, NULL, "SYSCALL", NULL, NULL, NULL, NULL,
243                 NULL, NULL, NULL, NULL, "xd", NULL, NULL, NULL,
244                 NULL, NULL, "pdpe1gb", "rdtscp", NULL, "em64t", NULL, NULL,
245         };
246         const char *intel_cap_extended_edx_flags_desc[] = {
247                 NULL,                                       // 0
248                 NULL,                                       // 1
249                 NULL,                                       // 2
250                 NULL,                                       // 3
251                 NULL,                                       // 4
252                 NULL,                                       // 5
253                 NULL,                                       // 6
254                 NULL,                                       // 7
255                 NULL,                                       // 8
256                 NULL,                                       // 9
257                 NULL,                                       // 10
258                 "SYSCALL/SYSRET instructions",              // 11
259                 NULL,                                       // 12
260                 NULL,                                       // 13
261                 NULL,                                       // 14
262                 NULL,                                       // 15
263                 NULL,                                       // 16
264                 NULL,                                       // 17
265                 NULL,                                       // 18
266                 NULL,                                       // 19
267                 "Execution Disable Bit",                    // 20
268                 NULL,                                       // 21
269                 NULL,                                       // 22
270                 NULL,                                       // 23
271                 NULL,                                       // 24
272                 NULL,                                       // 25
273                 "1-GByte pages",                            // 26
274                 "RDTSCP and IA32_TSC_AUX",                  // 27
275                 NULL,                                       // 28
276                 "Intel 64 Instruction Set Architecture",    // 29
277                 NULL,                                       // 30
278                 NULL                                        // 31
279         };
280         /* CPUID 0x80000001 ECX flags */
281         const char *intel_cap_extended_ecx_flags[] = {
282                 "lahf_lm", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
283                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
284                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
285                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
286         };
287         const char *intel_cap_extended_ecx_flags_desc[] = {
288                 "LAHF/SAHF available in 64-bit mode",       // 0
289                 NULL,                                       // 1
290                 NULL,                                       // 2
291                 NULL,                                       // 3
292                 NULL,                                       // 4
293                 NULL,                                       // 5
294                 NULL,                                       // 6
295                 NULL,                                       // 7
296                 NULL,                                       // 8
297                 NULL,                                       // 9
298                 NULL,                                       // 10
299                 NULL,                                       // 11
300                 NULL,                                       // 12
301                 NULL,                                       // 13
302                 NULL,                                       // 14
303                 NULL,                                       // 15
304                 NULL,                                       // 16
305                 NULL,                                       // 17
306                 NULL,                                       // 18
307                 NULL,                                       // 19
308                 NULL,                                       // 19
309                 NULL,                                       // 20
310                 NULL,                                       // 22
311                 NULL,                                       // 23
312                 NULL,                                       // 24
313                 NULL,                                       // 25
314                 NULL,                                       // 26
315                 NULL,                                       // 27
316                 NULL,                                       // 28
317                 NULL,                                       // 29
318                 NULL,                                       // 30
319                 NULL                                        // 31
320         };
321
322         const char *amd_cap_generic_ecx_flags[] = {
323                 "sse3", "pclmulqdq", NULL, "mwait", NULL, NULL, NULL, NULL,
324                 NULL, "ssse3", NULL, NULL, "fma", "cmpxchg16b", NULL, NULL,
325                 NULL, NULL, NULL, "sse4_1", "sse4_2", NULL, NULL, "popcnt",
326                 NULL, "aes", "xsave", "osxsave", "avx", "f16c", NULL, NULL
327         };
328         const char *amd_cap_generic_ecx_flags_desc[] = {
329                 "Streaming SIMD Extensions 3",              // 0
330                 NULL,                                       // 1
331                 NULL,                                       // 2
332                 "MONITOR/MWAIT instructions",               // 3
333                 NULL,                                       // 4
334                 NULL,                                       // 5
335                 NULL,                                       // 6
336                 NULL,                                       // 7
337                 NULL,                                       // 8
338                 "Supplemental Streaming SIMD Extensions 3", // 9
339                 NULL,                                       // 10
340                 NULL,                                       // 11
341                 NULL,                                       // 12
342                 "CMPXCHG16B instruction",                   // 13
343                 NULL,                                       // 14
344                 NULL,                                       // 15
345                 NULL,                                       // 16
346                 NULL,                                       // 17
347                 NULL,                                       // 18
348                 "Streaming SIMD Extensions 4.1",            // 19
349                 NULL,                                       // 20
350                 NULL,                                       // 22
351                 "POPCNT instruction",                       // 23
352                 NULL,                                       // 24
353                 NULL,                                       // 25
354                 NULL,                                       // 26
355                 NULL,                                       // 27
356                 NULL,                                       // 28
357                 NULL,                                       // 29
358                 NULL,                                       // 30
359                 NULL                                        // 31
360         };
361         const char *amd_cap_extended_edx_flags[] = {
362                 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
363                 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
364                 "pat", "pse36", NULL, "mp", "nx", NULL, "mmxext", "mmx",
365                 "fxsr", "ffxsr", "page1gb", "rdtscp",
366                 NULL, "lm", "3dnowext", "3dnow"
367         }; /* "mp" defined for CPUs prior to AMD family 0xf */
368
369         const char *amd_cap_extended_ecx_flags[] = {
370                 "lahf/sahf", "CmpLegacy", "svm", "ExtApicSpace",
371                 "LockMovCr0", "abm", "sse4a", "misalignsse",
372                 "3dnowPref", "osvw", "ibs", "xop",
373                 "skinit", "wdt", NULL, "lwp",
374                 "fma4", NULL, NULL, "NodeId",
375                 NULL, "tbm", "TopoExt", "PerfCtrExtCore",
376                 "PerfCtrExtNB", NULL, NULL, NULL, NULL, NULL, NULL, NULL
377         };
378
379         const char *centaur_cap_extended_ecx_flags[] = {
380                 "sse3", NULL, NULL, NULL, NULL, NULL, NULL, "EPS",
381                 "tm2", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
382                 NULL, NULL, NULL, NULL, NULL, NULL, "mmxext", NULL,
383                 NULL, NULL, NULL, NULL, NULL, NULL, "3dnowext", "3dnow"
384         };
385         const char *centaur_cap_extended_edx_flags[] = {
386                 NULL, NULL, "RNGp", "RNGe", NULL, NULL, "ACEp", "ACEe",
387                 "ACE2p", "ACE2e", "PHEp", "PHEe", "PMMp", "PMMe", NULL, NULL,
388                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
389                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
390         };
391
392         const char *transmeta_cap_flags[] = {
393                 "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
394                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
395                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
396                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
397         };
398
399         printf("Feature flags:\n");
400         flag_decode(cpu->flags_edx, "1:edx", generic_cap_flags, generic_cap_flags_desc);
401
402         /* Vendor specific extensions. */
403         switch (cpu->vendor) {
404                 case VENDOR_AMD:
405                         flag_decode(cpu->flags_ecx, "1:ecx", amd_cap_generic_ecx_flags, amd_cap_generic_ecx_flags_desc);
406                         printf("\n");
407                         if (cpu->maxei < 0x80000001)
408                                 break;
409                         printf("Extended feature flags:\n");
410                         flag_decode(cpu->eflags_edx, "80000001:edx", amd_cap_extended_edx_flags, NULL);
411                         flag_decode(cpu->eflags_ecx, "80000001:ecx", amd_cap_extended_ecx_flags, NULL);
412                         printf("\n");
413                         break;
414
415                 case VENDOR_CENTAUR:
416                         printf("\n");
417                         printf("Extended feature flags:\n");
418                         flag_decode(cpu->flags_ecx, "1:ecx", centaur_cap_extended_ecx_flags, NULL);
419                         cpuid(cpu->number, 0xc0000000, &eax, &ebx, &ecx, &edx);
420                         if (eax >=0xc0000001) {
421                                 cpuid(cpu->number, 0xc0000001, &eax, &ebx, &ecx, &edx);
422                                 cpu->flags_edx = edx;
423                                 flag_decode(cpu->flags_edx, "1:edx", centaur_cap_extended_edx_flags, NULL);
424                         }
425                         break;
426
427                 case VENDOR_TRANSMETA:
428                         printf("\n");
429                         printf("Extended feature flags:\n");
430                         flag_decode(cpu->flags_ecx, "1:ecx", transmeta_cap_flags, NULL);
431                         break;
432
433                 case VENDOR_CYRIX:
434                         printf("\n");
435                         break;
436
437                 case VENDOR_INTEL:
438                         flag_decode(cpu->flags_ecx, "1:ecx", intel_cap_generic_ecx_flags, intel_cap_generic_ecx_flags_desc);
439                         printf("\n");
440                         if (cpu->maxei < 0x80000001)
441                                 break;
442                         printf("Extended feature flags:\n");
443                         flag_decode(cpu->eflags_edx, "80000001:edx", intel_cap_extended_edx_flags, intel_cap_extended_edx_flags_desc);
444                         flag_decode(cpu->eflags_ecx, "80000001:ecx", intel_cap_extended_ecx_flags, intel_cap_extended_ecx_flags_desc);
445                         show_extra_intel_flags(cpu);
446                         break;
447
448                 default:
449                         /* Unknown CPU manufacturer or no special handling needed */
450                         break;
451         }
452
453         printf("\n");
454 }
455
456 static sigjmp_buf out;
457
458 static void sigill(__attribute__((__unused__))int sig)
459 {
460         siglongjmp(out, 1);
461 }
462
463 static void test_longnop(void)
464 {
465         int died;
466
467         signal(SIGILL, sigill);
468
469         died = sigsetjmp(out, 1);
470
471         if (!died)
472                 asm volatile(".byte 0x0f,0x1f,0x00 /* nopl 0(%eax) */");
473
474         printf("Long NOPs supported: %s\n", died ? "no" : "yes");
475 }
476
477 void display_feature_flags(struct cpudata *cpu)
478 {
479         decode_feature_flags(cpu);
480         test_longnop();
481         printf("\n");
482 }