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) 2008 The DragonFly Project.
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
40 * $DragonFly: src/sys/platform/pc64/amd64/identcpu.c,v 1.2 2008/11/24 13:14:21 swildner Exp $
45 #include <sys/param.h>
50 #include <sys/eventhandler.h>
51 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/sysctl.h>
54 #include <sys/power.h>
56 #include <machine/asmacros.h>
57 #include <machine/clock.h>
58 #include <machine/cputypes.h>
59 #include <machine/frame.h>
60 #include <machine/intr_machdep.h>
61 #include <machine/segments.h>
62 #include <machine/specialreg.h>
63 #include <machine/md_var.h>
66 #include <amd64/isa/icu.h>
69 /* XXX - should be in header file: */
70 void printcpuinfo(void);
71 void identify_cpu(void);
72 void earlysetcpuclass(void);
73 void panicifcpuunsupported(void);
75 static void print_AMD_info(void);
76 static void print_AMD_assoc(int i
);
79 char machine
[] = "amd64";
80 SYSCTL_STRING(_hw
, HW_MACHINE
, machine
, CTLFLAG_RD
,
81 machine
, 0, "Machine class");
83 static char cpu_model
[128];
84 SYSCTL_STRING(_hw
, HW_MODEL
, model
, CTLFLAG_RD
,
85 cpu_model
, 0, "Machine model");
87 static int hw_clockrate
;
88 SYSCTL_INT(_hw
, OID_AUTO
, clockrate
, CTLFLAG_RD
,
89 &hw_clockrate
, 0, "CPU instruction clock rate");
91 static char cpu_brand
[48];
97 { "Clawhammer", CPUCLASS_K8
}, /* CPU_CLAWHAMMER */
98 { "Sledgehammer", CPUCLASS_K8
}, /* CPU_SLEDGEHAMMER */
105 extern int pq_l2size
;
106 extern int pq_l2nways
;
114 cpu_class
= amd64_cpus
[cpu
].cpu_class
;
116 strncpy(cpu_model
, amd64_cpus
[cpu
].cpu_name
, sizeof (cpu_model
));
118 /* Check for extended CPUID information and a processor name. */
119 if (cpu_exthigh
>= 0x80000004) {
121 for (i
= 0x80000002; i
< 0x80000005; i
++) {
123 memcpy(brand
, regs
, sizeof(regs
));
124 brand
+= sizeof(regs
);
128 if (strcmp(cpu_vendor
, "GenuineIntel") == 0) {
129 /* Please make up your mind folks! */
130 strcat(cpu_model
, "EM64T");
131 } else if (strcmp(cpu_vendor
, "AuthenticAMD") == 0) {
133 * Values taken from AMD Processor Recognition
134 * http://www.amd.com/K6/k6docs/pdf/20734g.pdf
135 * (also describes ``Features'' encodings.
137 strcpy(cpu_model
, "AMD ");
138 switch (cpu_id
& 0xF00) {
140 strcat(cpu_model
, "AMD64 Processor");
143 strcat(cpu_model
, "Unknown");
149 * Replace cpu_model with cpu_brand minus leading spaces if
153 while (*brand
== ' ')
156 strcpy(cpu_model
, brand
);
158 kprintf("%s (", cpu_model
);
162 hw_clockrate
= (tsc_freq
+ 5000) / 1000000;
163 kprintf("%jd.%02d-MHz ",
164 (intmax_t)(tsc_freq
+ 4999) / 1000000,
165 (u_int
)((tsc_freq
+ 4999) / 10000) % 100);
170 kprintf("Unknown"); /* will panic below... */
172 kprintf("-class CPU)\n");
174 kprintf(" Origin = \"%s\"",cpu_vendor
);
176 kprintf(" Id = 0x%x", cpu_id
);
178 if (strcmp(cpu_vendor
, "GenuineIntel") == 0 ||
179 strcmp(cpu_vendor
, "AuthenticAMD") == 0) {
180 kprintf(" Stepping = %u", cpu_id
& 0xf);
182 u_int cmp
= 1, htt
= 1;
185 * Here we should probably set up flags indicating
186 * whether or not various features are available.
187 * The interesting ones are probably VME, PSE, PAE,
188 * and PGE. The code already assumes without bothering
189 * to check that all CPUs >= Pentium have a TSC and
192 kprintf("\n Features=0x%b", cpu_feature
,
194 "\001FPU" /* Integral FPU */
195 "\002VME" /* Extended VM86 mode support */
196 "\003DE" /* Debugging Extensions (CR4.DE) */
197 "\004PSE" /* 4MByte page tables */
198 "\005TSC" /* Timestamp counter */
199 "\006MSR" /* Machine specific registers */
200 "\007PAE" /* Physical address extension */
201 "\010MCE" /* Machine Check support */
202 "\011CX8" /* CMPEXCH8 instruction */
203 "\012APIC" /* SMP local APIC */
204 "\013oldMTRR" /* Previous implementation of MTRR */
205 "\014SEP" /* Fast System Call */
206 "\015MTRR" /* Memory Type Range Registers */
207 "\016PGE" /* PG_G (global bit) support */
208 "\017MCA" /* Machine Check Architecture */
209 "\020CMOV" /* CMOV instruction */
210 "\021PAT" /* Page attributes table */
211 "\022PSE36" /* 36 bit address space support */
212 "\023PN" /* Processor Serial number */
213 "\024CLFLUSH" /* Has the CLFLUSH instruction */
215 "\026DTS" /* Debug Trace Store */
216 "\027ACPI" /* ACPI support */
217 "\030MMX" /* MMX instructions */
218 "\031FXSR" /* FXSAVE/FXRSTOR */
219 "\032SSE" /* Streaming SIMD Extensions */
220 "\033SSE2" /* Streaming SIMD Extensions #2 */
221 "\034SS" /* Self snoop */
222 "\035HTT" /* Hyperthreading (see EBX bit 16-23) */
223 "\036TM" /* Thermal Monitor clock slowdown */
224 "\037IA64" /* CPU can execute IA64 instructions */
225 "\040PBE" /* Pending Break Enable */
228 if (cpu_feature2
!= 0) {
229 kprintf("\n Features2=0x%b", cpu_feature2
,
231 "\001SSE3" /* SSE3 */
233 "\003DTES64" /* 64-bit Debug Trace */
234 "\004MON" /* MONITOR/MWAIT Instructions */
235 "\005DS_CPL" /* CPL Qualified Debug Store */
236 "\006VMX" /* Virtual Machine Extensions */
237 "\007SMX" /* Safer Mode Extensions */
238 "\010EST" /* Enhanced SpeedStep */
239 "\011TM2" /* Thermal Monitor 2 */
240 "\012SSSE3" /* SSSE3 */
241 "\013CNXT-ID" /* L1 context ID available */
244 "\016CX16" /* CMPXCHG16B Instruction */
245 "\017xTPR" /* Send Task Priority Messages*/
246 "\020PDCM" /* Perf/Debug Capability MSR */
249 "\023DCA" /* Direct Cache Access */
252 "\026x2APIC" /* xAPIC Extensions */
253 "\027MOVBE" /* MOVBE instruction */
267 * AMD64 Architecture Programmer's Manual Volume 3:
268 * General-Purpose and System Instructions
269 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf
271 * IA-32 Intel Architecture Software Developer's Manual,
272 * Volume 2A: Instruction Set Reference, A-M
273 * ftp://download.intel.com/design/Pentium4/manuals/25366617.pdf
275 if (amd_feature
!= 0) {
276 kprintf("\n AMD Features=0x%b", amd_feature
,
278 "\001<s0>" /* Same */
279 "\002<s1>" /* Same */
280 "\003<s2>" /* Same */
281 "\004<s3>" /* Same */
282 "\005<s4>" /* Same */
283 "\006<s5>" /* Same */
284 "\007<s6>" /* Same */
285 "\010<s7>" /* Same */
286 "\011<s8>" /* Same */
287 "\012<s9>" /* Same */
288 "\013<b10>" /* Undefined */
289 "\014SYSCALL" /* Have SYSCALL/SYSRET */
290 "\015<s12>" /* Same */
291 "\016<s13>" /* Same */
292 "\017<s14>" /* Same */
293 "\020<s15>" /* Same */
294 "\021<s16>" /* Same */
295 "\022<s17>" /* Same */
296 "\023<b18>" /* Reserved, unknown */
297 "\024MP" /* Multiprocessor Capable */
298 "\025NX" /* Has EFER.NXE, NX */
299 "\026<b21>" /* Undefined */
300 "\027MMX+" /* AMD MMX Extensions */
301 "\030<s23>" /* Same */
302 "\031<s24>" /* Same */
303 "\032FFXSR" /* Fast FXSAVE/FXRSTOR */
304 "\033Page1GB" /* 1-GB large page support */
305 "\034RDTSCP" /* RDTSCP */
306 "\035<b28>" /* Undefined */
307 "\036LM" /* 64 bit long mode */
308 "\0373DNow!+" /* AMD 3DNow! Extensions */
309 "\0403DNow!" /* AMD 3DNow! */
313 if (amd_feature2
!= 0) {
314 kprintf("\n AMD Features2=0x%b", amd_feature2
,
316 "\001LAHF" /* LAHF/SAHF in long mode */
317 "\002CMP" /* CMP legacy */
318 "\003SVM" /* Secure Virtual Mode */
319 "\004ExtAPIC" /* Extended APIC register */
320 "\005CR8" /* CR8 in legacy mode */
324 "\011Prefetch" /* 3DNow! Prefetch/PrefetchW */
351 if (cpu_feature
& CPUID_HTT
&& strcmp(cpu_vendor
,
352 "AuthenticAMD") == 0)
353 cpu_feature
&= ~CPUID_HTT
;
356 * If this CPU supports HTT or CMP then mention the
357 * number of physical/logical cores it contains.
359 if (cpu_feature
& CPUID_HTT
)
360 htt
= (cpu_procinfo
& CPUID_HTT_CORES
) >> 16;
361 if (strcmp(cpu_vendor
, "AuthenticAMD") == 0 &&
362 (amd_feature2
& AMDID2_CMP
))
363 cmp
= (cpu_procinfo2
& AMDID_CMP_CORES
) + 1;
364 else if (strcmp(cpu_vendor
, "GenuineIntel") == 0 &&
366 cpuid_count(4, 0, regs
);
367 if ((regs
[0] & 0x1f) != 0)
368 cmp
= ((regs
[0] >> 26) & 0x3f) + 1;
371 cpu_logical
= htt
/ cmp
;
373 kprintf("\n Cores per package: %d", cmp
);
375 kprintf("\n Logical CPUs per core: %d",
379 /* Avoid ugly blank lines: only print newline when we have to. */
380 if (*cpu_vendor
|| cpu_id
)
386 if (strcmp(cpu_vendor
, "AuthenticAMD") == 0)
391 panicifcpuunsupported(void)
395 #error "You need to specify a cpu type"
398 * Now that we have told the user what they have,
399 * let them know if that machine type isn't configured.
406 panic("CPU class not configured");
414 /* Update TSC freq with the value indicated by the caller. */
416 tsc_freq_changed(void *arg
, const struct cf_level
*level
, int status
)
418 /* If there was an error during the transition, don't do anything. */
422 /* Total setting for this level gives the new frequency in MHz. */
423 hw_clockrate
= level
->total_set
.freq
;
426 EVENTHANDLER_DEFINE(cpufreq_post_change
, tsc_freq_changed
, NULL
,
427 EVENTHANDLER_PRI_ANY
);
431 * Final stage of CPU identification. -- Should I check TI?
440 ((u_int
*)&cpu_vendor
)[0] = regs
[1];
441 ((u_int
*)&cpu_vendor
)[1] = regs
[3];
442 ((u_int
*)&cpu_vendor
)[2] = regs
[2];
443 cpu_vendor
[12] = '\0';
447 cpu_procinfo
= regs
[1];
448 cpu_feature
= regs
[3];
449 cpu_feature2
= regs
[2];
451 if (strcmp(cpu_vendor
, "GenuineIntel") == 0 ||
452 strcmp(cpu_vendor
, "AuthenticAMD") == 0) {
453 do_cpuid(0x80000000, regs
);
454 cpu_exthigh
= regs
[0];
456 if (cpu_exthigh
>= 0x80000001) {
457 do_cpuid(0x80000001, regs
);
458 amd_feature
= regs
[3] & ~(cpu_feature
& 0x0183f3ff);
459 amd_feature2
= regs
[2];
461 if (cpu_exthigh
>= 0x80000008) {
462 do_cpuid(0x80000008, regs
);
463 cpu_procinfo2
= regs
[2];
467 cpu
= CPU_CLAWHAMMER
;
471 print_AMD_assoc(int i
)
474 kprintf(", fully associative\n");
476 kprintf(", %d-way associative\n", i
);
480 print_AMD_l2_assoc(int i
)
483 case 0: kprintf(", disabled/not present\n"); break;
484 case 1: kprintf(", direct mapped\n"); break;
485 case 2: kprintf(", 2-way associative\n"); break;
486 case 4: kprintf(", 4-way associative\n"); break;
487 case 6: kprintf(", 8-way associative\n"); break;
488 case 8: kprintf(", 16-way associative\n"); break;
489 case 15: kprintf(", fully associative\n"); break;
490 default: kprintf(", reserved configuration\n"); break;
499 if (cpu_exthigh
< 0x80000005)
502 do_cpuid(0x80000005, regs
);
503 kprintf("L1 2MB data TLB: %d entries", (regs
[0] >> 16) & 0xff);
504 print_AMD_assoc(regs
[0] >> 24);
506 kprintf("L1 2MB instruction TLB: %d entries", regs
[0] & 0xff);
507 print_AMD_assoc((regs
[0] >> 8) & 0xff);
509 kprintf("L1 4KB data TLB: %d entries", (regs
[1] >> 16) & 0xff);
510 print_AMD_assoc(regs
[1] >> 24);
512 kprintf("L1 4KB instruction TLB: %d entries", regs
[1] & 0xff);
513 print_AMD_assoc((regs
[1] >> 8) & 0xff);
515 kprintf("L1 data cache: %d kbytes", regs
[2] >> 24);
516 kprintf(", %d bytes/line", regs
[2] & 0xff);
517 kprintf(", %d lines/tag", (regs
[2] >> 8) & 0xff);
518 print_AMD_assoc((regs
[2] >> 16) & 0xff);
520 kprintf("L1 instruction cache: %d kbytes", regs
[3] >> 24);
521 kprintf(", %d bytes/line", regs
[3] & 0xff);
522 kprintf(", %d lines/tag", (regs
[3] >> 8) & 0xff);
523 print_AMD_assoc((regs
[3] >> 16) & 0xff);
525 if (cpu_exthigh
>= 0x80000006) {
526 do_cpuid(0x80000006, regs
);
527 if ((regs
[0] >> 16) != 0) {
528 kprintf("L2 2MB data TLB: %d entries",
529 (regs
[0] >> 16) & 0xfff);
530 print_AMD_l2_assoc(regs
[0] >> 28);
531 kprintf("L2 2MB instruction TLB: %d entries",
533 print_AMD_l2_assoc((regs
[0] >> 28) & 0xf);
535 kprintf("L2 2MB unified TLB: %d entries",
537 print_AMD_l2_assoc((regs
[0] >> 28) & 0xf);
539 if ((regs
[1] >> 16) != 0) {
540 kprintf("L2 4KB data TLB: %d entries",
541 (regs
[1] >> 16) & 0xfff);
542 print_AMD_l2_assoc(regs
[1] >> 28);
544 kprintf("L2 4KB instruction TLB: %d entries",
545 (regs
[1] >> 16) & 0xfff);
546 print_AMD_l2_assoc((regs
[1] >> 28) & 0xf);
548 kprintf("L2 4KB unified TLB: %d entries",
549 (regs
[1] >> 16) & 0xfff);
550 print_AMD_l2_assoc((regs
[1] >> 28) & 0xf);
552 kprintf("L2 unified cache: %d kbytes", regs
[2] >> 16);
553 kprintf(", %d bytes/line", regs
[2] & 0xff);
554 kprintf(", %d lines/tag", (regs
[2] >> 8) & 0x0f);
555 print_AMD_l2_assoc((regs
[2] >> 12) & 0x0f);