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