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