comparison TOOLS/cpuinfo.c @ 1038:b36fb1ae4b53

applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
author arpi_esp
date Tue, 05 Jun 2001 18:40:44 +0000
parents
children d7a83bb5fec9
comparison
equal deleted inserted replaced
1037:2767682b85de 1038:b36fb1ae4b53
1
2 #include <stdio.h>
3 #include <sys/time.h>
4
5 #ifdef M_UNIX
6 typedef long long int64_t;
7 #define MISSING_USLEEP
8 #else
9 #include <inttypes.h>
10 #endif
11
12
13 typedef struct cpuid_regs {
14 unsigned int eax;
15 unsigned int ebx;
16 unsigned int ecx;
17 unsigned int edx;
18 } cpuid_regs_t;
19
20 static cpuid_regs_t
21 cpuid(int func) {
22 cpuid_regs_t regs;
23 #define CPUID ".byte 0x0f, 0xa2; "
24 asm("movl %4,%%eax; " CPUID
25 "movl %%eax,%0; movl %%ebx,%1; movl %%ecx,%2; movl %%edx,%3"
26 : "=m" (regs.eax), "=m" (regs.ebx), "=m" (regs.ecx), "=m" (regs.edx)
27 : "g" (func)
28 : "%eax", "%ebx", "%ecx", "%edx");
29 return regs;
30 }
31
32
33 static int64_t
34 rdtsc(void)
35 {
36 unsigned int i, j;
37 #define RDTSC ".byte 0x0f, 0x31; "
38 asm(RDTSC : "=a"(i), "=d"(j) : );
39 return ((int64_t)j<<32) + (int64_t)i;
40 }
41
42
43 static void
44 store32(char *d, unsigned int v)
45 {
46 d[0] = v & 0xff;
47 d[1] = (v >> 8) & 0xff;
48 d[2] = (v >> 16) & 0xff;
49 d[3] = (v >> 24) & 0xff;
50 }
51
52
53 int
54 main(int argc, char **argv)
55 {
56 cpuid_regs_t regs, regs_ext;
57 char idstr[13];
58 unsigned max_cpuid;
59 unsigned max_ext_cpuid;
60 unsigned int amd_flags;
61 char *model_name = "Unknown CPU";
62 int i;
63 char processor_name[49];
64
65 regs = cpuid(0);
66 max_cpuid = regs.eax;
67 /* printf("%d CPUID function codes\n", max_cpuid+1); */
68
69 store32(idstr+0, regs.ebx);
70 store32(idstr+4, regs.edx);
71 store32(idstr+8, regs.ecx);
72 idstr[12] = 0;
73 printf("vendor_id\t: %s\n", idstr);
74
75 if (strcmp(idstr, "GenuineIntel") == 0)
76 model_name = "Unknown Intel CPU";
77 else if (strcmp(idstr, "AuthenticAMD") == 0)
78 model_name = "Unknown AMD CPU";
79
80 regs_ext = cpuid((1<<31) + 0);
81 max_ext_cpuid = regs_ext.eax;
82 if (max_ext_cpuid >= (1<<31) + 1) {
83 regs_ext = cpuid((1<<31) + 1);
84 amd_flags = regs_ext.edx;
85
86 if (max_ext_cpuid >= (1<<31) + 4) {
87 for (i = 2; i <= 4; i++) {
88 regs_ext = cpuid((1<<31) + i);
89 store32(processor_name + (i-2)*16, regs_ext.eax);
90 store32(processor_name + (i-2)*16 + 4, regs_ext.ebx);
91 store32(processor_name + (i-2)*16 + 8, regs_ext.ecx);
92 store32(processor_name + (i-2)*16 + 12, regs_ext.edx);
93 }
94 processor_name[48] = 0;
95 model_name = processor_name;
96 }
97 } else {
98 amd_flags = 0;
99 }
100
101 if (max_cpuid >= 1) {
102 static struct {
103 int bit;
104 char *desc;;
105 char *description;
106 } cap[] = {
107 { 0, "fpu", "Floating-point unit on-chip" },
108 { 1, "vme", "Virtual Mode Enhancements" },
109 { 2, "de", "Debugging Extension" },
110 { 3, "pse", "Page Size Extension" },
111 { 4, "tsc", "Time Stamp Counter" },
112 { 5, "msr", "Pentium Processor MSR" },
113 { 6, "pae", "Physical Address Extension" },
114 { 7, "mce", "Machine Check Exception" },
115 { 8, "cx8", "CMPXCHG8B Instruction Supported" },
116 { 9, "apic", "On-chip CPIC Hardware Enabled" },
117 { 11, "sep", "SYSENTER and SYSEXIT" },
118 { 12, "mtrr", "Memory Type Range Registers" },
119 { 13, "pge", "PTE Global Bit" },
120 { 14, "mca", "Machine Check Architecture" },
121 { 15, "cmov", "Conditional Move/Compare Instruction" },
122 { 16, "pat", "Page Attribute Table" },
123 { 17, "pse", "Page Size Extension" },
124 { 18, "psn", "Processor Serial Number" },
125 { 19, "cflsh", "CFLUSH instruction" },
126 { 21, "ds", "Debug Store" },
127 { 22, "acpi", "Thermal Monitor and Clock Ctrl" },
128 { 23, "mmx", "MMX Technology" },
129 { 24, "fxsr", "FXSAVE/FXRSTOR" },
130 { 25, "sse", "SSE Extensions" },
131 { 26, "sse2", "SSE2 Extensions" },
132 { 27, "ss", "Self Snoop" },
133 { 29, "tm", "Therm. Monitor" },
134 { -1 }
135 };
136 static struct {
137 int bit;
138 char *desc;;
139 char *description;
140 } cap_amd[] = {
141 { 22, "mmxext","MMX Technology (AMD Extensions)" },
142 { 30, "3dnowext","3Dnow! Extensions" },
143 { 31, "3dnow", "3Dnow!" },
144 { -1 }
145 };
146 int i;
147
148 regs = cpuid(1);
149 printf("cpu family\t: %d\n"
150 "model\t\t: %d\n"
151 "stepping\t: %d\n" ,
152 (regs.eax >> 8) & 0xf,
153 (regs.eax >> 4) & 0xf,
154 regs.eax & 0xf);
155
156 printf("flags\t\t:");
157 for (i = 0; cap[i].bit >= 0; i++) {
158 if (regs.edx & (1 << cap[i].bit)) {
159 printf(" %s", cap[i].desc);
160 }
161 }
162 for (i = 0; cap_amd[i].bit >= 0; i++) {
163 if (amd_flags & (1 << cap_amd[i].bit)) {
164 printf(" %s", cap_amd[i].desc);
165 }
166 }
167 printf("\n");
168
169 if (regs.edx & (1 << 4)) {
170 int64_t tsc_start, tsc_end;
171 struct timeval tv_start, tv_end;
172 int usec_delay;
173
174 tsc_start = rdtsc();
175 gettimeofday(&tv_start, NULL);
176 #ifdef MISSING_USLEEP
177 sleep(1);
178 #else
179 usleep(100000);
180 #endif
181 tsc_end = rdtsc();
182 gettimeofday(&tv_end, NULL);
183
184 usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec)
185 + (tv_end.tv_usec - tv_start.tv_usec);
186
187 printf("cpu MHz\t\t: %.3f\n",
188 (double)(tsc_end-tsc_start) / usec_delay);
189 }
190 }
191
192 printf("model name\t: %s\n", model_name);
193
194 exit(0);
195 }