Mercurial > mplayer.hg
annotate cpuinfo.c @ 34021:fbb87f092560
Get rid of usage of deprecated palctrl which no longer works anyway.
Set up side data instead.
Note that for lavf demuxer we will use the merged side data anyway,
this is only for our own, e.g. AVI demuxer.
Fixes bug #1976.
author | reimar |
---|---|
date | Sat, 17 Sep 2011 16:48:40 +0000 |
parents | 514016233368 |
children |
rev | line source |
---|---|
30429
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
1 /* |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
2 * small utility to extract CPU information |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
3 * Used by configure to set CPU optimization levels on some operating |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
4 * systems where /proc/cpuinfo is non-existent or unreliable. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
5 * |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
6 * This file is part of MPlayer. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
7 * |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
8 * MPlayer is free software; you can redistribute it and/or modify |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
11 * (at your option) any later version. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
12 * |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
13 * MPlayer is distributed in the hope that it will be useful, |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
16 * GNU General Public License for more details. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
17 * |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
18 * You should have received a copy of the GNU General Public License along |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
19 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
c1a3f1bbba26
Add license header to all top-level files missing them.
diego
parents:
29072
diff
changeset
|
21 */ |
22932 | 22 |
23 #include <stdio.h> | |
24 #include <sys/time.h> | |
25 #include <stdlib.h> | |
26 #include <string.h> | |
27 #include <unistd.h> | |
28 | |
29 #ifdef __MINGW32__ | |
30 #define MISSING_USLEEP | |
31 #include <windows.h> | |
32 #define sleep(t) Sleep(1000*t); | |
33 #endif | |
34 | |
35 #ifdef M_UNIX | |
36 typedef long long int64_t; | |
37 #define MISSING_USLEEP | |
38 #else | |
39 #include <inttypes.h> | |
40 #endif | |
41 | |
42 #define CPUID_FEATURE_DEF(bit, desc, description) \ | |
31077 | 43 { bit, desc } |
22932 | 44 |
45 typedef struct cpuid_regs { | |
31077 | 46 unsigned int eax; |
47 unsigned int ebx; | |
48 unsigned int ecx; | |
49 unsigned int edx; | |
22932 | 50 } cpuid_regs_t; |
51 | |
52 static cpuid_regs_t | |
53 cpuid(int func) { | |
31077 | 54 cpuid_regs_t regs; |
22932 | 55 #define CPUID ".byte 0x0f, 0xa2; " |
56 #ifdef __x86_64__ | |
31077 | 57 __asm__("mov %%rbx, %%rsi\n\t" |
22932 | 58 #else |
31077 | 59 __asm__("mov %%ebx, %%esi\n\t" |
22932 | 60 #endif |
31077 | 61 CPUID"\n\t" |
22932 | 62 #ifdef __x86_64__ |
31077 | 63 "xchg %%rsi, %%rbx\n\t" |
22932 | 64 #else |
31077 | 65 "xchg %%esi, %%ebx\n\t" |
22932 | 66 #endif |
31077 | 67 : "=a" (regs.eax), "=S" (regs.ebx), "=c" (regs.ecx), "=d" (regs.edx) |
68 : "0" (func)); | |
69 return regs; | |
22932 | 70 } |
71 | |
72 | |
73 static int64_t | |
74 rdtsc(void) | |
75 { | |
31077 | 76 uint32_t hi, lo; |
22932 | 77 #define RDTSC ".byte 0x0f, 0x31; " |
31077 | 78 __asm__ volatile (RDTSC : "=a"(lo), "=d"(hi) : ); |
79 return (uint64_t) hi << 32 | lo; | |
22932 | 80 } |
81 | |
82 static const char* | |
83 brandname(int i) | |
84 { | |
31077 | 85 static const char* brandmap[] = { |
86 NULL, | |
87 "Intel(R) Celeron(R) processor", | |
88 "Intel(R) Pentium(R) III processor", | |
89 "Intel(R) Pentium(R) III Xeon(tm) processor", | |
90 "Intel(R) Pentium(R) III processor", | |
91 NULL, | |
92 "Mobile Intel(R) Pentium(R) III processor-M", | |
93 "Mobile Intel(R) Celeron(R) processor" | |
94 }; | |
22932 | 95 |
31077 | 96 if (i >= sizeof(brandmap)) |
97 return NULL; | |
98 else | |
99 return brandmap[i]; | |
22932 | 100 } |
101 | |
102 static void | |
103 store32(char *d, unsigned int v) | |
104 { | |
31077 | 105 d[0] = v & 0xff; |
106 d[1] = (v >> 8) & 0xff; | |
107 d[2] = (v >> 16) & 0xff; | |
108 d[3] = (v >> 24) & 0xff; | |
22932 | 109 } |
110 | |
111 | |
112 int | |
28599
3ff0da40013d
cosmetics: Replace unused 'argc/argv' in main declarations by 'void'.
diego
parents:
28597
diff
changeset
|
113 main(void) |
22932 | 114 { |
31077 | 115 cpuid_regs_t regs, regs_ext; |
116 char idstr[13]; | |
117 unsigned max_cpuid; | |
118 unsigned max_ext_cpuid; | |
119 unsigned int amd_flags; | |
120 unsigned int amd_flags2; | |
121 const char *model_name = NULL; | |
122 int i; | |
123 char processor_name[49]; | |
22932 | 124 |
31077 | 125 regs = cpuid(0); |
126 max_cpuid = regs.eax; | |
127 /* printf("%d CPUID function codes\n", max_cpuid+1); */ | |
22932 | 128 |
31077 | 129 store32(idstr+0, regs.ebx); |
130 store32(idstr+4, regs.edx); | |
131 store32(idstr+8, regs.ecx); | |
132 idstr[12] = 0; | |
133 printf("vendor_id\t: %s\n", idstr); | |
22932 | 134 |
31077 | 135 regs_ext = cpuid((1<<31) + 0); |
136 max_ext_cpuid = regs_ext.eax; | |
137 if (max_ext_cpuid >= (1<<31) + 1) { | |
138 regs_ext = cpuid((1<<31) + 1); | |
139 amd_flags = regs_ext.edx; | |
140 amd_flags2 = regs_ext.ecx; | |
22932 | 141 |
31077 | 142 if (max_ext_cpuid >= (1<<31) + 4) { |
143 for (i = 2; i <= 4; i++) { | |
144 regs_ext = cpuid((1<<31) + i); | |
145 store32(processor_name + (i-2)*16, regs_ext.eax); | |
146 store32(processor_name + (i-2)*16 + 4, regs_ext.ebx); | |
147 store32(processor_name + (i-2)*16 + 8, regs_ext.ecx); | |
148 store32(processor_name + (i-2)*16 + 12, regs_ext.edx); | |
149 } | |
150 processor_name[48] = 0; | |
151 model_name = processor_name; | |
152 while (*model_name == ' ') { | |
153 model_name++; | |
154 } | |
155 } | |
156 } else { | |
157 amd_flags = 0; | |
158 amd_flags2 = 0; | |
23346 | 159 } |
22932 | 160 |
31077 | 161 if (max_cpuid >= 1) { |
162 static struct { | |
163 int bit; | |
164 char *desc; | |
165 } cap[] = { | |
166 CPUID_FEATURE_DEF(0, "fpu", "Floating-point unit on-chip"), | |
167 CPUID_FEATURE_DEF(1, "vme", "Virtual Mode Enhancements"), | |
168 CPUID_FEATURE_DEF(2, "de", "Debugging Extension"), | |
169 CPUID_FEATURE_DEF(3, "pse", "Page Size Extension"), | |
170 CPUID_FEATURE_DEF(4, "tsc", "Time Stamp Counter"), | |
171 CPUID_FEATURE_DEF(5, "msr", "Pentium Processor MSR"), | |
172 CPUID_FEATURE_DEF(6, "pae", "Physical Address Extension"), | |
173 CPUID_FEATURE_DEF(7, "mce", "Machine Check Exception"), | |
174 CPUID_FEATURE_DEF(8, "cx8", "CMPXCHG8B Instruction Supported"), | |
175 CPUID_FEATURE_DEF(9, "apic", "On-chip APIC Hardware Enabled"), | |
176 CPUID_FEATURE_DEF(11, "sep", "SYSENTER and SYSEXIT"), | |
177 CPUID_FEATURE_DEF(12, "mtrr", "Memory Type Range Registers"), | |
178 CPUID_FEATURE_DEF(13, "pge", "PTE Global Bit"), | |
179 CPUID_FEATURE_DEF(14, "mca", "Machine Check Architecture"), | |
180 CPUID_FEATURE_DEF(15, "cmov", "Conditional Move/Compare Instruction"), | |
181 CPUID_FEATURE_DEF(16, "pat", "Page Attribute Table"), | |
182 CPUID_FEATURE_DEF(17, "pse36", "Page Size Extension 36-bit"), | |
183 CPUID_FEATURE_DEF(18, "pn", "Processor Serial Number"), | |
184 CPUID_FEATURE_DEF(19, "clflush", "CFLUSH instruction"), | |
185 CPUID_FEATURE_DEF(21, "dts", "Debug Store"), | |
186 CPUID_FEATURE_DEF(22, "acpi", "Thermal Monitor and Clock Ctrl"), | |
187 CPUID_FEATURE_DEF(23, "mmx", "MMX Technology"), | |
188 CPUID_FEATURE_DEF(24, "fxsr", "FXSAVE/FXRSTOR"), | |
189 CPUID_FEATURE_DEF(25, "sse", "SSE Extensions"), | |
190 CPUID_FEATURE_DEF(26, "sse2", "SSE2 Extensions"), | |
191 CPUID_FEATURE_DEF(27, "ss", "Self Snoop"), | |
192 CPUID_FEATURE_DEF(28, "ht", "Multi-threading"), | |
193 CPUID_FEATURE_DEF(29, "tm", "Therm. Monitor"), | |
194 CPUID_FEATURE_DEF(30, "ia64", "IA-64 Processor"), | |
195 CPUID_FEATURE_DEF(31, "pbe", "Pend. Brk. EN."), | |
196 { -1 } | |
197 }; | |
198 static struct { | |
199 int bit; | |
200 char *desc; | |
201 } cap2[] = { | |
202 CPUID_FEATURE_DEF(0, "pni", "SSE3 Extensions"), | |
203 CPUID_FEATURE_DEF(1, "pclmulqdq", "Carryless Multiplication"), | |
204 CPUID_FEATURE_DEF(2, "dtes64", "64-bit Debug Store"), | |
205 CPUID_FEATURE_DEF(3, "monitor", "MONITOR/MWAIT"), | |
206 CPUID_FEATURE_DEF(4, "ds_cpl", "CPL Qualified Debug Store"), | |
207 CPUID_FEATURE_DEF(5, "vmx", "Virtual Machine Extensions"), | |
208 CPUID_FEATURE_DEF(6, "smx", "Safer Mode Extensions"), | |
209 CPUID_FEATURE_DEF(7, "est", "Enhanced Intel SpeedStep Technology"), | |
210 CPUID_FEATURE_DEF(8, "tm2", "Thermal Monitor 2"), | |
211 CPUID_FEATURE_DEF(9, "ssse3", "Supplemental SSE3"), | |
212 CPUID_FEATURE_DEF(10, "cid", "L1 Context ID"), | |
213 CPUID_FEATURE_DEF(12, "fma", "Fused Multiply Add"), | |
214 CPUID_FEATURE_DEF(13, "cx16", "CMPXCHG16B Available"), | |
215 CPUID_FEATURE_DEF(14, "xtpr", "xTPR Disable"), | |
216 CPUID_FEATURE_DEF(15, "pdcm", "Perf/Debug Capability MSR"), | |
217 CPUID_FEATURE_DEF(18, "dca", "Direct Cache Access"), | |
218 CPUID_FEATURE_DEF(19, "sse4_1", "SSE4.1 Extensions"), | |
219 CPUID_FEATURE_DEF(20, "sse4_2", "SSE4.2 Extensions"), | |
220 CPUID_FEATURE_DEF(21, "x2apic", "x2APIC Feature"), | |
221 CPUID_FEATURE_DEF(22, "movbe", "MOVBE Instruction"), | |
222 CPUID_FEATURE_DEF(23, "popcnt", "Pop Count Instruction"), | |
223 CPUID_FEATURE_DEF(25, "aes", "AES Instruction"), | |
224 CPUID_FEATURE_DEF(26, "xsave", "XSAVE/XRSTOR Extensions"), | |
225 CPUID_FEATURE_DEF(27, "osxsave", "XSAVE/XRSTOR Enabled in the OS"), | |
226 CPUID_FEATURE_DEF(28, "avx", "Advanced Vector Extension"), | |
227 { -1 } | |
228 }; | |
229 static struct { | |
230 int bit; | |
231 char *desc; | |
232 } cap_amd[] = { | |
233 CPUID_FEATURE_DEF(11, "syscall", "SYSCALL and SYSRET"), | |
234 CPUID_FEATURE_DEF(19, "mp", "MP Capable"), | |
235 CPUID_FEATURE_DEF(20, "nx", "No-Execute Page Protection"), | |
236 CPUID_FEATURE_DEF(22, "mmxext", "MMX Technology (AMD Extensions)"), | |
237 CPUID_FEATURE_DEF(25, "fxsr_opt", "Fast FXSAVE/FXRSTOR"), | |
238 CPUID_FEATURE_DEF(26, "pdpe1gb", "PDP Entry for 1GiB Page"), | |
239 CPUID_FEATURE_DEF(27, "rdtscp", "RDTSCP Instruction"), | |
240 CPUID_FEATURE_DEF(29, "lm", "Long Mode Capable"), | |
241 CPUID_FEATURE_DEF(30, "3dnowext", "3DNow! Extensions"), | |
242 CPUID_FEATURE_DEF(31, "3dnow", "3DNow!"), | |
243 { -1 } | |
244 }; | |
245 static struct { | |
246 int bit; | |
247 char *desc; | |
248 } cap_amd2[] = { | |
249 CPUID_FEATURE_DEF(0, "lahf_lm", "LAHF/SAHF Supported in 64-bit Mode"), | |
250 CPUID_FEATURE_DEF(1, "cmp_legacy", "Chip Multi-Core"), | |
251 CPUID_FEATURE_DEF(2, "svm", "Secure Virtual Machine"), | |
252 CPUID_FEATURE_DEF(3, "extapic", "Extended APIC Space"), | |
253 CPUID_FEATURE_DEF(4, "cr8_legacy", "CR8 Available in Legacy Mode"), | |
254 CPUID_FEATURE_DEF(5, "abm", "Advanced Bit Manipulation"), | |
255 CPUID_FEATURE_DEF(6, "sse4a", "SSE4A Extensions"), | |
256 CPUID_FEATURE_DEF(7, "misalignsse", "Misaligned SSE Mode"), | |
257 CPUID_FEATURE_DEF(8, "3dnowprefetch", "3DNow! Prefetch/PrefetchW"), | |
258 CPUID_FEATURE_DEF(9, "osvw", "OS Visible Workaround"), | |
259 CPUID_FEATURE_DEF(10, "ibs", "Instruction Based Sampling"), | |
260 CPUID_FEATURE_DEF(11, "sse5", "SSE5 Extensions"), | |
261 CPUID_FEATURE_DEF(12, "skinit", "SKINIT, STGI, and DEV Support"), | |
262 CPUID_FEATURE_DEF(13, "wdt", "Watchdog Timer Support"), | |
263 { -1 } | |
264 }; | |
265 unsigned int family, model, stepping; | |
23346 | 266 |
31077 | 267 regs = cpuid(1); |
268 family = (regs.eax >> 8) & 0xf; | |
269 model = (regs.eax >> 4) & 0xf; | |
270 stepping = regs.eax & 0xf; | |
271 | |
272 if (family == 0xf) | |
273 family += (regs.eax >> 20) & 0xff; | |
274 if (family == 0xf || family == 6) | |
275 model += ((regs.eax >> 16) & 0xf) << 4; | |
276 | |
277 printf("cpu family\t: %d\n" | |
278 "model\t\t: %d\n" | |
279 "stepping\t: %d\n" , | |
280 family, | |
281 model, | |
282 stepping); | |
283 | |
284 if (strstr(idstr, "Intel") && !model_name) { | |
285 if (family == 6 && model == 0xb && stepping == 1) | |
286 model_name = "Intel (R) Celeron (R) processor"; | |
287 else | |
288 model_name = brandname(regs.ebx & 0xf); | |
289 } | |
290 | |
291 printf("flags\t\t:"); | |
292 for (i = 0; cap[i].bit >= 0; i++) { | |
293 if (regs.edx & (1 << cap[i].bit)) { | |
294 printf(" %s", cap[i].desc); | |
295 } | |
296 } | |
297 for (i = 0; cap2[i].bit >= 0; i++) { | |
298 if (regs.ecx & (1 << cap2[i].bit)) { | |
299 printf(" %s", cap2[i].desc); | |
300 } | |
301 } | |
302 /* k6_mtrr is supported by some AMD K6-2/K6-III CPUs but | |
303 it is not indicated by a CPUID feature bit, so we | |
304 have to check the family, model and stepping instead. */ | |
305 if (strstr(idstr, "AMD") && | |
306 family == 5 && | |
307 (model >= 9 || (model == 8 && stepping >= 8))) | |
308 printf(" %s", "k6_mtrr"); | |
309 /* similar for cyrix_arr. */ | |
310 if (strstr(idstr, "Cyrix") && | |
311 (family == 5 && (model < 4 || family == 6))) | |
312 printf(" %s", "cyrix_arr"); | |
313 /* as well as centaur_mcr. */ | |
314 if (strstr(idstr, "Centaur") && | |
315 family == 5) | |
316 printf(" %s", "centaur_mcr"); | |
317 | |
318 for (i = 0; cap_amd[i].bit >= 0; i++) { | |
319 if (amd_flags & (1 << cap_amd[i].bit)) { | |
320 printf(" %s", cap_amd[i].desc); | |
321 } | |
322 } | |
323 for (i = 0; cap_amd2[i].bit >= 0; i++) { | |
324 if (amd_flags2 & (1 << cap_amd2[i].bit)) { | |
325 printf(" %s", cap_amd2[i].desc); | |
326 } | |
327 } | |
328 printf("\n"); | |
329 | |
330 if (regs.edx & (1 << 4)) { | |
331 int64_t tsc_start, tsc_end; | |
332 struct timeval tv_start, tv_end; | |
333 int usec_delay; | |
334 | |
335 tsc_start = rdtsc(); | |
336 gettimeofday(&tv_start, NULL); | |
337 #ifdef MISSING_USLEEP | |
338 sleep(1); | |
339 #else | |
340 usleep(100000); | |
341 #endif | |
342 tsc_end = rdtsc(); | |
343 gettimeofday(&tv_end, NULL); | |
344 | |
345 usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec) | |
346 + (tv_end.tv_usec - tv_start.tv_usec); | |
347 | |
348 printf("cpu MHz\t\t: %.3f\n", | |
349 (double)(tsc_end-tsc_start) / usec_delay); | |
350 } | |
22932 | 351 } |
352 | |
31077 | 353 printf("model name\t: "); |
354 if (model_name) | |
355 printf("%s\n", model_name); | |
356 else | |
357 printf("Unknown %s CPU\n", idstr); | |
22932 | 358 } |