i386.c revision 1.24 1 /* $NetBSD: i386.c,v 1.24 2011/02/19 13:34:38 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Frank van der Linden, and by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c)2008 YAMAMOTO Takashi,
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57
58 #include <sys/cdefs.h>
59 #ifndef lint
60 __RCSID("$NetBSD: i386.c,v 1.24 2011/02/19 13:34:38 jmcneill Exp $");
61 #endif /* not lint */
62
63 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <sys/bitops.h>
66 #include <sys/sysctl.h>
67
68 #include <string.h>
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <err.h>
72 #include <assert.h>
73 #include <math.h>
74 #include <util.h>
75
76 #include <machine/specialreg.h>
77 #include <machine/cpu.h>
78
79 #include <x86/cpuvar.h>
80 #include <x86/cputypes.h>
81 #include <x86/cacheinfo.h>
82
83 #include "../cpuctl.h"
84
85 /* Size of buffer for printing humanized numbers */
86 #define HUMAN_BUFSIZE sizeof("999KB")
87
88 #define x86_cpuid(a,b) x86_cpuid2((a),0,(b))
89
90 void x86_cpuid2(uint32_t, uint32_t, uint32_t *);
91 void x86_identify(void);
92
93 struct cpu_info {
94 const char *ci_dev;
95 int32_t ci_cpuid_level;
96 uint32_t ci_signature; /* X86 cpuid type */
97 uint32_t ci_feat_val[5]; /* X86 CPUID feature bits
98 * [0] basic features %edx
99 * [1] basic features %ecx
100 * [2] extended features %edx
101 * [3] extended features %ecx
102 * [4] VIA padlock features
103 */
104 uint32_t ci_cpu_class; /* CPU class */
105 uint32_t ci_brand_id; /* Intel brand id */
106 uint32_t ci_vendor[4]; /* vendor string */
107 uint32_t ci_cpu_serial[3]; /* PIII serial number */
108 uint64_t ci_tsc_freq; /* cpu cycles/second */
109 uint8_t ci_packageid;
110 uint8_t ci_coreid;
111 uint8_t ci_smtid;
112 uint32_t ci_initapicid;
113 struct x86_cache_info ci_cinfo[CAI_COUNT];
114 void (*ci_info)(struct cpu_info *);
115 };
116
117 struct cpu_nocpuid_nameclass {
118 int cpu_vendor;
119 const char *cpu_vendorname;
120 const char *cpu_name;
121 int cpu_class;
122 void (*cpu_setup)(struct cpu_info *);
123 void (*cpu_cacheinfo)(struct cpu_info *);
124 void (*cpu_info)(struct cpu_info *);
125 };
126
127 struct cpu_extend_nameclass {
128 int ext_model;
129 const char *cpu_models[CPU_MAXMODEL+1];
130 };
131
132 struct cpu_cpuid_nameclass {
133 const char *cpu_id;
134 int cpu_vendor;
135 const char *cpu_vendorname;
136 struct cpu_cpuid_family {
137 int cpu_class;
138 const char *cpu_models[CPU_MAXMODEL+2];
139 void (*cpu_setup)(struct cpu_info *);
140 void (*cpu_probe)(struct cpu_info *);
141 void (*cpu_info)(struct cpu_info *);
142 struct cpu_extend_nameclass *cpu_extended_names;
143 } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1];
144 };
145
146 static const struct x86_cache_info intel_cpuid_cache_info[] = INTEL_CACHE_INFO;
147
148 /*
149 * Map Brand ID from cpuid instruction to brand name.
150 * Source: Intel Processor Identification and the CPUID Instruction, AP-485
151 */
152 static const char * const i386_intel_brand[] = {
153 "", /* Unsupported */
154 "Celeron", /* Intel (R) Celeron (TM) processor */
155 "Pentium III", /* Intel (R) Pentium (R) III processor */
156 "Pentium III Xeon", /* Intel (R) Pentium (R) III Xeon (TM) processor */
157 "Pentium III", /* Intel (R) Pentium (R) III processor */
158 "", /* Reserved */
159 "Mobile Pentium III", /* Mobile Intel (R) Pentium (R) III processor-M */
160 "Mobile Celeron", /* Mobile Intel (R) Celeron (R) processor */
161 "Pentium 4", /* Intel (R) Pentium (R) 4 processor */
162 "Pentium 4", /* Intel (R) Pentium (R) 4 processor */
163 "Celeron", /* Intel (R) Celeron (TM) processor */
164 "Xeon", /* Intel (R) Xeon (TM) processor */
165 "Xeon MP", /* Intel (R) Xeon (TM) processor MP */
166 "", /* Reserved */
167 "Mobile Pentium 4", /* Mobile Intel (R) Pentium (R) 4 processor-M */
168 "Mobile Celeron", /* Mobile Intel (R) Celeron (R) processor */
169 };
170
171 /*
172 * AMD processors don't have Brand IDs, so we need these names for probe.
173 */
174 static const char * const amd_brand[] = {
175 "",
176 "Duron", /* AMD Duron(tm) */
177 "MP", /* AMD Athlon(tm) MP */
178 "XP", /* AMD Athlon(tm) XP */
179 "4" /* AMD Athlon(tm) 4 */
180 };
181
182 static int cpu_vendor;
183 static char cpu_brand_string[49];
184 static char amd_brand_name[48];
185
186 static void via_cpu_probe(struct cpu_info *);
187 static void amd_family6_probe(struct cpu_info *);
188 static void intel_family_new_probe(struct cpu_info *);
189 static const char *intel_family6_name(struct cpu_info *);
190 static const char *amd_amd64_name(struct cpu_info *);
191 static void amd_family5_setup(struct cpu_info *);
192 static void transmeta_cpu_info(struct cpu_info *);
193 static const char *print_cache_config(struct cpu_info *, int, const char *,
194 const char *);
195 static const char *print_tlb_config(struct cpu_info *, int, const char *,
196 const char *);
197 static void amd_cpu_cacheinfo(struct cpu_info *);
198 static void via_cpu_cacheinfo(struct cpu_info *);
199 static void x86_print_cacheinfo(struct cpu_info *);
200 static const struct x86_cache_info *cache_info_lookup(
201 const struct x86_cache_info *, uint8_t);
202 static void cyrix6x86_cpu_setup(struct cpu_info *);
203 static void winchip_cpu_setup(struct cpu_info *);
204 static void amd_family5_setup(struct cpu_info *);
205 static void powernow_probe(struct cpu_info *);
206
207 /*
208 * Info for CTL_HW
209 */
210 static char cpu_model[120];
211
212 /*
213 * Note: these are just the ones that may not have a cpuid instruction.
214 * We deal with the rest in a different way.
215 */
216 const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[] = {
217 { CPUVENDOR_INTEL, "Intel", "386SX", CPUCLASS_386,
218 NULL, NULL, NULL }, /* CPU_386SX */
219 { CPUVENDOR_INTEL, "Intel", "386DX", CPUCLASS_386,
220 NULL, NULL, NULL }, /* CPU_386 */
221 { CPUVENDOR_INTEL, "Intel", "486SX", CPUCLASS_486,
222 NULL, NULL, NULL }, /* CPU_486SX */
223 { CPUVENDOR_INTEL, "Intel", "486DX", CPUCLASS_486,
224 NULL, NULL, NULL }, /* CPU_486 */
225 { CPUVENDOR_CYRIX, "Cyrix", "486DLC", CPUCLASS_486,
226 NULL, NULL, NULL }, /* CPU_486DLC */
227 { CPUVENDOR_CYRIX, "Cyrix", "6x86", CPUCLASS_486,
228 NULL, NULL, NULL }, /* CPU_6x86 */
229 { CPUVENDOR_NEXGEN,"NexGen","586", CPUCLASS_386,
230 NULL, NULL, NULL }, /* CPU_NX586 */
231 };
232
233 const char *classnames[] = {
234 "386",
235 "486",
236 "586",
237 "686"
238 };
239
240 const char *modifiers[] = {
241 "",
242 "OverDrive",
243 "Dual",
244 ""
245 };
246
247 struct cpu_extend_nameclass intel_family6_ext_models[] = {
248 { /* Extended models 1x */
249 0x01, { NULL, NULL,
250 NULL, NULL,
251 NULL, "EP80579 Integrated Processor",
252 "Celeron (45nm)", "Core 2 Extreme",
253 NULL, NULL,
254 "Core i7 (Nehalem)", NULL,
255 "Atom", "XeonMP (Nehalem)",
256 NULL, NULL} },
257 { /* End of list */
258 0x00, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
259 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
260 };
261
262 const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
263 {
264 "GenuineIntel",
265 CPUVENDOR_INTEL,
266 "Intel",
267 /* Family 4 */
268 { {
269 CPUCLASS_486,
270 {
271 "486DX", "486DX", "486SX", "486DX2", "486SL",
272 "486SX2", 0, "486DX2 W/B Enhanced",
273 "486DX4", 0, 0, 0, 0, 0, 0, 0,
274 "486" /* Default */
275 },
276 NULL,
277 NULL,
278 NULL,
279 NULL,
280 },
281 /* Family 5 */
282 {
283 CPUCLASS_586,
284 {
285 "Pentium (P5 A-step)", "Pentium (P5)",
286 "Pentium (P54C)", "Pentium (P24T)",
287 "Pentium/MMX", "Pentium", 0,
288 "Pentium (P54C)", "Pentium/MMX (Tillamook)",
289 0, 0, 0, 0, 0, 0, 0,
290 "Pentium" /* Default */
291 },
292 NULL,
293 NULL,
294 NULL,
295 NULL,
296 },
297 /* Family 6 */
298 {
299 CPUCLASS_686,
300 {
301 "Pentium Pro (A-step)", "Pentium Pro", 0,
302 "Pentium II (Klamath)", "Pentium Pro",
303 "Pentium II/Celeron (Deschutes)",
304 "Celeron (Mendocino)",
305 "Pentium III (Katmai)",
306 "Pentium III (Coppermine)",
307 "Pentium M (Banias)",
308 "Pentium III Xeon (Cascades)",
309 "Pentium III (Tualatin)", 0,
310 "Pentium M (Dothan)",
311 "Pentium M (Yonah)",
312 "Core 2",
313 "Pentium Pro, II or III" /* Default */
314 },
315 NULL,
316 intel_family_new_probe,
317 NULL,
318 &intel_family6_ext_models[0],
319 },
320 /* Family > 6 */
321 {
322 CPUCLASS_686,
323 {
324 0, 0, 0, 0, 0, 0, 0, 0,
325 0, 0, 0, 0, 0, 0, 0, 0,
326 "Pentium 4" /* Default */
327 },
328 NULL,
329 intel_family_new_probe,
330 NULL,
331 NULL,
332 } }
333 },
334 {
335 "AuthenticAMD",
336 CPUVENDOR_AMD,
337 "AMD",
338 /* Family 4 */
339 { {
340 CPUCLASS_486,
341 {
342 0, 0, 0, "Am486DX2 W/T",
343 0, 0, 0, "Am486DX2 W/B",
344 "Am486DX4 W/T or Am5x86 W/T 150",
345 "Am486DX4 W/B or Am5x86 W/B 150", 0, 0,
346 0, 0, "Am5x86 W/T 133/160",
347 "Am5x86 W/B 133/160",
348 "Am486 or Am5x86" /* Default */
349 },
350 NULL,
351 NULL,
352 NULL,
353 NULL,
354 },
355 /* Family 5 */
356 {
357 CPUCLASS_586,
358 {
359 "K5", "K5", "K5", "K5", 0, 0, "K6",
360 "K6", "K6-2", "K6-III", "Geode LX", 0, 0,
361 "K6-2+/III+", 0, 0,
362 "K5 or K6" /* Default */
363 },
364 amd_family5_setup,
365 NULL,
366 amd_cpu_cacheinfo,
367 NULL,
368 },
369 /* Family 6 */
370 {
371 CPUCLASS_686,
372 {
373 0, "Athlon Model 1", "Athlon Model 2",
374 "Duron", "Athlon Model 4 (Thunderbird)",
375 0, "Athlon", "Duron", "Athlon", 0,
376 "Athlon", 0, 0, 0, 0, 0,
377 "K7 (Athlon)" /* Default */
378 },
379 NULL,
380 amd_family6_probe,
381 amd_cpu_cacheinfo,
382 NULL,
383 },
384 /* Family > 6 */
385 {
386 CPUCLASS_686,
387 {
388 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 0, 0, 0, 0, 0, 0, 0,
390 "Unknown K8 (Athlon)" /* Default */
391 },
392 NULL,
393 amd_family6_probe,
394 amd_cpu_cacheinfo,
395 NULL,
396 } }
397 },
398 {
399 "CyrixInstead",
400 CPUVENDOR_CYRIX,
401 "Cyrix",
402 /* Family 4 */
403 { {
404 CPUCLASS_486,
405 {
406 0, 0, 0,
407 "MediaGX",
408 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
409 "486" /* Default */
410 },
411 cyrix6x86_cpu_setup, /* XXX ?? */
412 NULL,
413 NULL,
414 NULL,
415 },
416 /* Family 5 */
417 {
418 CPUCLASS_586,
419 {
420 0, 0, "6x86", 0,
421 "MMX-enhanced MediaGX (GXm)", /* or Geode? */
422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
423 "6x86" /* Default */
424 },
425 cyrix6x86_cpu_setup,
426 NULL,
427 NULL,
428 NULL,
429 },
430 /* Family 6 */
431 {
432 CPUCLASS_686,
433 {
434 "6x86MX", 0, 0, 0, 0, 0, 0, 0,
435 0, 0, 0, 0, 0, 0, 0, 0,
436 "6x86MX" /* Default */
437 },
438 cyrix6x86_cpu_setup,
439 NULL,
440 NULL,
441 NULL,
442 },
443 /* Family > 6 */
444 {
445 CPUCLASS_686,
446 {
447 0, 0, 0, 0, 0, 0, 0, 0,
448 0, 0, 0, 0, 0, 0, 0, 0,
449 "Unknown 6x86MX" /* Default */
450 },
451 NULL,
452 NULL,
453 NULL,
454 NULL,
455 } }
456 },
457 { /* MediaGX is now owned by National Semiconductor */
458 "Geode by NSC",
459 CPUVENDOR_CYRIX, /* XXX */
460 "National Semiconductor",
461 /* Family 4, NSC never had any of these */
462 { {
463 CPUCLASS_486,
464 {
465 0, 0, 0, 0, 0, 0, 0, 0,
466 0, 0, 0, 0, 0, 0, 0, 0,
467 "486 compatible" /* Default */
468 },
469 NULL,
470 NULL,
471 NULL,
472 NULL,
473 },
474 /* Family 5: Geode family, formerly MediaGX */
475 {
476 CPUCLASS_586,
477 {
478 0, 0, 0, 0,
479 "Geode GX1",
480 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
481 "Geode" /* Default */
482 },
483 cyrix6x86_cpu_setup,
484 NULL,
485 amd_cpu_cacheinfo,
486 NULL,
487 },
488 /* Family 6, not yet available from NSC */
489 {
490 CPUCLASS_686,
491 {
492 0, 0, 0, 0, 0, 0, 0, 0,
493 0, 0, 0, 0, 0, 0, 0, 0,
494 "Pentium Pro compatible" /* Default */
495 },
496 NULL,
497 NULL,
498 NULL,
499 NULL,
500 },
501 /* Family > 6, not yet available from NSC */
502 {
503 CPUCLASS_686,
504 {
505 0, 0, 0, 0, 0, 0, 0, 0,
506 0, 0, 0, 0, 0, 0, 0, 0,
507 "Pentium Pro compatible" /* Default */
508 },
509 NULL,
510 NULL,
511 NULL,
512 NULL,
513 } }
514 },
515 {
516 "CentaurHauls",
517 CPUVENDOR_IDT,
518 "IDT",
519 /* Family 4, IDT never had any of these */
520 { {
521 CPUCLASS_486,
522 {
523 0, 0, 0, 0, 0, 0, 0, 0,
524 0, 0, 0, 0, 0, 0, 0, 0,
525 "486 compatible" /* Default */
526 },
527 NULL,
528 NULL,
529 NULL,
530 NULL,
531 },
532 /* Family 5 */
533 {
534 CPUCLASS_586,
535 {
536 0, 0, 0, 0, "WinChip C6", 0, 0, 0,
537 "WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0,
538 "WinChip" /* Default */
539 },
540 winchip_cpu_setup,
541 NULL,
542 NULL,
543 NULL,
544 },
545 /* Family 6, VIA acquired IDT Centaur design subsidiary */
546 {
547 CPUCLASS_686,
548 {
549 0, 0, 0, 0, 0, 0, "C3 Samuel",
550 "C3 Samuel 2/Ezra", "C3 Ezra-T",
551 "C3 Nehemiah", "C7 Esther", 0, 0, "C7 Esther",
552 0, "VIA Nano",
553 "Unknown VIA/IDT" /* Default */
554 },
555 NULL,
556 via_cpu_probe,
557 via_cpu_cacheinfo,
558 NULL,
559 },
560 /* Family > 6, not yet available from VIA */
561 {
562 CPUCLASS_686,
563 {
564 0, 0, 0, 0, 0, 0, 0, 0,
565 0, 0, 0, 0, 0, 0, 0, 0,
566 "Pentium Pro compatible" /* Default */
567 },
568 NULL,
569 NULL,
570 NULL,
571 NULL,
572 } }
573 },
574 {
575 "GenuineTMx86",
576 CPUVENDOR_TRANSMETA,
577 "Transmeta",
578 /* Family 4, Transmeta never had any of these */
579 { {
580 CPUCLASS_486,
581 {
582 0, 0, 0, 0, 0, 0, 0, 0,
583 0, 0, 0, 0, 0, 0, 0, 0,
584 "486 compatible" /* Default */
585 },
586 NULL,
587 NULL,
588 NULL,
589 NULL,
590 },
591 /* Family 5 */
592 {
593 CPUCLASS_586,
594 {
595 0, 0, 0, 0, 0, 0, 0, 0,
596 0, 0, 0, 0, 0, 0, 0, 0,
597 "Crusoe" /* Default */
598 },
599 NULL,
600 NULL,
601 transmeta_cpu_info,
602 NULL,
603 },
604 /* Family 6, not yet available from Transmeta */
605 {
606 CPUCLASS_686,
607 {
608 0, 0, 0, 0, 0, 0, 0, 0,
609 0, 0, 0, 0, 0, 0, 0, 0,
610 "Pentium Pro compatible" /* Default */
611 },
612 NULL,
613 NULL,
614 NULL,
615 NULL,
616 },
617 /* Family > 6, not yet available from Transmeta */
618 {
619 CPUCLASS_686,
620 {
621 0, 0, 0, 0, 0, 0, 0, 0,
622 0, 0, 0, 0, 0, 0, 0, 0,
623 "Pentium Pro compatible" /* Default */
624 },
625 NULL,
626 NULL,
627 NULL,
628 NULL,
629 } }
630 }
631 };
632
633 /*
634 * disable the TSC such that we don't use the TSC in microtime(9)
635 * because some CPUs got the implementation wrong.
636 */
637 static void
638 disable_tsc(struct cpu_info *ci)
639 {
640 if (ci->ci_feat_val[0] & CPUID_TSC) {
641 ci->ci_feat_val[0] &= ~CPUID_TSC;
642 aprint_error("WARNING: broken TSC disabled\n");
643 }
644 }
645
646 static void
647 cyrix6x86_cpu_setup(struct cpu_info *ci)
648 {
649
650 /*
651 * Do not disable the TSC on the Geode GX, it's reported to
652 * work fine.
653 */
654 if (ci->ci_signature != 0x552)
655 disable_tsc(ci);
656 }
657
658 void
659 winchip_cpu_setup(struct cpu_info *ci)
660 {
661 switch (CPUID2MODEL(ci->ci_signature)) { /* model */
662 case 4: /* WinChip C6 */
663 disable_tsc(ci);
664 }
665 }
666
667
668 static void
669 identifycpu_cpuids(struct cpu_info *ci)
670 {
671 const char *cpuname = ci->ci_dev;
672 u_int lp_max = 1; /* logical processors per package */
673 u_int smt_max; /* smt per core */
674 u_int core_max = 1; /* core per package */
675 u_int smt_bits, core_bits;
676 uint32_t descs[4];
677
678 aprint_verbose("%s: Initial APIC ID %u\n", cpuname, ci->ci_initapicid);
679 ci->ci_packageid = ci->ci_initapicid;
680 ci->ci_coreid = 0;
681 ci->ci_smtid = 0;
682 if (cpu_vendor != CPUVENDOR_INTEL) {
683 return;
684 }
685
686 /*
687 * 253668.pdf 7.10.2
688 */
689
690 if ((ci->ci_feat_val[0] & CPUID_HTT) != 0) {
691 x86_cpuid(1, descs);
692 lp_max = (descs[1] >> 16) & 0xff;
693 }
694 x86_cpuid(0, descs);
695 if (descs[0] >= 4) {
696 x86_cpuid2(4, 0, descs);
697 core_max = (descs[0] >> 26) + 1;
698 }
699 assert(lp_max >= core_max);
700 smt_max = lp_max / core_max;
701 smt_bits = ilog2(smt_max - 1) + 1;
702 core_bits = ilog2(core_max - 1) + 1;
703 if (smt_bits + core_bits) {
704 ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits);
705 }
706 aprint_verbose("%s: Cluster/Package ID %u\n", cpuname,
707 ci->ci_packageid);
708 if (core_bits) {
709 u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1);
710
711 ci->ci_coreid =
712 __SHIFTOUT(ci->ci_initapicid, core_mask);
713 aprint_verbose("%s: Core ID %u\n", cpuname, ci->ci_coreid);
714 }
715 if (smt_bits) {
716 u_int smt_mask = __BITS((int)0, (int)(smt_bits - 1));
717
718 ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask);
719 aprint_verbose("%s: SMT ID %u\n", cpuname, ci->ci_smtid);
720 }
721 }
722
723 static void
724 via_cpu_probe(struct cpu_info *ci)
725 {
726 u_int model = CPUID2MODEL(ci->ci_signature);
727 u_int stepping = CPUID2STEPPING(ci->ci_signature);
728 u_int descs[4];
729 u_int lfunc;
730
731 /*
732 * Determine the largest extended function value.
733 */
734 x86_cpuid(0x80000000, descs);
735 lfunc = descs[0];
736
737 /*
738 * Determine the extended feature flags.
739 */
740 if (lfunc >= 0x80000001) {
741 x86_cpuid(0x80000001, descs);
742 ci->ci_feat_val[2] |= descs[3];
743 }
744
745 if (model < 0x9 || (model == 0x9 && stepping < 3))
746 return;
747
748 /* Nehemiah or Esther */
749 x86_cpuid(0xc0000000, descs);
750 lfunc = descs[0];
751 if (lfunc < 0xc0000001) /* no ACE, no RNG */
752 return;
753
754 x86_cpuid(0xc0000001, descs);
755 lfunc = descs[3];
756 ci->ci_feat_val[4] = lfunc;
757 }
758
759 static const char *
760 intel_family6_name(struct cpu_info *ci)
761 {
762 int model = CPUID2MODEL(ci->ci_signature);
763 const char *ret = NULL;
764 u_int l2cache = ci->ci_cinfo[CAI_L2CACHE].cai_totalsize;
765
766 if (model == 5) {
767 switch (l2cache) {
768 case 0:
769 case 128 * 1024:
770 ret = "Celeron (Covington)";
771 break;
772 case 256 * 1024:
773 ret = "Mobile Pentium II (Dixon)";
774 break;
775 case 512 * 1024:
776 ret = "Pentium II";
777 break;
778 case 1 * 1024 * 1024:
779 case 2 * 1024 * 1024:
780 ret = "Pentium II Xeon";
781 break;
782 }
783 } else if (model == 6) {
784 switch (l2cache) {
785 case 256 * 1024:
786 case 512 * 1024:
787 ret = "Mobile Pentium II";
788 break;
789 }
790 } else if (model == 7) {
791 switch (l2cache) {
792 case 512 * 1024:
793 ret = "Pentium III";
794 break;
795 case 1 * 1024 * 1024:
796 case 2 * 1024 * 1024:
797 ret = "Pentium III Xeon";
798 break;
799 }
800 } else if (model >= 8) {
801 if (ci->ci_brand_id && ci->ci_brand_id < 0x10) {
802 switch (ci->ci_brand_id) {
803 case 0x3:
804 if (ci->ci_signature == 0x6B1)
805 ret = "Celeron";
806 break;
807 case 0x8:
808 if (ci->ci_signature >= 0xF13)
809 ret = "genuine processor";
810 break;
811 case 0xB:
812 if (ci->ci_signature >= 0xF13)
813 ret = "Xeon MP";
814 break;
815 case 0xE:
816 if (ci->ci_signature < 0xF13)
817 ret = "Xeon";
818 break;
819 }
820 if (ret == NULL)
821 ret = i386_intel_brand[ci->ci_brand_id];
822 }
823 }
824
825 return ret;
826 }
827
828 /*
829 * Identify AMD64 CPU names from cpuid.
830 *
831 * Based on:
832 * "Revision Guide for AMD Athlon 64 and AMD Opteron Processors"
833 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25759.pdf
834 * "Revision Guide for AMD NPT Family 0Fh Processors"
835 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
836 * and other miscellaneous reports.
837 */
838 static const char *
839 amd_amd64_name(struct cpu_info *ci)
840 {
841 int extfamily, extmodel, model;
842 const char *ret = NULL;
843
844 model = CPUID2MODEL(ci->ci_signature);
845 extfamily = CPUID2EXTFAMILY(ci->ci_signature);
846 extmodel = CPUID2EXTMODEL(ci->ci_signature);
847
848 switch (extfamily) {
849 case 0x00:
850 switch (model) {
851 case 0x1:
852 switch (extmodel) {
853 case 0x2: /* rev JH-E1/E6 */
854 case 0x4: /* rev JH-F2 */
855 ret = "Dual-Core Opteron";
856 break;
857 }
858 break;
859 case 0x3:
860 switch (extmodel) {
861 case 0x2: /* rev JH-E6 (Toledo) */
862 ret = "Dual-Core Opteron or Athlon 64 X2";
863 break;
864 case 0x4: /* rev JH-F2 (Windsor) */
865 ret = "Athlon 64 FX or Athlon 64 X2";
866 break;
867 }
868 break;
869 case 0x4:
870 switch (extmodel) {
871 case 0x0: /* rev SH-B0/C0/CG (ClawHammer) */
872 case 0x1: /* rev SH-D0 */
873 ret = "Athlon 64";
874 break;
875 case 0x2: /* rev SH-E5 (Lancaster?) */
876 ret = "Mobile Athlon 64 or Turion 64";
877 break;
878 }
879 break;
880 case 0x5:
881 switch (extmodel) {
882 case 0x0: /* rev SH-B0/B3/C0/CG (SledgeHammer?) */
883 ret = "Opteron or Athlon 64 FX";
884 break;
885 case 0x1: /* rev SH-D0 */
886 case 0x2: /* rev SH-E4 */
887 ret = "Opteron";
888 break;
889 }
890 break;
891 case 0x7:
892 switch (extmodel) {
893 case 0x0: /* rev SH-CG (ClawHammer) */
894 case 0x1: /* rev SH-D0 */
895 ret = "Athlon 64";
896 break;
897 case 0x2: /* rev DH-E4, SH-E4 */
898 ret = "Athlon 64 or Athlon 64 FX or Opteron";
899 break;
900 }
901 break;
902 case 0x8:
903 switch (extmodel) {
904 case 0x0: /* rev CH-CG */
905 case 0x1: /* rev CH-D0 */
906 ret = "Athlon 64 or Sempron";
907 break;
908 case 0x4: /* rev BH-F2 */
909 ret = "Turion 64 X2";
910 break;
911 }
912 break;
913 case 0xb:
914 switch (extmodel) {
915 case 0x0: /* rev CH-CG */
916 case 0x1: /* rev CH-D0 */
917 ret = "Athlon 64";
918 break;
919 case 0x2: /* rev BH-E4 (Manchester) */
920 case 0x4: /* rev BH-F2 (Windsor) */
921 ret = "Athlon 64 X2";
922 break;
923 case 0x6: /* rev BH-G1 (Brisbane) */
924 ret = "Athlon X2 or Athlon 64 X2";
925 break;
926 }
927 break;
928 case 0xc:
929 switch (extmodel) {
930 case 0x0: /* rev DH-CG (Newcastle) */
931 case 0x1: /* rev DH-D0 (Winchester) */
932 case 0x2: /* rev DH-E3/E6 */
933 ret = "Athlon 64 or Sempron";
934 break;
935 }
936 break;
937 case 0xe:
938 switch (extmodel) {
939 case 0x0: /* rev DH-CG (Newcastle?) */
940 ret = "Athlon 64 or Sempron";
941 break;
942 }
943 break;
944 case 0xf:
945 switch (extmodel) {
946 case 0x0: /* rev DH-CG (Newcastle/Paris) */
947 case 0x1: /* rev DH-D0 (Winchester/Victoria) */
948 case 0x2: /* rev DH-E3/E6 (Venice/Palermo) */
949 case 0x4: /* rev DH-F2 (Orleans/Manila) */
950 case 0x5: /* rev DH-F2 (Orleans/Manila) */
951 case 0x6: /* rev DH-G1 */
952 ret = "Athlon 64 or Sempron";
953 break;
954 }
955 break;
956 default:
957 ret = "Unknown AMD64 CPU";
958 }
959 break;
960 case 0x01:
961 switch (model) {
962 case 0x02:
963 ret = "Family 10h";
964 break;
965 default:
966 ret = "Unknown AMD64 CPU";
967 break;
968 }
969 break;
970 }
971
972 return ret;
973 }
974
975 static void
976 cpu_probe_base_features(struct cpu_info *ci)
977 {
978 const struct x86_cache_info *cai;
979 u_int descs[4];
980 int iterations, i, j;
981 uint8_t desc;
982 uint32_t miscbytes;
983 uint32_t brand[12];
984
985 if (ci->ci_cpuid_level < 0)
986 return;
987
988 x86_cpuid(0, descs);
989 ci->ci_cpuid_level = descs[0];
990 ci->ci_vendor[0] = descs[1];
991 ci->ci_vendor[2] = descs[2];
992 ci->ci_vendor[1] = descs[3];
993 ci->ci_vendor[3] = 0;
994
995 x86_cpuid(0x80000000, brand);
996 if (brand[0] >= 0x80000004) {
997 x86_cpuid(0x80000002, brand);
998 x86_cpuid(0x80000003, brand + 4);
999 x86_cpuid(0x80000004, brand + 8);
1000 for (i = 0; i < 48; i++)
1001 if (((char *) brand)[i] != ' ')
1002 break;
1003 memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i);
1004 }
1005
1006 if (ci->ci_cpuid_level < 1)
1007 return;
1008
1009 x86_cpuid(1, descs);
1010 ci->ci_signature = descs[0];
1011 miscbytes = descs[1];
1012 ci->ci_feat_val[1] = descs[2];
1013 ci->ci_feat_val[0] = descs[3];
1014
1015 /* Brand is low order 8 bits of ebx */
1016 ci->ci_brand_id = miscbytes & 0xff;
1017 ci->ci_initapicid = (miscbytes >> 24) & 0xff;
1018 if (ci->ci_cpuid_level < 2)
1019 return;
1020
1021 /*
1022 * Parse the cache info from `cpuid', if we have it.
1023 * XXX This is kinda ugly, but hey, so is the architecture...
1024 */
1025
1026 x86_cpuid(2, descs);
1027
1028 iterations = descs[0] & 0xff;
1029 while (iterations-- > 0) {
1030 for (i = 0; i < 4; i++) {
1031 if (descs[i] & 0x80000000)
1032 continue;
1033 for (j = 0; j < 4; j++) {
1034 if (i == 0 && j == 0)
1035 continue;
1036 desc = (descs[i] >> (j * 8)) & 0xff;
1037 if (desc == 0)
1038 continue;
1039 cai = cache_info_lookup(intel_cpuid_cache_info,
1040 desc);
1041 if (cai != NULL)
1042 ci->ci_cinfo[cai->cai_index] = *cai;
1043 }
1044 }
1045 x86_cpuid(2, descs);
1046 }
1047
1048 if (ci->ci_cpuid_level < 3)
1049 return;
1050
1051 /*
1052 * If the processor serial number misfeature is present and supported,
1053 * extract it here.
1054 */
1055 if ((ci->ci_feat_val[0] & CPUID_PN) != 0) {
1056 ci->ci_cpu_serial[0] = ci->ci_signature;
1057 x86_cpuid(3, descs);
1058 ci->ci_cpu_serial[2] = descs[2];
1059 ci->ci_cpu_serial[1] = descs[3];
1060 }
1061 }
1062
1063 static void
1064 cpu_probe_features(struct cpu_info *ci)
1065 {
1066 const struct cpu_cpuid_nameclass *cpup = NULL;
1067 int i, xmax, family;
1068
1069 cpu_probe_base_features(ci);
1070
1071 if (ci->ci_cpuid_level < 1)
1072 return;
1073
1074 xmax = __arraycount(i386_cpuid_cpus);
1075 for (i = 0; i < xmax; i++) {
1076 if (!strncmp((char *)ci->ci_vendor,
1077 i386_cpuid_cpus[i].cpu_id, 12)) {
1078 cpup = &i386_cpuid_cpus[i];
1079 break;
1080 }
1081 }
1082
1083 if (cpup == NULL)
1084 return;
1085
1086 family = (ci->ci_signature >> 8) & 0xf;
1087
1088 if (family > CPU_MAXFAMILY) {
1089 family = CPU_MAXFAMILY;
1090 }
1091 i = family - CPU_MINFAMILY;
1092
1093 if (cpup->cpu_family[i].cpu_probe == NULL)
1094 return;
1095
1096 (*cpup->cpu_family[i].cpu_probe)(ci);
1097 }
1098
1099 static void
1100 intel_family_new_probe(struct cpu_info *ci)
1101 {
1102 uint32_t descs[4];
1103
1104 x86_cpuid(0x80000000, descs);
1105
1106 /*
1107 * Determine extended feature flags.
1108 */
1109 if (descs[0] >= 0x80000001) {
1110 x86_cpuid(0x80000001, descs);
1111 ci->ci_feat_val[2] |= descs[3];
1112 ci->ci_feat_val[3] |= descs[2];
1113 }
1114 }
1115
1116 static void
1117 amd_family6_probe(struct cpu_info *ci)
1118 {
1119 uint32_t descs[4];
1120 char *p;
1121 size_t i;
1122
1123 x86_cpuid(0x80000000, descs);
1124
1125 /*
1126 * Determine the extended feature flags.
1127 */
1128 if (descs[0] >= 0x80000001) {
1129 x86_cpuid(0x80000001, descs);
1130 ci->ci_feat_val[2] |= descs[3]; /* %edx */
1131 ci->ci_feat_val[3] = descs[2]; /* %ecx */
1132 }
1133
1134 if (*cpu_brand_string == '\0')
1135 return;
1136
1137 for (i = 1; i < __arraycount(amd_brand); i++)
1138 if ((p = strstr(cpu_brand_string, amd_brand[i])) != NULL) {
1139 ci->ci_brand_id = i;
1140 strlcpy(amd_brand_name, p, sizeof(amd_brand_name));
1141 break;
1142 }
1143 }
1144
1145 static void
1146 amd_family5_setup(struct cpu_info *ci)
1147 {
1148
1149 switch (CPUID2MODEL(ci->ci_signature)) {
1150 case 0: /* AMD-K5 Model 0 */
1151 /*
1152 * According to the AMD Processor Recognition App Note,
1153 * the AMD-K5 Model 0 uses the wrong bit to indicate
1154 * support for global PTEs, instead using bit 9 (APIC)
1155 * rather than bit 13 (i.e. "0x200" vs. 0x2000". Oops!).
1156 */
1157 if (ci->ci_feat_val[0] & CPUID_APIC)
1158 ci->ci_feat_val[0] =
1159 (ci->ci_feat_val[0] & ~CPUID_APIC) | CPUID_PGE;
1160 /*
1161 * XXX But pmap_pg_g is already initialized -- need to kick
1162 * XXX the pmap somehow. How does the MP branch do this?
1163 */
1164 break;
1165 }
1166 }
1167
1168 static void
1169 tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage)
1170 {
1171 u_int descs[4];
1172
1173 x86_cpuid(0x80860007, descs);
1174 *frequency = descs[0];
1175 *voltage = descs[1];
1176 *percentage = descs[2];
1177 }
1178
1179 static void
1180 transmeta_cpu_info(struct cpu_info *ci)
1181 {
1182 u_int descs[4], nreg;
1183 u_int frequency, voltage, percentage;
1184
1185 x86_cpuid(0x80860000, descs);
1186 nreg = descs[0];
1187 if (nreg >= 0x80860001) {
1188 x86_cpuid(0x80860001, descs);
1189 aprint_verbose_dev(ci->ci_dev, "Processor revision %u.%u.%u.%u\n",
1190 (descs[1] >> 24) & 0xff,
1191 (descs[1] >> 16) & 0xff,
1192 (descs[1] >> 8) & 0xff,
1193 descs[1] & 0xff);
1194 }
1195 if (nreg >= 0x80860002) {
1196 x86_cpuid(0x80860002, descs);
1197 aprint_verbose_dev(ci->ci_dev, "Code Morphing Software Rev: %u.%u.%u-%u-%u\n",
1198 (descs[1] >> 24) & 0xff,
1199 (descs[1] >> 16) & 0xff,
1200 (descs[1] >> 8) & 0xff,
1201 descs[1] & 0xff,
1202 descs[2]);
1203 }
1204 if (nreg >= 0x80860006) {
1205 union {
1206 char text[65];
1207 u_int descs[4][4];
1208 } info;
1209 int i;
1210
1211 for (i=0; i<4; i++) {
1212 x86_cpuid(0x80860003 + i, info.descs[i]);
1213 }
1214 info.text[64] = '\0';
1215 aprint_verbose_dev(ci->ci_dev, "%s\n", info.text);
1216 }
1217
1218 if (nreg >= 0x80860007) {
1219 tmx86_get_longrun_status(&frequency,
1220 &voltage, &percentage);
1221 aprint_verbose_dev(ci->ci_dev, "LongRun <%dMHz %dmV %d%%>\n",
1222 frequency, voltage, percentage);
1223 }
1224 }
1225
1226 void
1227 identifycpu(const char *cpuname)
1228 {
1229 const char *name = "", *modifier, *vendorname, *brand = "";
1230 int class = CPUCLASS_386, i, xmax;
1231 int modif, family, model, ext_model;
1232 const struct cpu_extend_nameclass *modlist;
1233 const struct cpu_cpuid_nameclass *cpup = NULL;
1234 const struct cpu_cpuid_family *cpufam;
1235 const char *feature_str[5];
1236 struct cpu_info *ci, cistore;
1237 extern int cpu;
1238 extern int cpu_info_level;
1239 size_t sz;
1240 char buf[512];
1241 char *bp;
1242
1243 ci = &cistore;
1244 memset(ci, 0, sizeof(*ci));
1245 ci->ci_dev = cpuname;
1246
1247 x86_identify();
1248 ci->ci_cpuid_level = cpu_info_level;
1249 cpu_probe_features(ci);
1250
1251 if (ci->ci_cpuid_level == -1) {
1252 if ((size_t)cpu >= __arraycount(i386_nocpuid_cpus))
1253 errx(1, "unknown cpu type %d", cpu);
1254 name = i386_nocpuid_cpus[cpu].cpu_name;
1255 cpu_vendor = i386_nocpuid_cpus[cpu].cpu_vendor;
1256 vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname;
1257 class = i386_nocpuid_cpus[cpu].cpu_class;
1258 ci->ci_info = i386_nocpuid_cpus[cpu].cpu_info;
1259 modifier = "";
1260 } else {
1261 xmax = __arraycount(i386_cpuid_cpus);
1262 modif = (ci->ci_signature >> 12) & 0x3;
1263 family = CPUID2FAMILY(ci->ci_signature);
1264 if (family < CPU_MINFAMILY)
1265 errx(1, "identifycpu: strange family value");
1266 model = CPUID2MODEL(ci->ci_signature);
1267 ext_model = CPUID2EXTMODEL(ci->ci_signature);
1268
1269 for (i = 0; i < xmax; i++) {
1270 if (!strncmp((char *)ci->ci_vendor,
1271 i386_cpuid_cpus[i].cpu_id, 12)) {
1272 cpup = &i386_cpuid_cpus[i];
1273 break;
1274 }
1275 }
1276
1277 if (cpup == NULL) {
1278 cpu_vendor = CPUVENDOR_UNKNOWN;
1279 if (ci->ci_vendor[0] != '\0')
1280 vendorname = (char *)&ci->ci_vendor[0];
1281 else
1282 vendorname = "Unknown";
1283 if (family >= CPU_MAXFAMILY)
1284 family = CPU_MINFAMILY;
1285 class = family - 3;
1286 modifier = "";
1287 name = "";
1288 ci->ci_info = NULL;
1289 } else {
1290 cpu_vendor = cpup->cpu_vendor;
1291 vendorname = cpup->cpu_vendorname;
1292 modifier = modifiers[modif];
1293 if (family > CPU_MAXFAMILY) {
1294 family = CPU_MAXFAMILY;
1295 model = CPU_DEFMODEL;
1296 } else if (model > CPU_MAXMODEL) {
1297 model = CPU_DEFMODEL;
1298 ext_model = 0;
1299 }
1300 cpufam = &cpup->cpu_family[family - CPU_MINFAMILY];
1301 if (cpufam->cpu_extended_names == NULL ||
1302 ext_model == 0)
1303 name = cpufam->cpu_models[model];
1304 else {
1305 /*
1306 * Scan list(s) of extended model names
1307 */
1308 modlist = cpufam->cpu_extended_names;
1309 while (modlist->ext_model != 0) {
1310 if (modlist->ext_model == ext_model) {
1311 name =
1312 modlist->cpu_models[model];
1313 break;
1314 }
1315 modlist++;
1316 }
1317 }
1318 if (name == NULL || *name == '\0')
1319 name = cpufam->cpu_models[CPU_DEFMODEL];
1320 class = cpufam->cpu_class;
1321 ci->ci_info = cpufam->cpu_info;
1322
1323 if (cpu_vendor == CPUVENDOR_INTEL) {
1324 if (family == 6 && model >= 5) {
1325 const char *tmp;
1326 tmp = intel_family6_name(ci);
1327 if (tmp != NULL)
1328 name = tmp;
1329 }
1330 if (family == CPU_MAXFAMILY &&
1331 ci->ci_brand_id <
1332 __arraycount(i386_intel_brand) &&
1333 i386_intel_brand[ci->ci_brand_id])
1334 name =
1335 i386_intel_brand[ci->ci_brand_id];
1336 }
1337
1338 if (cpu_vendor == CPUVENDOR_AMD) {
1339 if (family == 6 && model >= 6) {
1340 if (ci->ci_brand_id == 1)
1341 /*
1342 * It's Duron. We override the
1343 * name, since it might have
1344 * been misidentified as Athlon.
1345 */
1346 name =
1347 amd_brand[ci->ci_brand_id];
1348 else
1349 brand = amd_brand_name;
1350 }
1351 if (CPUID2FAMILY(ci->ci_signature) == 0xf) {
1352 /*
1353 * Identify AMD64 CPU names.
1354 * Note family value is clipped by
1355 * CPU_MAXFAMILY.
1356 */
1357 const char *tmp;
1358 tmp = amd_amd64_name(ci);
1359 if (tmp != NULL)
1360 name = tmp;
1361 }
1362 }
1363
1364 if (cpu_vendor == CPUVENDOR_IDT && family >= 6)
1365 vendorname = "VIA";
1366 }
1367 }
1368
1369 ci->ci_cpu_class = class;
1370
1371 sz = sizeof(ci->ci_tsc_freq);
1372 (void)sysctlbyname("machdep.tsc_freq", &ci->ci_tsc_freq, &sz, NULL, 0);
1373
1374 snprintf(cpu_model, sizeof(cpu_model), "%s%s%s%s%s%s%s (%s-class)",
1375 vendorname,
1376 *modifier ? " " : "", modifier,
1377 *name ? " " : "", name,
1378 *brand ? " " : "", brand,
1379 classnames[class]);
1380 aprint_normal("%s: %s", cpuname, cpu_model);
1381
1382 if (ci->ci_tsc_freq != 0)
1383 aprint_normal(", %qd.%02qd MHz",
1384 (ci->ci_tsc_freq + 4999) / 1000000,
1385 ((ci->ci_tsc_freq + 4999) / 10000) % 100);
1386 if (ci->ci_signature != 0)
1387 aprint_normal(", id 0x%x", ci->ci_signature);
1388 aprint_normal("\n");
1389
1390 if (ci->ci_info)
1391 (*ci->ci_info)(ci);
1392
1393 /*
1394 * display CPU feature flags
1395 */
1396
1397 #define MAX_FEATURE_LEN 60 /* XXX Need to find a better way to set this */
1398
1399 feature_str[0] = CPUID_FLAGS1;
1400 feature_str[1] = CPUID2_FLAGS1;
1401 feature_str[2] = CPUID_EXT_FLAGS;
1402 feature_str[3] = NULL;
1403 feature_str[4] = NULL;
1404
1405 switch (cpu_vendor) {
1406 case CPUVENDOR_AMD:
1407 feature_str[3] = CPUID_AMD_FLAGS4;
1408 break;
1409 case CPUVENDOR_INTEL:
1410 feature_str[2] = CPUID_INTEL_EXT_FLAGS;
1411 feature_str[3] = CPUID_INTEL_FLAGS4;
1412 break;
1413 case CPUVENDOR_IDT:
1414 feature_str[4] = CPUID_FLAGS_PADLOCK;
1415 break;
1416 default:
1417 break;
1418 }
1419
1420 for (i = 0; i <= 4; i++) {
1421 if (ci->ci_feat_val[i] && feature_str[i] != NULL) {
1422 snprintb_m(buf, sizeof(buf), feature_str[i],
1423 ci->ci_feat_val[i], MAX_FEATURE_LEN);
1424 bp = buf;
1425 while (*bp != '\0') {
1426 aprint_verbose("%s: %sfeatures%c %s\n",
1427 cpuname, (i == 4)?"padlock ":"",
1428 (i == 4 || i == 0)?' ':'1' + i, bp);
1429 bp += strlen(bp) + 1;
1430 }
1431 }
1432 }
1433
1434 if (*cpu_brand_string != '\0')
1435 aprint_normal("%s: \"%s\"\n", cpuname, cpu_brand_string);
1436
1437 x86_print_cacheinfo(ci);
1438
1439 if (ci->ci_cpuid_level >= 3 && (ci->ci_feat_val[0] & CPUID_PN)) {
1440 aprint_verbose("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
1441 cpuname,
1442 ci->ci_cpu_serial[0] / 65536, ci->ci_cpu_serial[0] % 65536,
1443 ci->ci_cpu_serial[1] / 65536, ci->ci_cpu_serial[1] % 65536,
1444 ci->ci_cpu_serial[2] / 65536, ci->ci_cpu_serial[2] % 65536);
1445 }
1446
1447 if (ci->ci_cpu_class == CPUCLASS_386) {
1448 errx(1, "NetBSD requires an 80486 or later processor");
1449 }
1450
1451 if (cpu == CPU_486DLC) {
1452 #ifndef CYRIX_CACHE_WORKS
1453 aprint_error("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
1454 #else
1455 #ifndef CYRIX_CACHE_REALLY_WORKS
1456 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
1457 #else
1458 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
1459 #endif
1460 #endif
1461 }
1462
1463 /*
1464 * Everything past this point requires a Pentium or later.
1465 */
1466 if (ci->ci_cpuid_level < 0)
1467 return;
1468
1469 identifycpu_cpuids(ci);
1470
1471 #ifdef INTEL_CORETEMP
1472 if (cpu_vendor == CPUVENDOR_INTEL && ci->ci_cpuid_level >= 0x06)
1473 coretemp_register(ci);
1474 #endif
1475
1476 if (cpu_vendor == CPUVENDOR_AMD) {
1477 uint32_t data[4];
1478
1479 x86_cpuid(0x80000000, data);
1480 if (data[0] >= 0x80000007)
1481 powernow_probe(ci);
1482
1483 if ((data[0] >= 0x8000000a)
1484 && (ci->ci_feat_val[3] & CPUID_SVM) != 0) {
1485
1486 x86_cpuid(0x8000000a, data);
1487 aprint_verbose("%s: SVM Rev. %d\n", cpuname,
1488 data[0] & 0xf);
1489 aprint_verbose("%s: SVM NASID %d\n", cpuname, data[1]);
1490 snprintb_m(buf, sizeof(buf), CPUID_AMD_SVM_FLAGS,
1491 data[3], MAX_FEATURE_LEN);
1492 bp = buf;
1493 while (*bp != '\0') {
1494 aprint_verbose("%s: SVM features %s\n",
1495 cpuname, bp);
1496 bp += strlen(bp) + 1;
1497 }
1498 }
1499 }
1500
1501 #ifdef INTEL_ONDEMAND_CLOCKMOD
1502 clockmod_init();
1503 #endif
1504
1505 aprint_normal_dev(ci->ci_dev, "family %02x model %02x "
1506 "extfamily %02x extmodel %02x\n", CPUID2FAMILY(ci->ci_signature),
1507 CPUID2MODEL(ci->ci_signature), CPUID2EXTFAMILY(ci->ci_signature),
1508 CPUID2EXTMODEL(ci->ci_signature));
1509 }
1510
1511 static const char *
1512 print_cache_config(struct cpu_info *ci, int cache_tag, const char *name,
1513 const char *sep)
1514 {
1515 struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
1516 char human_num[HUMAN_BUFSIZE];
1517
1518 if (cai->cai_totalsize == 0)
1519 return sep;
1520
1521 if (sep == NULL)
1522 aprint_verbose_dev(ci->ci_dev, "");
1523 else
1524 aprint_verbose("%s", sep);
1525 if (name != NULL)
1526 aprint_verbose("%s ", name);
1527
1528 if (cai->cai_string != NULL) {
1529 aprint_verbose("%s ", cai->cai_string);
1530 } else {
1531 (void)humanize_number(human_num, sizeof(human_num),
1532 cai->cai_totalsize, "B", HN_AUTOSCALE, HN_NOSPACE);
1533 aprint_verbose("%s %dB/line ", human_num, cai->cai_linesize);
1534 }
1535 switch (cai->cai_associativity) {
1536 case 0:
1537 aprint_verbose("disabled");
1538 break;
1539 case 1:
1540 aprint_verbose("direct-mapped");
1541 break;
1542 case 0xff:
1543 aprint_verbose("fully associative");
1544 break;
1545 default:
1546 aprint_verbose("%d-way", cai->cai_associativity);
1547 break;
1548 }
1549 return ", ";
1550 }
1551
1552 static const char *
1553 print_tlb_config(struct cpu_info *ci, int cache_tag, const char *name,
1554 const char *sep)
1555 {
1556 struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
1557 char human_num[HUMAN_BUFSIZE];
1558
1559 if (cai->cai_totalsize == 0)
1560 return sep;
1561
1562 if (sep == NULL)
1563 aprint_verbose_dev(ci->ci_dev, "");
1564 else
1565 aprint_verbose("%s", sep);
1566 if (name != NULL)
1567 aprint_verbose("%s ", name);
1568
1569 if (cai->cai_string != NULL) {
1570 aprint_verbose("%s", cai->cai_string);
1571 } else {
1572 (void)humanize_number(human_num, sizeof(human_num),
1573 cai->cai_linesize, "B", HN_AUTOSCALE, HN_NOSPACE);
1574 aprint_verbose("%d %s entries ", cai->cai_totalsize,
1575 human_num);
1576 switch (cai->cai_associativity) {
1577 case 0:
1578 aprint_verbose("disabled");
1579 break;
1580 case 1:
1581 aprint_verbose("direct-mapped");
1582 break;
1583 case 0xff:
1584 aprint_verbose("fully associative");
1585 break;
1586 default:
1587 aprint_verbose("%d-way", cai->cai_associativity);
1588 break;
1589 }
1590 }
1591 return ", ";
1592 }
1593
1594 static const struct x86_cache_info *
1595 cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc)
1596 {
1597 int i;
1598
1599 for (i = 0; cai[i].cai_desc != 0; i++) {
1600 if (cai[i].cai_desc == desc)
1601 return (&cai[i]);
1602 }
1603
1604 return (NULL);
1605 }
1606
1607 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] =
1608 AMD_L2CACHE_INFO;
1609
1610 static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] =
1611 AMD_L3CACHE_INFO;
1612
1613 static void
1614 amd_cpu_cacheinfo(struct cpu_info *ci)
1615 {
1616 const struct x86_cache_info *cp;
1617 struct x86_cache_info *cai;
1618 int family, model;
1619 u_int descs[4];
1620 u_int lfunc;
1621
1622 family = (ci->ci_signature >> 8) & 15;
1623 model = CPUID2MODEL(ci->ci_signature);
1624
1625 /*
1626 * K5 model 0 has none of this info.
1627 */
1628 if (family == 5 && model == 0)
1629 return;
1630
1631 /*
1632 * Get extended values for K8 and up.
1633 */
1634 if (family == 0xf) {
1635 family += CPUID2EXTFAMILY(ci->ci_signature);
1636 model += CPUID2EXTMODEL(ci->ci_signature);
1637 }
1638
1639 /*
1640 * Determine the largest extended function value.
1641 */
1642 x86_cpuid(0x80000000, descs);
1643 lfunc = descs[0];
1644
1645 /*
1646 * Determine L1 cache/TLB info.
1647 */
1648 if (lfunc < 0x80000005) {
1649 /* No L1 cache info available. */
1650 return;
1651 }
1652
1653 x86_cpuid(0x80000005, descs);
1654
1655 /*
1656 * K6-III and higher have large page TLBs.
1657 */
1658 if ((family == 5 && model >= 9) || family >= 6) {
1659 cai = &ci->ci_cinfo[CAI_ITLB2];
1660 cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
1661 cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
1662 cai->cai_linesize = (4 * 1024 * 1024);
1663
1664 cai = &ci->ci_cinfo[CAI_DTLB2];
1665 cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
1666 cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
1667 cai->cai_linesize = (4 * 1024 * 1024);
1668 }
1669
1670 cai = &ci->ci_cinfo[CAI_ITLB];
1671 cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
1672 cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
1673 cai->cai_linesize = (4 * 1024);
1674
1675 cai = &ci->ci_cinfo[CAI_DTLB];
1676 cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
1677 cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
1678 cai->cai_linesize = (4 * 1024);
1679
1680 cai = &ci->ci_cinfo[CAI_DCACHE];
1681 cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
1682 cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
1683 cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]);
1684
1685 cai = &ci->ci_cinfo[CAI_ICACHE];
1686 cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
1687 cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
1688 cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
1689
1690 /*
1691 * Determine L2 cache/TLB info.
1692 */
1693 if (lfunc < 0x80000006) {
1694 /* No L2 cache info available. */
1695 return;
1696 }
1697
1698 x86_cpuid(0x80000006, descs);
1699
1700 cai = &ci->ci_cinfo[CAI_L2CACHE];
1701 cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
1702 cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
1703 cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
1704
1705 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
1706 cai->cai_associativity);
1707 if (cp != NULL)
1708 cai->cai_associativity = cp->cai_associativity;
1709 else
1710 cai->cai_associativity = 0; /* XXX Unknown/reserved */
1711
1712 /*
1713 * Determine L3 cache info on AMD Family 10h processors
1714 */
1715 if (family == 0x10) {
1716 cai = &ci->ci_cinfo[CAI_L3CACHE];
1717 cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]);
1718 cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]);
1719 cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]);
1720
1721 cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info,
1722 cai->cai_associativity);
1723 if (cp != NULL)
1724 cai->cai_associativity = cp->cai_associativity;
1725 else
1726 cai->cai_associativity = 0; /* XXX Unkn/Rsvd */
1727 }
1728 }
1729
1730 static void
1731 via_cpu_cacheinfo(struct cpu_info *ci)
1732 {
1733 struct x86_cache_info *cai;
1734 int family, model, stepping;
1735 u_int descs[4];
1736 u_int lfunc;
1737
1738 family = (ci->ci_signature >> 8) & 15;
1739 model = CPUID2MODEL(ci->ci_signature);
1740 stepping = CPUID2STEPPING(ci->ci_signature);
1741
1742 /*
1743 * Determine the largest extended function value.
1744 */
1745 x86_cpuid(0x80000000, descs);
1746 lfunc = descs[0];
1747
1748 /*
1749 * Determine L1 cache/TLB info.
1750 */
1751 if (lfunc < 0x80000005) {
1752 /* No L1 cache info available. */
1753 return;
1754 }
1755
1756 x86_cpuid(0x80000005, descs);
1757
1758 cai = &ci->ci_cinfo[CAI_ITLB];
1759 cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]);
1760 cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]);
1761 cai->cai_linesize = (4 * 1024);
1762
1763 cai = &ci->ci_cinfo[CAI_DTLB];
1764 cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]);
1765 cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]);
1766 cai->cai_linesize = (4 * 1024);
1767
1768 cai = &ci->ci_cinfo[CAI_DCACHE];
1769 cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]);
1770 cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]);
1771 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]);
1772 if (model == 9 && stepping == 8) {
1773 /* Erratum: stepping 8 reports 4 when it should be 2 */
1774 cai->cai_associativity = 2;
1775 }
1776
1777 cai = &ci->ci_cinfo[CAI_ICACHE];
1778 cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]);
1779 cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]);
1780 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]);
1781 if (model == 9 && stepping == 8) {
1782 /* Erratum: stepping 8 reports 4 when it should be 2 */
1783 cai->cai_associativity = 2;
1784 }
1785
1786 /*
1787 * Determine L2 cache/TLB info.
1788 */
1789 if (lfunc < 0x80000006) {
1790 /* No L2 cache info available. */
1791 return;
1792 }
1793
1794 x86_cpuid(0x80000006, descs);
1795
1796 cai = &ci->ci_cinfo[CAI_L2CACHE];
1797 if (model >= 9) {
1798 cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]);
1799 cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]);
1800 cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]);
1801 } else {
1802 cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]);
1803 cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]);
1804 cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]);
1805 }
1806 }
1807
1808 static void
1809 x86_print_cacheinfo(struct cpu_info *ci)
1810 {
1811 const char *sep;
1812
1813 if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 ||
1814 ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) {
1815 sep = print_cache_config(ci, CAI_ICACHE, "I-cache", NULL);
1816 sep = print_cache_config(ci, CAI_DCACHE, "D-cache", sep);
1817 if (sep != NULL)
1818 aprint_verbose("\n");
1819 }
1820 if (ci->ci_cinfo[CAI_L2CACHE].cai_totalsize != 0) {
1821 sep = print_cache_config(ci, CAI_L2CACHE, "L2 cache", NULL);
1822 if (sep != NULL)
1823 aprint_verbose("\n");
1824 }
1825 if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) {
1826 sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL);
1827 sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep);
1828 if (sep != NULL)
1829 aprint_verbose("\n");
1830 }
1831 if (ci->ci_cinfo[CAI_DTLB].cai_totalsize != 0) {
1832 sep = print_tlb_config(ci, CAI_DTLB, "DTLB", NULL);
1833 sep = print_tlb_config(ci, CAI_DTLB2, NULL, sep);
1834 if (sep != NULL)
1835 aprint_verbose("\n");
1836 }
1837 if (ci->ci_cinfo[CAI_L3CACHE].cai_totalsize != 0) {
1838 sep = print_cache_config(ci, CAI_L3CACHE, "L3 cache", NULL);
1839 if (sep != NULL)
1840 aprint_verbose("\n");
1841 }
1842 }
1843
1844 static void
1845 powernow_probe(struct cpu_info *ci)
1846 {
1847 uint32_t regs[4];
1848 char buf[256];
1849
1850 x86_cpuid(0x80000007, regs);
1851
1852 snprintb(buf, sizeof(buf), CPUID_APM_FLAGS, regs[3]);
1853 aprint_normal_dev(ci->ci_dev, "AMD Power Management features: %s\n",
1854 buf);
1855 }
1856