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