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