1 /* $NetBSD: i386.c,v 1.19 2009/05/14 20:16:10 pgoyette Exp $ */
4 * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Frank van der Linden, and by Jason R. Thorpe.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
33 * Copyright (c)2008 YAMAMOTO Takashi,
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
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.
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
58 #include <sys/cdefs.h>
60 __RCSID("$NetBSD: i386.c,v 1.19 2009/05/14 20:16:10 pgoyette Exp $");
63 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <sys/bitops.h>
66 #include <sys/sysctl.h>
76 #include <machine/specialreg.h>
77 #include <machine/cpu.h>
79 #include <x86/cpuvar.h>
80 #include <x86/cputypes.h>
81 #include <x86/cacheinfo.h>
83 #include "../cpuctl.h"
85 /* Size of buffer for printing humanized numbers */
86 #define HUMAN_BUFSIZE sizeof("999KB")
88 #define x86_cpuid(a,b) x86_cpuid2((a),0,(b))
90 void x86_cpuid2(uint32_t, uint32_t, uint32_t *);
91 void x86_identify(void);
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
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
;
112 uint32_t ci_initapicid
;
113 struct x86_cache_info ci_cinfo
[CAI_COUNT
];
114 void (*ci_info
)(struct cpu_info
*);
117 struct cpu_nocpuid_nameclass
{
119 const char *cpu_vendorname
;
120 const char *cpu_name
;
122 void (*cpu_setup
)(struct cpu_info
*);
123 void (*cpu_cacheinfo
)(struct cpu_info
*);
124 void (*cpu_info
)(struct cpu_info
*);
127 struct cpu_extend_nameclass
{
129 const char *cpu_models
[CPU_MAXMODEL
+1];
132 struct cpu_cpuid_nameclass
{
135 const char *cpu_vendorname
;
136 struct cpu_cpuid_family
{
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];
146 static const struct x86_cache_info intel_cpuid_cache_info
[] = INTEL_CACHE_INFO
;
149 * Map Brand ID from cpuid instruction to brand name.
150 * Source: Intel Processor Identification and the CPUID Instruction, AP-485
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 */
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 */
167 "Mobile Pentium 4", /* Mobile Intel (R) Pentium (R) 4 processor-M */
168 "Mobile Celeron", /* Mobile Intel (R) Celeron (R) processor */
172 * AMD processors don't have Brand IDs, so we need these names for probe.
174 static const char * const amd_brand
[] = {
176 "Duron", /* AMD Duron(tm) */
177 "MP", /* AMD Athlon(tm) MP */
178 "XP", /* AMD Athlon(tm) XP */
179 "4" /* AMD Athlon(tm) 4 */
182 static int cpu_vendor
;
183 static char cpu_brand_string
[49];
184 static char amd_brand_name
[48];
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 *,
195 static const char *print_tlb_config(struct cpu_info
*, int, 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
*);
210 static char cpu_model
[120];
213 * Note: these are just the ones that may not have a cpuid instruction.
214 * We deal with the rest in a different way.
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 */
233 const char *classnames
[] = {
240 const char *modifiers
[] = {
247 struct cpu_extend_nameclass intel_family6_ext_models
[] = {
248 { /* Extended models 1x */
251 NULL
, "EP80579 Integrated Processor",
252 "Celeron (45nm)", "Core 2 Extreme",
254 "Core i7 (Nehalem)", NULL
,
255 "Atom", "XeonMP (Nehalem)",
258 0x00, { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
259 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
} }
262 const struct cpu_cpuid_nameclass i386_cpuid_cpus
[] = {
271 "486DX", "486DX", "486SX", "486DX2", "486SL",
272 "486SX2", 0, "486DX2 W/B Enhanced",
273 "486DX4", 0, 0, 0, 0, 0, 0, 0,
285 "Pentium (P5 A-step)", "Pentium (P5)",
286 "Pentium (P54C)", "Pentium (P24T)",
287 "Pentium/MMX", "Pentium", 0,
288 "Pentium (P54C)", "Pentium/MMX (Tillamook)",
290 "Pentium" /* Default */
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)",
313 "Pentium Pro, II or III" /* Default */
316 intel_family_new_probe
,
318 &intel_family6_ext_models
[0],
324 0, 0, 0, 0, 0, 0, 0, 0,
325 0, 0, 0, 0, 0, 0, 0, 0,
326 "Pentium 4" /* Default */
329 intel_family_new_probe
,
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 */
359 "K5", "K5", "K5", "K5", 0, 0, "K6",
360 "K6", "K6-2", "K6-III", "Geode LX", 0, 0,
362 "K5 or K6" /* Default */
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 */
388 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 0, 0, 0, 0, 0, 0, 0,
390 "Unknown K8 (Athlon)" /* Default */
408 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
411 cyrix6x86_cpu_setup
, /* XXX ?? */
421 "MMX-enhanced MediaGX (GXm)", /* or Geode? */
422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
434 "6x86MX", 0, 0, 0, 0, 0, 0, 0,
435 0, 0, 0, 0, 0, 0, 0, 0,
436 "6x86MX" /* Default */
447 0, 0, 0, 0, 0, 0, 0, 0,
448 0, 0, 0, 0, 0, 0, 0, 0,
449 "Unknown 6x86MX" /* Default */
457 { /* MediaGX is now owned by National Semiconductor */
459 CPUVENDOR_CYRIX
, /* XXX */
460 "National Semiconductor",
461 /* Family 4, NSC never had any of these */
465 0, 0, 0, 0, 0, 0, 0, 0,
466 0, 0, 0, 0, 0, 0, 0, 0,
467 "486 compatible" /* Default */
474 /* Family 5: Geode family, formerly MediaGX */
480 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
481 "Geode" /* Default */
488 /* Family 6, not yet available from NSC */
492 0, 0, 0, 0, 0, 0, 0, 0,
493 0, 0, 0, 0, 0, 0, 0, 0,
494 "Pentium Pro compatible" /* Default */
501 /* Family > 6, not yet available from NSC */
505 0, 0, 0, 0, 0, 0, 0, 0,
506 0, 0, 0, 0, 0, 0, 0, 0,
507 "Pentium Pro compatible" /* Default */
519 /* Family 4, IDT never had any of these */
523 0, 0, 0, 0, 0, 0, 0, 0,
524 0, 0, 0, 0, 0, 0, 0, 0,
525 "486 compatible" /* Default */
536 0, 0, 0, 0, "WinChip C6", 0, 0, 0,
537 "WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0,
538 "WinChip" /* Default */
545 /* Family 6, VIA acquired IDT Centaur design subsidiary */
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",
553 "Unknown VIA/IDT" /* Default */
560 /* Family > 6, not yet available from VIA */
564 0, 0, 0, 0, 0, 0, 0, 0,
565 0, 0, 0, 0, 0, 0, 0, 0,
566 "Pentium Pro compatible" /* Default */
578 /* Family 4, Transmeta never had any of these */
582 0, 0, 0, 0, 0, 0, 0, 0,
583 0, 0, 0, 0, 0, 0, 0, 0,
584 "486 compatible" /* Default */
595 0, 0, 0, 0, 0, 0, 0, 0,
596 0, 0, 0, 0, 0, 0, 0, 0,
597 "Crusoe" /* Default */
604 /* Family 6, not yet available from Transmeta */
608 0, 0, 0, 0, 0, 0, 0, 0,
609 0, 0, 0, 0, 0, 0, 0, 0,
610 "Pentium Pro compatible" /* Default */
617 /* Family > 6, not yet available from Transmeta */
621 0, 0, 0, 0, 0, 0, 0, 0,
622 0, 0, 0, 0, 0, 0, 0, 0,
623 "Pentium Pro compatible" /* Default */
634 * disable the TSC such that we don't use the TSC in microtime(9)
635 * because some CPUs got the implementation wrong.
638 disable_tsc(struct cpu_info
*ci
)
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");
647 cyrix6x86_cpu_setup(struct cpu_info
*ci
)
651 * Do not disable the TSC on the Geode GX, it's reported to
654 if (ci
->ci_signature
!= 0x552)
659 winchip_cpu_setup(struct cpu_info
*ci
)
661 switch (CPUID2MODEL(ci
->ci_signature
)) { /* model */
662 case 4: /* WinChip C6 */
669 identifycpu_cpuids(struct cpu_info
*ci
)
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
;
678 aprint_verbose("%s: Initial APIC ID %u\n", cpuname
, ci
->ci_initapicid
);
679 ci
->ci_packageid
= ci
->ci_initapicid
;
682 if (cpu_vendor
!= CPUVENDOR_INTEL
) {
690 if ((ci
->ci_feat_val
[0] & CPUID_HTT
) != 0) {
692 lp_max
= (descs
[1] >> 16) & 0xff;
696 x86_cpuid2(4, 0, descs
);
697 core_max
= (descs
[0] >> 26) + 1;
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
);
706 aprint_verbose("%s: Cluster/Package ID %u\n", cpuname
,
709 u_int core_mask
= __BITS(smt_bits
, smt_bits
+ core_bits
- 1);
712 __SHIFTOUT(ci
->ci_initapicid
, core_mask
);
713 aprint_verbose("%s: Core ID %u\n", cpuname
, ci
->ci_coreid
);
716 u_int smt_mask
= __BITS((int)0, (int)(smt_bits
- 1));
718 ci
->ci_smtid
= __SHIFTOUT(ci
->ci_initapicid
, smt_mask
);
719 aprint_verbose("%s: SMT ID %u\n", cpuname
, ci
->ci_smtid
);
724 via_cpu_probe(struct cpu_info
*ci
)
726 u_int model
= CPUID2MODEL(ci
->ci_signature
);
727 u_int stepping
= CPUID2STEPPING(ci
->ci_signature
);
732 * Determine the largest extended function value.
734 x86_cpuid(0x80000000, descs
);
738 * Determine the extended feature flags.
740 if (lfunc
>= 0x80000001) {
741 x86_cpuid(0x80000001, descs
);
742 ci
->ci_feat_val
[2] |= descs
[3];
748 /* Nehemiah or Esther */
749 x86_cpuid(0xc0000000, descs
);
751 if (lfunc
< 0xc0000001) /* no ACE, no RNG */
754 x86_cpuid(0xc0000001, descs
);
756 if (model
> 0x9 || stepping
>= 8) { /* ACE */
757 if (lfunc
& CPUID_VIA_HAS_ACE
) {
758 ci
->ci_feat_val
[4] = lfunc
;
764 intel_family6_name(struct cpu_info
*ci
)
766 int model
= CPUID2MODEL(ci
->ci_signature
);
767 const char *ret
= NULL
;
768 u_int l2cache
= ci
->ci_cinfo
[CAI_L2CACHE
].cai_totalsize
;
774 ret
= "Celeron (Covington)";
777 ret
= "Mobile Pentium II (Dixon)";
782 case 1 * 1024 * 1024:
783 case 2 * 1024 * 1024:
784 ret
= "Pentium II Xeon";
787 } else if (model
== 6) {
791 ret
= "Mobile Pentium II";
794 } else if (model
== 7) {
799 case 1 * 1024 * 1024:
800 case 2 * 1024 * 1024:
801 ret
= "Pentium III Xeon";
804 } else if (model
>= 8) {
805 if (ci
->ci_brand_id
&& ci
->ci_brand_id
< 0x10) {
806 switch (ci
->ci_brand_id
) {
808 if (ci
->ci_signature
== 0x6B1)
812 if (ci
->ci_signature
>= 0xF13)
813 ret
= "genuine processor";
816 if (ci
->ci_signature
>= 0xF13)
820 if (ci
->ci_signature
< 0xF13)
825 ret
= i386_intel_brand
[ci
->ci_brand_id
];
833 * Identify AMD64 CPU names from cpuid.
836 * "Revision Guide for AMD Athlon 64 and AMD Opteron Processors"
837 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25759.pdf
838 * "Revision Guide for AMD NPT Family 0Fh Processors"
839 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
840 * and other miscellaneous reports.
843 amd_amd64_name(struct cpu_info
*ci
)
845 int extfamily
, extmodel
, model
;
846 const char *ret
= NULL
;
848 model
= CPUID2MODEL(ci
->ci_signature
);
849 extfamily
= CPUID2EXTFAMILY(ci
->ci_signature
);
850 extmodel
= CPUID2EXTMODEL(ci
->ci_signature
);
857 case 0x2: /* rev JH-E1/E6 */
858 case 0x4: /* rev JH-F2 */
859 ret
= "Dual-Core Opteron";
865 case 0x2: /* rev JH-E6 (Toledo) */
866 ret
= "Dual-Core Opteron or Athlon 64 X2";
868 case 0x4: /* rev JH-F2 (Windsor) */
869 ret
= "Athlon 64 FX or Athlon 64 X2";
875 case 0x0: /* rev SH-B0/C0/CG (ClawHammer) */
876 case 0x1: /* rev SH-D0 */
879 case 0x2: /* rev SH-E5 (Lancaster?) */
880 ret
= "Mobile Athlon 64 or Turion 64";
886 case 0x0: /* rev SH-B0/B3/C0/CG (SledgeHammer?) */
887 ret
= "Opteron or Athlon 64 FX";
889 case 0x1: /* rev SH-D0 */
890 case 0x2: /* rev SH-E4 */
897 case 0x0: /* rev SH-CG (ClawHammer) */
898 case 0x1: /* rev SH-D0 */
901 case 0x2: /* rev DH-E4, SH-E4 */
902 ret
= "Athlon 64 or Athlon 64 FX or Opteron";
908 case 0x0: /* rev CH-CG */
909 case 0x1: /* rev CH-D0 */
910 ret
= "Athlon 64 or Sempron";
912 case 0x4: /* rev BH-F2 */
913 ret
= "Turion 64 X2";
919 case 0x0: /* rev CH-CG */
920 case 0x1: /* rev CH-D0 */
923 case 0x2: /* rev BH-E4 (Manchester) */
924 case 0x4: /* rev BH-F2 (Windsor) */
925 ret
= "Athlon 64 X2";
927 case 0x6: /* rev BH-G1 (Brisbane) */
928 ret
= "Athlon X2 or Athlon 64 X2";
934 case 0x0: /* rev DH-CG (Newcastle) */
935 case 0x1: /* rev DH-D0 (Winchester) */
936 case 0x2: /* rev DH-E3/E6 */
937 ret
= "Athlon 64 or Sempron";
943 case 0x0: /* rev DH-CG (Newcastle?) */
944 ret
= "Athlon 64 or Sempron";
950 case 0x0: /* rev DH-CG (Newcastle/Paris) */
951 case 0x1: /* rev DH-D0 (Winchester/Victoria) */
952 case 0x2: /* rev DH-E3/E6 (Venice/Palermo) */
953 case 0x4: /* rev DH-F2 (Orleans/Manila) */
954 case 0x5: /* rev DH-F2 (Orleans/Manila) */
955 case 0x6: /* rev DH-G1 */
956 ret
= "Athlon 64 or Sempron";
961 ret
= "Unknown AMD64 CPU";
970 ret
= "Unknown AMD64 CPU";
980 cpu_probe_base_features(struct cpu_info
*ci
)
982 const struct x86_cache_info
*cai
;
984 int iterations
, i
, j
;
989 if (ci
->ci_cpuid_level
< 0)
993 ci
->ci_cpuid_level
= descs
[0];
994 ci
->ci_vendor
[0] = descs
[1];
995 ci
->ci_vendor
[2] = descs
[2];
996 ci
->ci_vendor
[1] = descs
[3];
997 ci
->ci_vendor
[3] = 0;
999 x86_cpuid(0x80000000, brand
);
1000 if (brand
[0] >= 0x80000004) {
1001 x86_cpuid(0x80000002, brand
);
1002 x86_cpuid(0x80000003, brand
+ 4);
1003 x86_cpuid(0x80000004, brand
+ 8);
1004 for (i
= 0; i
< 48; i
++)
1005 if (((char *) brand
)[i
] != ' ')
1007 memcpy(cpu_brand_string
, ((char *) brand
) + i
, 48 - i
);
1010 if (ci
->ci_cpuid_level
< 1)
1013 x86_cpuid(1, descs
);
1014 ci
->ci_signature
= descs
[0];
1015 miscbytes
= descs
[1];
1016 ci
->ci_feat_val
[1] = descs
[2];
1017 ci
->ci_feat_val
[0] = descs
[3];
1019 /* Brand is low order 8 bits of ebx */
1020 ci
->ci_brand_id
= miscbytes
& 0xff;
1021 ci
->ci_initapicid
= (miscbytes
>> 24) & 0xff;
1022 if (ci
->ci_cpuid_level
< 2)
1026 * Parse the cache info from `cpuid', if we have it.
1027 * XXX This is kinda ugly, but hey, so is the architecture...
1030 x86_cpuid(2, descs
);
1032 iterations
= descs
[0] & 0xff;
1033 while (iterations
-- > 0) {
1034 for (i
= 0; i
< 4; i
++) {
1035 if (descs
[i
] & 0x80000000)
1037 for (j
= 0; j
< 4; j
++) {
1038 if (i
== 0 && j
== 0)
1040 desc
= (descs
[i
] >> (j
* 8)) & 0xff;
1043 cai
= cache_info_lookup(intel_cpuid_cache_info
,
1046 ci
->ci_cinfo
[cai
->cai_index
] = *cai
;
1049 x86_cpuid(2, descs
);
1052 if (ci
->ci_cpuid_level
< 3)
1056 * If the processor serial number misfeature is present and supported,
1059 if ((ci
->ci_feat_val
[0] & CPUID_PN
) != 0) {
1060 ci
->ci_cpu_serial
[0] = ci
->ci_signature
;
1061 x86_cpuid(3, descs
);
1062 ci
->ci_cpu_serial
[2] = descs
[2];
1063 ci
->ci_cpu_serial
[1] = descs
[3];
1068 cpu_probe_features(struct cpu_info
*ci
)
1070 const struct cpu_cpuid_nameclass
*cpup
= NULL
;
1071 int i
, xmax
, family
;
1073 cpu_probe_base_features(ci
);
1075 if (ci
->ci_cpuid_level
< 1)
1078 xmax
= __arraycount(i386_cpuid_cpus
);
1079 for (i
= 0; i
< xmax
; i
++) {
1080 if (!strncmp((char *)ci
->ci_vendor
,
1081 i386_cpuid_cpus
[i
].cpu_id
, 12)) {
1082 cpup
= &i386_cpuid_cpus
[i
];
1090 family
= (ci
->ci_signature
>> 8) & 0xf;
1092 if (family
> CPU_MAXFAMILY
) {
1093 family
= CPU_MAXFAMILY
;
1095 i
= family
- CPU_MINFAMILY
;
1097 if (cpup
->cpu_family
[i
].cpu_probe
== NULL
)
1100 (*cpup
->cpu_family
[i
].cpu_probe
)(ci
);
1104 intel_family_new_probe(struct cpu_info
*ci
)
1108 x86_cpuid(0x80000000, descs
);
1111 * Determine extended feature flags.
1113 if (descs
[0] >= 0x80000001) {
1114 x86_cpuid(0x80000001, descs
);
1115 ci
->ci_feat_val
[2] |= descs
[3];
1116 ci
->ci_feat_val
[3] |= descs
[2];
1121 amd_family6_probe(struct cpu_info
*ci
)
1127 x86_cpuid(0x80000000, descs
);
1130 * Determine the extended feature flags.
1132 if (descs
[0] >= 0x80000001) {
1133 x86_cpuid(0x80000001, descs
);
1134 ci
->ci_feat_val
[2] |= descs
[3]; /* %edx */
1135 ci
->ci_feat_val
[3] = descs
[2]; /* %ecx */
1138 if (*cpu_brand_string
== '\0')
1141 for (i
= 1; i
< __arraycount(amd_brand
); i
++)
1142 if ((p
= strstr(cpu_brand_string
, amd_brand
[i
])) != NULL
) {
1143 ci
->ci_brand_id
= i
;
1144 strlcpy(amd_brand_name
, p
, sizeof(amd_brand_name
));
1150 amd_family5_setup(struct cpu_info
*ci
)
1153 switch (CPUID2MODEL(ci
->ci_signature
)) {
1154 case 0: /* AMD-K5 Model 0 */
1156 * According to the AMD Processor Recognition App Note,
1157 * the AMD-K5 Model 0 uses the wrong bit to indicate
1158 * support for global PTEs, instead using bit 9 (APIC)
1159 * rather than bit 13 (i.e. "0x200" vs. 0x2000". Oops!).
1161 if (ci
->ci_feat_val
[0] & CPUID_APIC
)
1162 ci
->ci_feat_val
[0] =
1163 (ci
->ci_feat_val
[0] & ~CPUID_APIC
) | CPUID_PGE
;
1165 * XXX But pmap_pg_g is already initialized -- need to kick
1166 * XXX the pmap somehow. How does the MP branch do this?
1173 tmx86_get_longrun_status(u_int
*frequency
, u_int
*voltage
, u_int
*percentage
)
1177 x86_cpuid(0x80860007, descs
);
1178 *frequency
= descs
[0];
1179 *voltage
= descs
[1];
1180 *percentage
= descs
[2];
1184 transmeta_cpu_info(struct cpu_info
*ci
)
1186 u_int descs
[4], nreg
;
1187 u_int frequency
, voltage
, percentage
;
1189 x86_cpuid(0x80860000, descs
);
1191 if (nreg
>= 0x80860001) {
1192 x86_cpuid(0x80860001, descs
);
1193 aprint_verbose_dev(ci
->ci_dev
, "Processor revision %u.%u.%u.%u\n",
1194 (descs
[1] >> 24) & 0xff,
1195 (descs
[1] >> 16) & 0xff,
1196 (descs
[1] >> 8) & 0xff,
1199 if (nreg
>= 0x80860002) {
1200 x86_cpuid(0x80860002, descs
);
1201 aprint_verbose_dev(ci
->ci_dev
, "Code Morphing Software Rev: %u.%u.%u-%u-%u\n",
1202 (descs
[1] >> 24) & 0xff,
1203 (descs
[1] >> 16) & 0xff,
1204 (descs
[1] >> 8) & 0xff,
1208 if (nreg
>= 0x80860006) {
1215 for (i
=0; i
<4; i
++) {
1216 x86_cpuid(0x80860003 + i
, info
.descs
[i
]);
1218 info
.text
[64] = '\0';
1219 aprint_verbose_dev(ci
->ci_dev
, "%s\n", info
.text
);
1222 if (nreg
>= 0x80860007) {
1223 tmx86_get_longrun_status(&frequency
,
1224 &voltage
, &percentage
);
1225 aprint_verbose_dev(ci
->ci_dev
, "LongRun <%dMHz %dmV %d%%>\n",
1226 frequency
, voltage
, percentage
);
1231 identifycpu(const char *cpuname
)
1233 const char *name
= "", *modifier
, *vendorname
, *brand
= "";
1234 int class = CPUCLASS_386
, i
, xmax
;
1235 int modif
, family
, model
, ext_model
;
1236 const struct cpu_extend_nameclass
*modlist
;
1237 const struct cpu_cpuid_nameclass
*cpup
= NULL
;
1238 const struct cpu_cpuid_family
*cpufam
;
1239 const char *feature_str
[5];
1240 struct cpu_info
*ci
, cistore
;
1242 extern int cpu_info_level
;
1248 memset(ci
, 0, sizeof(*ci
));
1249 ci
->ci_dev
= cpuname
;
1252 ci
->ci_cpuid_level
= cpu_info_level
;
1253 cpu_probe_features(ci
);
1255 if (ci
->ci_cpuid_level
== -1) {
1256 if ((size_t)cpu
>= __arraycount(i386_nocpuid_cpus
))
1257 errx(1, "unknown cpu type %d", cpu
);
1258 name
= i386_nocpuid_cpus
[cpu
].cpu_name
;
1259 cpu_vendor
= i386_nocpuid_cpus
[cpu
].cpu_vendor
;
1260 vendorname
= i386_nocpuid_cpus
[cpu
].cpu_vendorname
;
1261 class = i386_nocpuid_cpus
[cpu
].cpu_class
;
1262 ci
->ci_info
= i386_nocpuid_cpus
[cpu
].cpu_info
;
1265 xmax
= __arraycount(i386_cpuid_cpus
);
1266 modif
= (ci
->ci_signature
>> 12) & 0x3;
1267 family
= CPUID2FAMILY(ci
->ci_signature
);
1268 if (family
< CPU_MINFAMILY
)
1269 errx(1, "identifycpu: strange family value");
1270 model
= CPUID2MODEL(ci
->ci_signature
);
1271 ext_model
= CPUID2EXTMODEL(ci
->ci_signature
);
1273 for (i
= 0; i
< xmax
; i
++) {
1274 if (!strncmp((char *)ci
->ci_vendor
,
1275 i386_cpuid_cpus
[i
].cpu_id
, 12)) {
1276 cpup
= &i386_cpuid_cpus
[i
];
1282 cpu_vendor
= CPUVENDOR_UNKNOWN
;
1283 if (ci
->ci_vendor
[0] != '\0')
1284 vendorname
= (char *)&ci
->ci_vendor
[0];
1286 vendorname
= "Unknown";
1287 if (family
>= CPU_MAXFAMILY
)
1288 family
= CPU_MINFAMILY
;
1294 cpu_vendor
= cpup
->cpu_vendor
;
1295 vendorname
= cpup
->cpu_vendorname
;
1296 modifier
= modifiers
[modif
];
1297 if (family
> CPU_MAXFAMILY
) {
1298 family
= CPU_MAXFAMILY
;
1299 model
= CPU_DEFMODEL
;
1300 } else if (model
> CPU_MAXMODEL
) {
1301 model
= CPU_DEFMODEL
;
1304 cpufam
= &cpup
->cpu_family
[family
- CPU_MINFAMILY
];
1305 if (cpufam
->cpu_extended_names
== NULL
||
1307 name
= cpufam
->cpu_models
[model
];
1310 * Scan list(s) of extended model names
1312 modlist
= cpufam
->cpu_extended_names
;
1313 while (modlist
->ext_model
!= 0) {
1314 if (modlist
->ext_model
== ext_model
) {
1316 modlist
->cpu_models
[model
];
1322 if (name
== NULL
|| *name
== '\0')
1323 name
= cpufam
->cpu_models
[CPU_DEFMODEL
];
1324 class = cpufam
->cpu_class
;
1325 ci
->ci_info
= cpufam
->cpu_info
;
1327 if (cpu_vendor
== CPUVENDOR_INTEL
) {
1328 if (family
== 6 && model
>= 5) {
1330 tmp
= intel_family6_name(ci
);
1334 if (family
== CPU_MAXFAMILY
&&
1336 __arraycount(i386_intel_brand
) &&
1337 i386_intel_brand
[ci
->ci_brand_id
])
1339 i386_intel_brand
[ci
->ci_brand_id
];
1342 if (cpu_vendor
== CPUVENDOR_AMD
) {
1343 if (family
== 6 && model
>= 6) {
1344 if (ci
->ci_brand_id
== 1)
1346 * It's Duron. We override the
1347 * name, since it might have
1348 * been misidentified as Athlon.
1351 amd_brand
[ci
->ci_brand_id
];
1353 brand
= amd_brand_name
;
1355 if (CPUID2FAMILY(ci
->ci_signature
) == 0xf) {
1357 * Identify AMD64 CPU names.
1358 * Note family value is clipped by
1362 tmp
= amd_amd64_name(ci
);
1368 if (cpu_vendor
== CPUVENDOR_IDT
&& family
>= 6)
1373 ci
->ci_cpu_class
= class;
1375 sz
= sizeof(ci
->ci_tsc_freq
);
1376 (void)sysctlbyname("machdep.tsc_freq", &ci
->ci_tsc_freq
, &sz
, NULL
, 0);
1378 snprintf(cpu_model
, sizeof(cpu_model
), "%s%s%s%s%s%s%s (%s-class)",
1380 *modifier
? " " : "", modifier
,
1381 *name
? " " : "", name
,
1382 *brand
? " " : "", brand
,
1384 aprint_normal("%s: %s", cpuname
, cpu_model
);
1386 if (ci
->ci_tsc_freq
!= 0)
1387 aprint_normal(", %qd.%02qd MHz",
1388 (ci
->ci_tsc_freq
+ 4999) / 1000000,
1389 ((ci
->ci_tsc_freq
+ 4999) / 10000) % 100);
1390 if (ci
->ci_signature
!= 0)
1391 aprint_normal(", id 0x%x", ci
->ci_signature
);
1392 aprint_normal("\n");
1398 * display CPU feature flags
1401 #define MAX_FEATURE_LEN 60 /* XXX Need to find a better way to set this */
1403 feature_str
[0] = CPUID_FLAGS1
;
1404 feature_str
[1] = CPUID2_FLAGS1
;
1405 feature_str
[2] = CPUID_EXT_FLAGS
;
1406 feature_str
[3] = NULL
;
1407 feature_str
[4] = NULL
;
1409 switch (cpu_vendor
) {
1411 feature_str
[3] = CPUID_AMD_FLAGS4
;
1413 case CPUVENDOR_INTEL
:
1414 feature_str
[2] = CPUID_INTEL_EXT_FLAGS
;
1415 feature_str
[3] = CPUID_INTEL_FLAGS4
;
1417 case CPUVENDOR_CYRIX
:
1418 feature_str
[4] = CPUID_FLAGS_PADLOCK
;
1424 for (i
= 0; i
<= 4; i
++) {
1425 if (ci
->ci_feat_val
[i
] && feature_str
[i
] != NULL
) {
1426 snprintb_m(buf
, sizeof(buf
), feature_str
[i
],
1427 ci
->ci_feat_val
[i
], MAX_FEATURE_LEN
);
1429 while (*bp
!= '\0') {
1430 aprint_verbose("%s: %sfeatures%c %s\n",
1431 cpuname
, (i
== 4)?"padlock ":"",
1432 (i
== 4 || i
== 0)?' ':'1' + i
, bp
);
1433 bp
+= strlen(bp
) + 1;
1438 if (*cpu_brand_string
!= '\0')
1439 aprint_normal("%s: \"%s\"\n", cpuname
, cpu_brand_string
);
1441 x86_print_cacheinfo(ci
);
1443 if (ci
->ci_cpuid_level
>= 3 && (ci
->ci_feat_val
[0] & CPUID_PN
)) {
1444 aprint_verbose("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
1446 ci
->ci_cpu_serial
[0] / 65536, ci
->ci_cpu_serial
[0] % 65536,
1447 ci
->ci_cpu_serial
[1] / 65536, ci
->ci_cpu_serial
[1] % 65536,
1448 ci
->ci_cpu_serial
[2] / 65536, ci
->ci_cpu_serial
[2] % 65536);
1451 if (ci
->ci_cpu_class
== CPUCLASS_386
) {
1452 errx(1, "NetBSD requires an 80486 or later processor");
1455 if (cpu
== CPU_486DLC
) {
1456 #ifndef CYRIX_CACHE_WORKS
1457 aprint_error("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
1459 #ifndef CYRIX_CACHE_REALLY_WORKS
1460 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
1462 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
1468 * Everything past this point requires a Pentium or later.
1470 if (ci
->ci_cpuid_level
< 0)
1473 identifycpu_cpuids(ci
);
1475 #ifdef INTEL_CORETEMP
1476 if (cpu_vendor
== CPUVENDOR_INTEL
&& ci
->ci_cpuid_level
>= 0x06)
1477 coretemp_register(ci
);
1480 if (cpu_vendor
== CPUVENDOR_AMD
) {
1483 if ((ci
->ci_feat_val
[3] & CPUID_SVM
) != 0) {
1486 x86_cpuid(0x8000000a, data
);
1487 aprint_verbose("%s: SVM Rev. %d\n", cpuname
,
1489 aprint_verbose("%s: SVM NASID %d\n", cpuname
, data
[1]);
1490 snprintb(buf
, sizeof(buf
), CPUID_AMD_SVM_FLAGS
,
1492 aprint_verbose("%s: SVM features %s\n", cpuname
, buf
);
1496 #ifdef INTEL_ONDEMAND_CLOCKMOD
1500 aprint_normal_dev(ci
->ci_dev
, "family %02x model %02x "
1501 "extfamily %02x extmodel %02x\n", CPUID2FAMILY(ci
->ci_signature
),
1502 CPUID2MODEL(ci
->ci_signature
), CPUID2EXTFAMILY(ci
->ci_signature
),
1503 CPUID2EXTMODEL(ci
->ci_signature
));
1507 print_cache_config(struct cpu_info
*ci
, int cache_tag
, const char *name
,
1510 struct x86_cache_info
*cai
= &ci
->ci_cinfo
[cache_tag
];
1511 char human_num
[HUMAN_BUFSIZE
];
1513 if (cai
->cai_totalsize
== 0)
1517 aprint_verbose_dev(ci
->ci_dev
, "");
1519 aprint_verbose("%s", sep
);
1521 aprint_verbose("%s ", name
);
1523 if (cai
->cai_string
!= NULL
) {
1524 aprint_verbose("%s ", cai
->cai_string
);
1526 (void)humanize_number(human_num
, sizeof(human_num
),
1527 cai
->cai_totalsize
, "B", HN_AUTOSCALE
, HN_NOSPACE
);
1528 aprint_verbose("%s %dB/line ", human_num
, cai
->cai_linesize
);
1530 switch (cai
->cai_associativity
) {
1532 aprint_verbose("disabled");
1535 aprint_verbose("direct-mapped");
1538 aprint_verbose("fully associative");
1541 aprint_verbose("%d-way", cai
->cai_associativity
);
1548 print_tlb_config(struct cpu_info
*ci
, int cache_tag
, const char *name
,
1551 struct x86_cache_info
*cai
= &ci
->ci_cinfo
[cache_tag
];
1552 char human_num
[HUMAN_BUFSIZE
];
1554 if (cai
->cai_totalsize
== 0)
1558 aprint_verbose_dev(ci
->ci_dev
, "");
1560 aprint_verbose("%s", sep
);
1562 aprint_verbose("%s ", name
);
1564 if (cai
->cai_string
!= NULL
) {
1565 aprint_verbose("%s", cai
->cai_string
);
1567 (void)humanize_number(human_num
, sizeof(human_num
),
1568 cai
->cai_linesize
, "B", HN_AUTOSCALE
, HN_NOSPACE
);
1569 aprint_verbose("%d %s entries ", cai
->cai_totalsize
,
1571 switch (cai
->cai_associativity
) {
1573 aprint_verbose("disabled");
1576 aprint_verbose("direct-mapped");
1579 aprint_verbose("fully associative");
1582 aprint_verbose("%d-way", cai
->cai_associativity
);
1589 static const struct x86_cache_info
*
1590 cache_info_lookup(const struct x86_cache_info
*cai
, uint8_t desc
)
1594 for (i
= 0; cai
[i
].cai_desc
!= 0; i
++) {
1595 if (cai
[i
].cai_desc
== desc
)
1602 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info
[] =
1605 static const struct x86_cache_info amd_cpuid_l3cache_assoc_info
[] =
1609 amd_cpu_cacheinfo(struct cpu_info
*ci
)
1611 const struct x86_cache_info
*cp
;
1612 struct x86_cache_info
*cai
;
1617 family
= (ci
->ci_signature
>> 8) & 15;
1618 model
= CPUID2MODEL(ci
->ci_signature
);
1621 * K5 model 0 has none of this info.
1623 if (family
== 5 && model
== 0)
1627 * Get extended values for K8 and up.
1629 if (family
== 0xf) {
1630 family
+= CPUID2EXTFAMILY(ci
->ci_signature
);
1631 model
+= CPUID2EXTMODEL(ci
->ci_signature
);
1635 * Determine the largest extended function value.
1637 x86_cpuid(0x80000000, descs
);
1641 * Determine L1 cache/TLB info.
1643 if (lfunc
< 0x80000005) {
1644 /* No L1 cache info available. */
1648 x86_cpuid(0x80000005, descs
);
1651 * K6-III and higher have large page TLBs.
1653 if ((family
== 5 && model
>= 9) || family
>= 6) {
1654 cai
= &ci
->ci_cinfo
[CAI_ITLB2
];
1655 cai
->cai_totalsize
= AMD_L1_EAX_ITLB_ENTRIES(descs
[0]);
1656 cai
->cai_associativity
= AMD_L1_EAX_ITLB_ASSOC(descs
[0]);
1657 cai
->cai_linesize
= (4 * 1024 * 1024);
1659 cai
= &ci
->ci_cinfo
[CAI_DTLB2
];
1660 cai
->cai_totalsize
= AMD_L1_EAX_DTLB_ENTRIES(descs
[0]);
1661 cai
->cai_associativity
= AMD_L1_EAX_DTLB_ASSOC(descs
[0]);
1662 cai
->cai_linesize
= (4 * 1024 * 1024);
1665 cai
= &ci
->ci_cinfo
[CAI_ITLB
];
1666 cai
->cai_totalsize
= AMD_L1_EBX_ITLB_ENTRIES(descs
[1]);
1667 cai
->cai_associativity
= AMD_L1_EBX_ITLB_ASSOC(descs
[1]);
1668 cai
->cai_linesize
= (4 * 1024);
1670 cai
= &ci
->ci_cinfo
[CAI_DTLB
];
1671 cai
->cai_totalsize
= AMD_L1_EBX_DTLB_ENTRIES(descs
[1]);
1672 cai
->cai_associativity
= AMD_L1_EBX_DTLB_ASSOC(descs
[1]);
1673 cai
->cai_linesize
= (4 * 1024);
1675 cai
= &ci
->ci_cinfo
[CAI_DCACHE
];
1676 cai
->cai_totalsize
= AMD_L1_ECX_DC_SIZE(descs
[2]);
1677 cai
->cai_associativity
= AMD_L1_ECX_DC_ASSOC(descs
[2]);
1678 cai
->cai_linesize
= AMD_L1_EDX_IC_LS(descs
[2]);
1680 cai
= &ci
->ci_cinfo
[CAI_ICACHE
];
1681 cai
->cai_totalsize
= AMD_L1_EDX_IC_SIZE(descs
[3]);
1682 cai
->cai_associativity
= AMD_L1_EDX_IC_ASSOC(descs
[3]);
1683 cai
->cai_linesize
= AMD_L1_EDX_IC_LS(descs
[3]);
1686 * Determine L2 cache/TLB info.
1688 if (lfunc
< 0x80000006) {
1689 /* No L2 cache info available. */
1693 x86_cpuid(0x80000006, descs
);
1695 cai
= &ci
->ci_cinfo
[CAI_L2CACHE
];
1696 cai
->cai_totalsize
= AMD_L2_ECX_C_SIZE(descs
[2]);
1697 cai
->cai_associativity
= AMD_L2_ECX_C_ASSOC(descs
[2]);
1698 cai
->cai_linesize
= AMD_L2_ECX_C_LS(descs
[2]);
1700 cp
= cache_info_lookup(amd_cpuid_l2cache_assoc_info
,
1701 cai
->cai_associativity
);
1703 cai
->cai_associativity
= cp
->cai_associativity
;
1705 cai
->cai_associativity
= 0; /* XXX Unknown/reserved */
1708 * Determine L3 cache info on AMD Family 10h processors
1710 if (family
== 0x10) {
1711 cai
= &ci
->ci_cinfo
[CAI_L3CACHE
];
1712 cai
->cai_totalsize
= AMD_L3_EDX_C_SIZE(descs
[3]);
1713 cai
->cai_associativity
= AMD_L3_EDX_C_ASSOC(descs
[3]);
1714 cai
->cai_linesize
= AMD_L3_EDX_C_LS(descs
[3]);
1716 cp
= cache_info_lookup(amd_cpuid_l3cache_assoc_info
,
1717 cai
->cai_associativity
);
1719 cai
->cai_associativity
= cp
->cai_associativity
;
1721 cai
->cai_associativity
= 0; /* XXX Unkn/Rsvd */
1726 via_cpu_cacheinfo(struct cpu_info
*ci
)
1728 struct x86_cache_info
*cai
;
1729 int family
, model
, stepping
;
1733 family
= (ci
->ci_signature
>> 8) & 15;
1734 model
= CPUID2MODEL(ci
->ci_signature
);
1735 stepping
= CPUID2STEPPING(ci
->ci_signature
);
1738 * Determine the largest extended function value.
1740 x86_cpuid(0x80000000, descs
);
1744 * Determine L1 cache/TLB info.
1746 if (lfunc
< 0x80000005) {
1747 /* No L1 cache info available. */
1751 x86_cpuid(0x80000005, descs
);
1753 cai
= &ci
->ci_cinfo
[CAI_ITLB
];
1754 cai
->cai_totalsize
= VIA_L1_EBX_ITLB_ENTRIES(descs
[1]);
1755 cai
->cai_associativity
= VIA_L1_EBX_ITLB_ASSOC(descs
[1]);
1756 cai
->cai_linesize
= (4 * 1024);
1758 cai
= &ci
->ci_cinfo
[CAI_DTLB
];
1759 cai
->cai_totalsize
= VIA_L1_EBX_DTLB_ENTRIES(descs
[1]);
1760 cai
->cai_associativity
= VIA_L1_EBX_DTLB_ASSOC(descs
[1]);
1761 cai
->cai_linesize
= (4 * 1024);
1763 cai
= &ci
->ci_cinfo
[CAI_DCACHE
];
1764 cai
->cai_totalsize
= VIA_L1_ECX_DC_SIZE(descs
[2]);
1765 cai
->cai_associativity
= VIA_L1_ECX_DC_ASSOC(descs
[2]);
1766 cai
->cai_linesize
= VIA_L1_EDX_IC_LS(descs
[2]);
1767 if (model
== 9 && stepping
== 8) {
1768 /* Erratum: stepping 8 reports 4 when it should be 2 */
1769 cai
->cai_associativity
= 2;
1772 cai
= &ci
->ci_cinfo
[CAI_ICACHE
];
1773 cai
->cai_totalsize
= VIA_L1_EDX_IC_SIZE(descs
[3]);
1774 cai
->cai_associativity
= VIA_L1_EDX_IC_ASSOC(descs
[3]);
1775 cai
->cai_linesize
= VIA_L1_EDX_IC_LS(descs
[3]);
1776 if (model
== 9 && stepping
== 8) {
1777 /* Erratum: stepping 8 reports 4 when it should be 2 */
1778 cai
->cai_associativity
= 2;
1782 * Determine L2 cache/TLB info.
1784 if (lfunc
< 0x80000006) {
1785 /* No L2 cache info available. */
1789 x86_cpuid(0x80000006, descs
);
1791 cai
= &ci
->ci_cinfo
[CAI_L2CACHE
];
1793 cai
->cai_totalsize
= VIA_L2N_ECX_C_SIZE(descs
[2]);
1794 cai
->cai_associativity
= VIA_L2N_ECX_C_ASSOC(descs
[2]);
1795 cai
->cai_linesize
= VIA_L2N_ECX_C_LS(descs
[2]);
1797 cai
->cai_totalsize
= VIA_L2_ECX_C_SIZE(descs
[2]);
1798 cai
->cai_associativity
= VIA_L2_ECX_C_ASSOC(descs
[2]);
1799 cai
->cai_linesize
= VIA_L2_ECX_C_LS(descs
[2]);
1804 x86_print_cacheinfo(struct cpu_info
*ci
)
1808 if (ci
->ci_cinfo
[CAI_ICACHE
].cai_totalsize
!= 0 ||
1809 ci
->ci_cinfo
[CAI_DCACHE
].cai_totalsize
!= 0) {
1810 sep
= print_cache_config(ci
, CAI_ICACHE
, "I-cache", NULL
);
1811 sep
= print_cache_config(ci
, CAI_DCACHE
, "D-cache", sep
);
1813 aprint_verbose("\n");
1815 if (ci
->ci_cinfo
[CAI_L2CACHE
].cai_totalsize
!= 0) {
1816 sep
= print_cache_config(ci
, CAI_L2CACHE
, "L2 cache", NULL
);
1818 aprint_verbose("\n");
1820 if (ci
->ci_cinfo
[CAI_ITLB
].cai_totalsize
!= 0) {
1821 sep
= print_tlb_config(ci
, CAI_ITLB
, "ITLB", NULL
);
1822 sep
= print_tlb_config(ci
, CAI_ITLB2
, NULL
, sep
);
1824 aprint_verbose("\n");
1826 if (ci
->ci_cinfo
[CAI_DTLB
].cai_totalsize
!= 0) {
1827 sep
= print_tlb_config(ci
, CAI_DTLB
, "DTLB", NULL
);
1828 sep
= print_tlb_config(ci
, CAI_DTLB2
, NULL
, sep
);
1830 aprint_verbose("\n");
1832 if (ci
->ci_cinfo
[CAI_L3CACHE
].cai_totalsize
!= 0) {
1833 sep
= print_cache_config(ci
, CAI_L3CACHE
, "L3 cache", NULL
);
1835 aprint_verbose("\n");
1840 powernow_probe(struct cpu_info
*ci
)
1845 x86_cpuid(0x80000000, regs
);
1847 /* We need CPUID(0x80000007) */
1848 if (regs
[0] < 0x80000007)
1850 x86_cpuid(0x80000007, regs
);
1852 snprintb(buf
, sizeof(buf
), CPUID_APM_FLAGS
, regs
[3]);
1853 aprint_normal_dev(ci
->ci_dev
, "AMD Power Management features: %s\n",