1 /*-
2 * Copyright (c) 1992 Terrence R. Lambert.
3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
4 * Copyright (c) 1997 KATO Takenori.
5 * Copyright (c) 2001 Tamotsu Hattori.
6 * Copyright (c) 2001 Mitsuru IWASAKI.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * William Jolitz.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
41 */
42
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD: releng/5.2/sys/amd64/amd64/identcpu.c 122940 2003-11-21 03:02:00Z peter $");
45
46 #include "opt_cpu.h"
47
48 #include <sys/param.h>
49 #include <sys/bus.h>
50 #include <sys/systm.h>
51 #include <sys/kernel.h>
52 #include <sys/sysctl.h>
53 #include <sys/power.h>
54
55 #include <machine/asmacros.h>
56 #include <machine/clock.h>
57 #include <machine/cputypes.h>
58 #include <machine/frame.h>
59 #include <machine/intr_machdep.h>
60 #include <machine/segments.h>
61 #include <machine/specialreg.h>
62 #include <machine/md_var.h>
63
64 #include <amd64/isa/icu.h>
65
66 /* XXX - should be in header file: */
67 void printcpuinfo(void);
68 void identify_cpu(void);
69 void earlysetcpuclass(void);
70 void panicifcpuunsupported(void);
71
72 static void print_AMD_features(void);
73 static void print_AMD_info(void);
74 static void print_AMD_assoc(int i);
75
76 int cpu_class;
77 u_int cpu_exthigh; /* Highest arg to extended CPUID */
78 char machine[] = "amd64";
79 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
80 machine, 0, "Machine class");
81
82 static char cpu_model[128];
83 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD,
84 cpu_model, 0, "Machine model");
85
86 static int hw_clockrate;
87 SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD,
88 &hw_clockrate, 0, "CPU instruction clock rate");
89
90 static char cpu_brand[48];
91
92 static struct cpu_nameclass amd64_cpus[] = {
93 { "Clawhammer", CPUCLASS_K8 }, /* CPU_CLAWHAMMER */
94 { "Sledgehammer", CPUCLASS_K8 }, /* CPU_SLEDGEHAMMER */
95 };
96
97 void
98 printcpuinfo(void)
99 {
100 u_int regs[4], i;
101 char *brand;
102
103 cpu_class = amd64_cpus[cpu].cpu_class;
104 printf("CPU: ");
105 strncpy(cpu_model, amd64_cpus[cpu].cpu_name, sizeof (cpu_model));
106
107 /* Check for extended CPUID information and a processor name. */
108 if (cpu_high > 0 &&
109 (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
110 strcmp(cpu_vendor, "AuthenticAMD") == 0)) {
111 do_cpuid(0x80000000, regs);
112 if (regs[0] >= 0x80000000) {
113 cpu_exthigh = regs[0];
114 if (cpu_exthigh >= 0x80000004) {
115 brand = cpu_brand;
116 for (i = 0x80000002; i < 0x80000005; i++) {
117 do_cpuid(i, regs);
118 memcpy(brand, regs, sizeof(regs));
119 brand += sizeof(regs);
120 }
121 }
122 }
123 }
124
125 if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
126 /* How the hell did you get here?? */
127 strcat(cpu_model, "Yamhill?");
128 } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
129 /*
130 * Values taken from AMD Processor Recognition
131 * http://www.amd.com/K6/k6docs/pdf/20734g.pdf
132 * (also describes ``Features'' encodings.
133 */
134 strcpy(cpu_model, "AMD ");
135 switch (cpu_id & 0xF00) {
136 case 0xf00:
137 strcat(cpu_model, "AMD64 Processor");
138 break;
139 default:
140 strcat(cpu_model, "Unknown");
141 break;
142 }
143 }
144
145 /*
146 * Replace cpu_model with cpu_brand minus leading spaces if
147 * we have one.
148 */
149 brand = cpu_brand;
150 while (*brand == ' ')
151 ++brand;
152 if (*brand != '\0')
153 strcpy(cpu_model, brand);
154
155 printf("%s (", cpu_model);
156 switch(cpu_class) {
157 case CPUCLASS_K8:
158 hw_clockrate = (tsc_freq + 5000) / 1000000;
159 printf("%jd.%02d-MHz ",
160 (intmax_t)(tsc_freq + 4999) / 1000000,
161 (u_int)((tsc_freq + 4999) / 10000) % 100);
162 printf("K8");
163 break;
164 default:
165 printf("Unknown"); /* will panic below... */
166 }
167 printf("-class CPU)\n");
168 if(*cpu_vendor)
169 printf(" Origin = \"%s\"",cpu_vendor);
170 if(cpu_id)
171 printf(" Id = 0x%x", cpu_id);
172
173 if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
174 strcmp(cpu_vendor, "AuthenticAMD") == 0) {
175 printf(" Stepping = %u", cpu_id & 0xf);
176 if (cpu_high > 0) {
177 /*
178 * Here we should probably set up flags indicating
179 * whether or not various features are available.
180 * The interesting ones are probably VME, PSE, PAE,
181 * and PGE. The code already assumes without bothering
182 * to check that all CPUs >= Pentium have a TSC and
183 * MSRs.
184 */
185 printf("\n Features=0x%b", cpu_feature,
186 "\020"
187 "\001FPU" /* Integral FPU */
188 "\002VME" /* Extended VM86 mode support */
189 "\003DE" /* Debugging Extensions (CR4.DE) */
190 "\004PSE" /* 4MByte page tables */
191 "\005TSC" /* Timestamp counter */
192 "\006MSR" /* Machine specific registers */
193 "\007PAE" /* Physical address extension */
194 "\010MCE" /* Machine Check support */
195 "\011CX8" /* CMPEXCH8 instruction */
196 "\012APIC" /* SMP local APIC */
197 "\013oldMTRR" /* Previous implementation of MTRR */
198 "\014SEP" /* Fast System Call */
199 "\015MTRR" /* Memory Type Range Registers */
200 "\016PGE" /* PG_G (global bit) support */
201 "\017MCA" /* Machine Check Architecture */
202 "\020CMOV" /* CMOV instruction */
203 "\021PAT" /* Page attributes table */
204 "\022PSE36" /* 36 bit address space support */
205 "\023PN" /* Processor Serial number */
206 "\024CLFLUSH" /* Has the CLFLUSH instruction */
207 "\025<b20>"
208 "\026DTS" /* Debug Trace Store */
209 "\027ACPI" /* ACPI support */
210 "\030MMX" /* MMX instructions */
211 "\031FXSR" /* FXSAVE/FXRSTOR */
212 "\032SSE" /* Streaming SIMD Extensions */
213 "\033SSE2" /* Streaming SIMD Extensions #2 */
214 "\034SS" /* Self snoop */
215 "\035HTT" /* Hyperthreading (see EBX bit 16-23) */
216 "\036TM" /* Thermal Monitor clock slowdown */
217 "\037IA64" /* CPU can execute IA64 instructions */
218 "\040PBE" /* Pending Break Enable */
219 );
220
221 /*
222 * If this CPU supports hyperthreading then mention
223 * the number of logical CPU's it contains.
224 */
225 if (cpu_feature & CPUID_HTT &&
226 (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1)
227 printf("\n Hyperthreading: %d logical CPUs",
228 (cpu_procinfo & CPUID_HTT_CORES) >> 16);
229 }
230 if (strcmp(cpu_vendor, "AuthenticAMD") == 0 &&
231 cpu_exthigh >= 0x80000001)
232 print_AMD_features();
233 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
234 }
235 /* Avoid ugly blank lines: only print newline when we have to. */
236 if (*cpu_vendor || cpu_id)
237 printf("\n");
238
239 if (!bootverbose)
240 return;
241
242 if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
243 print_AMD_info();
244 }
245
246 void
247 panicifcpuunsupported(void)
248 {
249
250 #ifndef HAMMER
251 #error "You need to specify a cpu type"
252 #endif
253 /*
254 * Now that we have told the user what they have,
255 * let them know if that machine type isn't configured.
256 */
257 switch (cpu_class) {
258 case CPUCLASS_X86:
259 #ifndef HAMMER
260 case CPUCLASS_K8:
261 #endif
262 panic("CPU class not configured");
263 default:
264 break;
265 }
266 }
267
268
269 /*
270 * Final stage of CPU identification. -- Should I check TI?
271 */
272 void
273 identify_cpu(void)
274 {
275 u_int regs[4];
276
277 do_cpuid(0, regs);
278 cpu_high = regs[0];
279 ((u_int *)&cpu_vendor)[0] = regs[1];
280 ((u_int *)&cpu_vendor)[1] = regs[3];
281 ((u_int *)&cpu_vendor)[2] = regs[2];
282 cpu_vendor[12] = '\0';
283
284 do_cpuid(1, regs);
285 cpu_id = regs[0];
286 cpu_procinfo = regs[1];
287 cpu_feature = regs[3];
288
289 /* XXX */
290 cpu = CPU_CLAWHAMMER;
291 }
292
293 static void
294 print_AMD_assoc(int i)
295 {
296 if (i == 255)
297 printf(", fully associative\n");
298 else
299 printf(", %d-way associative\n", i);
300 }
301
302 static void
303 print_AMD_info(void)
304 {
305
306 if (cpu_exthigh >= 0x80000005) {
307 u_int regs[4];
308
309 do_cpuid(0x80000005, regs);
310 printf("Data TLB: %d entries", (regs[1] >> 16) & 0xff);
311 print_AMD_assoc(regs[1] >> 24);
312 printf("Instruction TLB: %d entries", regs[1] & 0xff);
313 print_AMD_assoc((regs[1] >> 8) & 0xff);
314 printf("L1 data cache: %d kbytes", regs[2] >> 24);
315 printf(", %d bytes/line", regs[2] & 0xff);
316 printf(", %d lines/tag", (regs[2] >> 8) & 0xff);
317 print_AMD_assoc((regs[2] >> 16) & 0xff);
318 printf("L1 instruction cache: %d kbytes", regs[3] >> 24);
319 printf(", %d bytes/line", regs[3] & 0xff);
320 printf(", %d lines/tag", (regs[3] >> 8) & 0xff);
321 print_AMD_assoc((regs[3] >> 16) & 0xff);
322 if (cpu_exthigh >= 0x80000006) { /* K6-III only */
323 do_cpuid(0x80000006, regs);
324 printf("L2 internal cache: %d kbytes", regs[2] >> 16);
325 printf(", %d bytes/line", regs[2] & 0xff);
326 printf(", %d lines/tag", (regs[2] >> 8) & 0x0f);
327 print_AMD_assoc((regs[2] >> 12) & 0x0f);
328 }
329 }
330 }
331
332 static void
333 print_AMD_features(void)
334 {
335 u_int regs[4];
336
337 /*
338 * Values taken from AMD Processor Recognition
339 * http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf
340 */
341 do_cpuid(0x80000001, regs);
342 printf("\n AMD Features=0x%b", regs[3] &~ cpu_feature,
343 "\020" /* in hex */
344 "\001FPU" /* Integral FPU */
345 "\002VME" /* Extended VM86 mode support */
346 "\003DE" /* Debug extensions */
347 "\004PSE" /* 4MByte page tables */
348 "\005TSC" /* Timestamp counter */
349 "\006MSR" /* Machine specific registers */
350 "\007PAE" /* Physical address extension */
351 "\010MCE" /* Machine Check support */
352 "\011CX8" /* CMPEXCH8 instruction */
353 "\012APIC" /* SMP local APIC */
354 "\013<b10>"
355 "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */
356 "\015MTRR" /* Memory Type Range Registers */
357 "\016PGE" /* PG_G (global bit) support */
358 "\017MCA" /* Machine Check Architecture */
359 "\020ICMOV" /* CMOV instruction */
360 "\021PAT" /* Page attributes table */
361 "\022PGE36" /* 36 bit address space support */
362 "\023RSVD" /* Reserved, unknown */
363 "\024MP" /* Multiprocessor Capable */
364 "\025NX" /* Has EFER.NXE, NX (no execute pte bit) */
365 "\026<b21>"
366 "\027MMX+" /* AMD MMX Instruction Extensions */
367 "\030MMX"
368 "\031FXSAVE" /* FXSAVE/FXRSTOR */
369 "\032<b25>"
370 "\033<b26>"
371 "\034<b27>"
372 "\035<b28>"
373 "\036LM" /* Long mode */
374 "\0373DNow!+" /* AMD 3DNow! Instruction Extensions */
375 "\0403DNow!" /* AMD 3DNow! Instructions */
376 );
377 }
Cache object: c2980fcd82113ef69aa4e787a88c5132
|