comparison TOOLS/cpuinfo.c @ 17041:4471c5a962ec

M-x untabify
author gpoirier
date Wed, 23 Nov 2005 19:29:11 +0000
parents 0bfb87188015
children 744aa553e4a1
comparison
equal deleted inserted replaced
17040:0bfb87188015 17041:4471c5a962ec
1 /* small utility to extract CPU information 1 /* small utility to extract CPU information
2 Used by configure to set CPU optimization levels on some operating 2 Used by configure to set CPU optimization levels on some operating
3 systems where /proc/cpuinfo is non-existent or unreliable. */ 3 systems where /proc/cpuinfo is non-existent or unreliable. */
4 4
5 #include <stdio.h> 5 #include <stdio.h>
6 #include <sys/time.h> 6 #include <sys/time.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #ifdef __MINGW32__ 10 #ifdef __MINGW32__
11 #include <sys/timeb.h> 11 #include <sys/timeb.h>
12 void gettimeofday(struct timeval* t,void* timezone) 12 void gettimeofday(struct timeval* t,void* timezone) {
13 { struct timeb timebuffer; 13 struct timeb timebuffer;
14 ftime( &timebuffer ); 14 ftime( &timebuffer );
15 t->tv_sec=timebuffer.time; 15 t->tv_sec=timebuffer.time;
16 t->tv_usec=1000*timebuffer.millitm; 16 t->tv_usec=1000*timebuffer.millitm;
17 } 17 }
18 #define MISSING_USLEEP 18 #define MISSING_USLEEP
19 #define sleep(t) _sleep(1000*t); 19 #define sleep(t) _sleep(1000*t);
20 #endif 20 #endif
21 21
23 #define usleep(t) snooze(t) 23 #define usleep(t) snooze(t)
24 #endif 24 #endif
25 25
26 #ifdef M_UNIX 26 #ifdef M_UNIX
27 typedef long long int64_t; 27 typedef long long int64_t;
28 #define MISSING_USLEEP 28 #define MISSING_USLEEP
29 #else 29 #else
30 #include <inttypes.h> 30 #include <inttypes.h>
31 #endif 31 #endif
32 32
33 33
34 typedef struct cpuid_regs { 34 typedef struct cpuid_regs {
35 unsigned int eax; 35 unsigned int eax;
36 unsigned int ebx; 36 unsigned int ebx;
37 unsigned int ecx; 37 unsigned int ecx;
38 unsigned int edx; 38 unsigned int edx;
39 } cpuid_regs_t; 39 } cpuid_regs_t;
40 40
41 static cpuid_regs_t 41 static cpuid_regs_t
42 cpuid(int func) { 42 cpuid(int func) {
43 cpuid_regs_t regs; 43 cpuid_regs_t regs;
44 #define CPUID ".byte 0x0f, 0xa2; " 44 #define CPUID ".byte 0x0f, 0xa2; "
45 asm("push %%ebx; " 45 asm("push %%ebx; "
46 "movl %4,%%eax; " CPUID 46 "movl %4,%%eax; " CPUID
47 "movl %%eax,%0; movl %%ebx,%1; movl %%ecx,%2; movl %%edx,%3; " 47 "movl %%eax,%0; movl %%ebx,%1; movl %%ecx,%2; movl %%edx,%3; "
48 "pop %%ebx" 48 "pop %%ebx"
49 : "=m" (regs.eax), "=m" (regs.ebx), "=m" (regs.ecx), "=m" (regs.edx) 49 : "=m" (regs.eax), "=m" (regs.ebx), "=m" (regs.ecx), "=m" (regs.edx)
50 : "g" (func) 50 : "g" (func)
51 : "%eax", "%ecx", "%edx"); 51 : "%eax", "%ecx", "%edx");
52 return regs; 52 return regs;
53 } 53 }
54 54
55 55
56 static int64_t 56 static int64_t
57 rdtsc(void) 57 rdtsc(void)
58 { 58 {
59 unsigned int i, j; 59 unsigned int i, j;
60 #define RDTSC ".byte 0x0f, 0x31; " 60 #define RDTSC ".byte 0x0f, 0x31; "
61 asm(RDTSC : "=a"(i), "=d"(j) : ); 61 asm(RDTSC : "=a"(i), "=d"(j) : );
62 return ((int64_t)j<<32) + (int64_t)i; 62 return ((int64_t)j<<32) + (int64_t)i;
63 } 63 }
64 64
65 65
66 static void 66 static void
67 store32(char *d, unsigned int v) 67 store32(char *d, unsigned int v)
68 { 68 {
69 d[0] = v & 0xff; 69 d[0] = v & 0xff;
70 d[1] = (v >> 8) & 0xff; 70 d[1] = (v >> 8) & 0xff;
71 d[2] = (v >> 16) & 0xff; 71 d[2] = (v >> 16) & 0xff;
72 d[3] = (v >> 24) & 0xff; 72 d[3] = (v >> 24) & 0xff;
73 } 73 }
74 74
75 75
76 int 76 int
77 main(int argc, char **argv) 77 main(int argc, char **argv)
78 { 78 {
79 cpuid_regs_t regs, regs_ext; 79 cpuid_regs_t regs, regs_ext;
80 char idstr[13]; 80 char idstr[13];
81 unsigned max_cpuid; 81 unsigned max_cpuid;
82 unsigned max_ext_cpuid; 82 unsigned max_ext_cpuid;
83 unsigned int amd_flags; 83 unsigned int amd_flags;
84 unsigned int amd_flags2; 84 unsigned int amd_flags2;
85 char *model_name = "Unknown CPU"; 85 char *model_name = "Unknown CPU";
86 int i; 86 int i;
87 char processor_name[49]; 87 char processor_name[49];
88 88
89 regs = cpuid(0); 89 regs = cpuid(0);
90 max_cpuid = regs.eax; 90 max_cpuid = regs.eax;
91 /* printf("%d CPUID function codes\n", max_cpuid+1); */ 91 /* printf("%d CPUID function codes\n", max_cpuid+1); */
92 92
93 store32(idstr+0, regs.ebx); 93 store32(idstr+0, regs.ebx);
94 store32(idstr+4, regs.edx); 94 store32(idstr+4, regs.edx);
95 store32(idstr+8, regs.ecx); 95 store32(idstr+8, regs.ecx);
96 idstr[12] = 0; 96 idstr[12] = 0;
97 printf("vendor_id\t: %s\n", idstr); 97 printf("vendor_id\t: %s\n", idstr);
98 98
99 if (strcmp(idstr, "GenuineIntel") == 0) 99 if (strcmp(idstr, "GenuineIntel") == 0)
100 model_name = "Unknown Intel CPU"; 100 model_name = "Unknown Intel CPU";
101 else if (strcmp(idstr, "AuthenticAMD") == 0) 101 else if (strcmp(idstr, "AuthenticAMD") == 0)
102 model_name = "Unknown AMD CPU"; 102 model_name = "Unknown AMD CPU";
103 103
104 regs_ext = cpuid((1<<31) + 0); 104 regs_ext = cpuid((1<<31) + 0);
105 max_ext_cpuid = regs_ext.eax; 105 max_ext_cpuid = regs_ext.eax;
106 if (max_ext_cpuid >= (1<<31) + 1) { 106 if (max_ext_cpuid >= (1<<31) + 1) {
107 regs_ext = cpuid((1<<31) + 1); 107 regs_ext = cpuid((1<<31) + 1);
108 amd_flags = regs_ext.edx; 108 amd_flags = regs_ext.edx;
109 amd_flags2 = regs_ext.ecx; 109 amd_flags2 = regs_ext.ecx;
110 110
111 if (max_ext_cpuid >= (1<<31) + 4) { 111 if (max_ext_cpuid >= (1<<31) + 4) {
112 for (i = 2; i <= 4; i++) { 112 for (i = 2; i <= 4; i++) {
113 regs_ext = cpuid((1<<31) + i); 113 regs_ext = cpuid((1<<31) + i);
114 store32(processor_name + (i-2)*16, regs_ext.eax); 114 store32(processor_name + (i-2)*16, regs_ext.eax);
115 store32(processor_name + (i-2)*16 + 4, regs_ext.ebx); 115 store32(processor_name + (i-2)*16 + 4, regs_ext.ebx);
116 store32(processor_name + (i-2)*16 + 8, regs_ext.ecx); 116 store32(processor_name + (i-2)*16 + 8, regs_ext.ecx);
117 store32(processor_name + (i-2)*16 + 12, regs_ext.edx); 117 store32(processor_name + (i-2)*16 + 12, regs_ext.edx);
118 } 118 }
119 processor_name[48] = 0; 119 processor_name[48] = 0;
120 model_name = processor_name; 120 model_name = processor_name;
121 } 121 }
122 } else { 122 } else {
123 amd_flags = 0; 123 amd_flags = 0;
124 amd_flags2 = 0; 124 amd_flags2 = 0;
125 } 125 }
126 126
127 if (max_cpuid >= 1) { 127 if (max_cpuid >= 1) {
128 static struct { 128 static struct {
129 int bit; 129 int bit;
130 char *desc;; 130 char *desc;;
131 char *description; 131 char *description;
132 } cap[] = { 132 } cap[] = {
133 { 0, "fpu", "Floating-point unit on-chip" }, 133 { 0, "fpu", "Floating-point unit on-chip" },
134 { 1, "vme", "Virtual Mode Enhancements" }, 134 { 1, "vme", "Virtual Mode Enhancements" },
135 { 2, "de", "Debugging Extension" }, 135 { 2, "de", "Debugging Extension" },
136 { 3, "pse", "Page Size Extension" }, 136 { 3, "pse", "Page Size Extension" },
137 { 4, "tsc", "Time Stamp Counter" }, 137 { 4, "tsc", "Time Stamp Counter" },
138 { 5, "msr", "Pentium Processor MSR" }, 138 { 5, "msr", "Pentium Processor MSR" },
139 { 6, "pae", "Physical Address Extension" }, 139 { 6, "pae", "Physical Address Extension" },
140 { 7, "mce", "Machine Check Exception" }, 140 { 7, "mce", "Machine Check Exception" },
141 { 8, "cx8", "CMPXCHG8B Instruction Supported" }, 141 { 8, "cx8", "CMPXCHG8B Instruction Supported" },
142 { 9, "apic", "On-chip CPIC Hardware Enabled" }, 142 { 9, "apic", "On-chip CPIC Hardware Enabled" },
143 { 11, "sep", "SYSENTER and SYSEXIT" }, 143 { 11, "sep", "SYSENTER and SYSEXIT" },
144 { 12, "mtrr", "Memory Type Range Registers" }, 144 { 12, "mtrr", "Memory Type Range Registers" },
145 { 13, "pge", "PTE Global Bit" }, 145 { 13, "pge", "PTE Global Bit" },
146 { 14, "mca", "Machine Check Architecture" }, 146 { 14, "mca", "Machine Check Architecture" },
147 { 15, "cmov", "Conditional Move/Compare Instruction" }, 147 { 15, "cmov", "Conditional Move/Compare Instruction" },
148 { 16, "pat", "Page Attribute Table" }, 148 { 16, "pat", "Page Attribute Table" },
149 { 17, "pse36", "Page Size Extension 36-bit" }, 149 { 17, "pse36", "Page Size Extension 36-bit" },
150 { 18, "psn", "Processor Serial Number" }, 150 { 18, "psn", "Processor Serial Number" },
151 { 19, "cflsh", "CFLUSH instruction" }, 151 { 19, "cflsh", "CFLUSH instruction" },
152 { 21, "ds", "Debug Store" }, 152 { 21, "ds", "Debug Store" },
153 { 22, "acpi", "Thermal Monitor and Clock Ctrl" }, 153 { 22, "acpi", "Thermal Monitor and Clock Ctrl" },
154 { 23, "mmx", "MMX Technology" }, 154 { 23, "mmx", "MMX Technology" },
155 { 24, "fxsr", "FXSAVE/FXRSTOR" }, 155 { 24, "fxsr", "FXSAVE/FXRSTOR" },
156 { 25, "sse", "SSE Extensions" }, 156 { 25, "sse", "SSE Extensions" },
157 { 26, "sse2", "SSE2 Extensions" }, 157 { 26, "sse2", "SSE2 Extensions" },
158 { 27, "ss", "Self Snoop" }, 158 { 27, "ss", "Self Snoop" },
159 { 28, "htt", "Multi-threading" }, 159 { 28, "htt", "Multi-threading" },
160 { 29, "tm", "Therm. Monitor" }, 160 { 29, "tm", "Therm. Monitor" },
161 { 30, "ia64", "IA-64 Processor" }, 161 { 30, "ia64", "IA-64 Processor" },
162 { 31, "pbe", "Pend. Brk. EN." }, 162 { 31, "pbe", "Pend. Brk. EN." },
163 { -1 } 163 { -1 }
164 }; 164 };
165 static struct { 165 static struct {
166 int bit; 166 int bit;
167 char *desc; 167 char *desc;
168 char *description; 168 char *description;
169 } cap2[] = { 169 } cap2[] = {
170 { 0, "sse3", "SSE3 Extensions" }, 170 { 0, "sse3", "SSE3 Extensions" },
171 { 3, "monitor", "MONITOR/MWAIT" }, 171 { 3, "monitor", "MONITOR/MWAIT" },
172 { 4, "ds-cpl", "CPL Qualified Debug Store" }, 172 { 4, "ds-cpl", "CPL Qualified Debug Store" },
173 { 5, "vmx", "Virtual Machine Extensions" }, 173 { 5, "vmx", "Virtual Machine Extensions" },
174 { 7, "est", "Enhanced Intel SpeedStep Technology" }, 174 { 7, "est", "Enhanced Intel SpeedStep Technology" },
175 { 8, "tm2", "Thermal Monitor 2" }, 175 { 8, "tm2", "Thermal Monitor 2" },
176 { 10, "cnxt-id", "L1 Context ID" }, 176 { 10, "cnxt-id", "L1 Context ID" },
177 { 13, "cmpxchg16b", "CMPXCHG16B Available" }, 177 { 13, "cmpxchg16b", "CMPXCHG16B Available" },
178 { -1 } 178 { -1 }
179 }; 179 };
180 static struct { 180 static struct {
181 int bit; 181 int bit;
182 char *desc;; 182 char *desc;;
183 char *description; 183 char *description;
184 } cap_amd[] = { 184 } cap_amd[] = {
185 { 11, "syscall", "SYSCALL and SYSRET" }, 185 { 11, "syscall", "SYSCALL and SYSRET" },
186 { 19, "mp", "MP Capable" }, 186 { 19, "mp", "MP Capable" },
187 { 20, "nx", "No-Execute Page Protection" }, 187 { 20, "nx", "No-Execute Page Protection" },
188 { 22, "mmxext","MMX Technology (AMD Extensions)" }, 188 { 22, "mmxext","MMX Technology (AMD Extensions)" },
189 { 25, "fxsr_opt", "Fast FXSAVE/FXRSTOR" }, 189 { 25, "fxsr_opt", "Fast FXSAVE/FXRSTOR" },
190 { 27, "rdtscp", "RDTSCP Instruction" }, 190 { 27, "rdtscp", "RDTSCP Instruction" },
191 { 30, "3dnowext","3Dnow! Extensions" }, 191 { 30, "3dnowext","3Dnow! Extensions" },
192 { 31, "3dnow", "3Dnow!" }, 192 { 31, "3dnow", "3Dnow!" },
193 { -1 } 193 { -1 }
194 }; 194 };
195 static struct { 195 static struct {
196 int bit; 196 int bit;
197 char *desc; 197 char *desc;
198 char *description; 198 char *description;
199 } cap_amd2[] = { 199 } cap_amd2[] = {
200 { 0, "lahf_lm", "LAHF/SAHF Supported in 64-bit Mode" }, 200 { 0, "lahf_lm", "LAHF/SAHF Supported in 64-bit Mode" },
201 { 1, "cmp_legacy", "Chip Multi-Core" }, 201 { 1, "cmp_legacy", "Chip Multi-Core" },
202 { 2, "svm", "Secure Virtual Machine" }, 202 { 2, "svm", "Secure Virtual Machine" },
203 { 4, "cr8", "CR8 Available in Legacy Mode" }, 203 { 4, "cr8", "CR8 Available in Legacy Mode" },
204 { -1 } 204 { -1 }
205 }; 205 };
206 unsigned int family, model, stepping; 206 unsigned int family, model, stepping;
207 207
208 regs = cpuid(1); 208 regs = cpuid(1);
209 printf("cpu family\t: %d\n" 209 printf("cpu family\t: %d\n"
210 "model\t\t: %d\n" 210 "model\t\t: %d\n"
211 "stepping\t: %d\n" , 211 "stepping\t: %d\n" ,
212 family = (regs.eax >> 8) & 0xf, 212 family = (regs.eax >> 8) & 0xf,
213 model = (regs.eax >> 4) & 0xf, 213 model = (regs.eax >> 4) & 0xf,
214 stepping = regs.eax & 0xf); 214 stepping = regs.eax & 0xf);
215 215
216 printf("flags\t\t:"); 216 printf("flags\t\t:");
217 for (i = 0; cap[i].bit >= 0; i++) { 217 for (i = 0; cap[i].bit >= 0; i++) {
218 if (regs.edx & (1 << cap[i].bit)) { 218 if (regs.edx & (1 << cap[i].bit)) {
219 printf(" %s", cap[i].desc); 219 printf(" %s", cap[i].desc);
220 } 220 }
221 } 221 }
222 for (i = 0; cap2[i].bit >= 0; i++) { 222 for (i = 0; cap2[i].bit >= 0; i++) {
223 if (regs.ecx & (1 << cap[i].bit)) { 223 if (regs.ecx & (1 << cap[i].bit)) {
224 printf(" %s", cap2[i].desc); 224 printf(" %s", cap2[i].desc);
225 } 225 }
226 } 226 }
227 /* k6_mtrr is supported by some AMD K6-2/K6-III CPUs but 227 /* k6_mtrr is supported by some AMD K6-2/K6-III CPUs but
228 it is not indicated by a CPUID feature bit, so we 228 it is not indicated by a CPUID feature bit, so we
229 have to check the family, model and stepping instead. */ 229 have to check the family, model and stepping instead. */
230 if (strstr(idstr, "AMD") && 230 if (strstr(idstr, "AMD") &&
231 family == 5 && 231 family == 5 &&
232 (model >= 9 || model == 8 && stepping >= 8)) 232 (model >= 9 || model == 8 && stepping >= 8))
233 printf(" %s", "k6_mtrr"); 233 printf(" %s", "k6_mtrr");
234 234
235 for (i = 0; cap_amd[i].bit >= 0; i++) { 235 for (i = 0; cap_amd[i].bit >= 0; i++) {
236 if (amd_flags & (1 << cap_amd[i].bit)) { 236 if (amd_flags & (1 << cap_amd[i].bit)) {
237 printf(" %s", cap_amd[i].desc); 237 printf(" %s", cap_amd[i].desc);
238 } 238 }
239 } 239 }
240 for (i = 0; cap_amd2[i].bit >= 0; i++) { 240 for (i = 0; cap_amd2[i].bit >= 0; i++) {
241 if (amd_flags2 & (1 << cap_amd2[i].bit)) { 241 if (amd_flags2 & (1 << cap_amd2[i].bit)) {
242 printf(" %s", cap_amd2[i].desc); 242 printf(" %s", cap_amd2[i].desc);
243 } 243 }
244 } 244 }
245 printf("\n"); 245 printf("\n");
246 246
247 if (regs.edx & (1 << 4)) { 247 if (regs.edx & (1 << 4)) {
248 int64_t tsc_start, tsc_end; 248 int64_t tsc_start, tsc_end;
249 struct timeval tv_start, tv_end; 249 struct timeval tv_start, tv_end;
250 int usec_delay; 250 int usec_delay;
251 251
252 tsc_start = rdtsc(); 252 tsc_start = rdtsc();
253 gettimeofday(&tv_start, NULL); 253 gettimeofday(&tv_start, NULL);
254 #ifdef MISSING_USLEEP 254 #ifdef MISSING_USLEEP
255 sleep(1); 255 sleep(1);
256 #else 256 #else
257 usleep(100000); 257 usleep(100000);
258 #endif 258 #endif
259 tsc_end = rdtsc(); 259 tsc_end = rdtsc();
260 gettimeofday(&tv_end, NULL); 260 gettimeofday(&tv_end, NULL);
261 261
262 usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec) 262 usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec)
263 + (tv_end.tv_usec - tv_start.tv_usec); 263 + (tv_end.tv_usec - tv_start.tv_usec);
264 264
265 printf("cpu MHz\t\t: %.3f\n", 265 printf("cpu MHz\t\t: %.3f\n",
266 (double)(tsc_end-tsc_start) / usec_delay); 266 (double)(tsc_end-tsc_start) / usec_delay);
267 } 267 }
268 } 268 }
269 269
270 printf("model name\t: %s\n", model_name); 270 printf("model name\t: %s\n", model_name);
271 271
272 exit(0); 272 exit(0);
273 } 273 }