xref: /netbsd-src/sys/arch/x86/x86/identcpu.c (revision e77448e07be3174235c13f58032a0d6d0ab7638d)
1 /*	$NetBSD: identcpu.c,v 1.7 2008/05/13 11:22:15 ad 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 __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.7 2008/05/13 11:22:15 ad Exp $");
60 
61 #include "opt_enhanced_speedstep.h"
62 #include "opt_intel_odcm.h"
63 #include "opt_intel_coretemp.h"
64 #include "opt_powernow_k8.h"
65 #include "opt_xen.h"
66 #ifdef i386	/* XXX */
67 #include "opt_powernow_k7.h"
68 #endif
69 
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/malloc.h>
73 #include <sys/bitops.h>
74 
75 #include <uvm/uvm_extern.h>
76 
77 #include <machine/specialreg.h>
78 #include <machine/pio.h>
79 #include <machine/cpu.h>
80 
81 #include <x86/cputypes.h>
82 #include <x86/cacheinfo.h>
83 #include <x86/cpuvar.h>
84 #include <x86/cpu_msr.h>
85 #include <x86/powernow.h>
86 
87 static const struct x86_cache_info intel_cpuid_cache_info[] = {
88 	{ CAI_ITLB, 	0x01,	 4, 32,        4 * 1024 },
89 	{ CAI_ITLB,     0xb0,    4,128,        4 * 1024 },
90 	{ CAI_ITLB2, 	0x02, 0xff,  2, 4 * 1024 * 1024 },
91 	{ CAI_DTLB, 	0x03,    4, 64,        4 * 1024 },
92 	{ CAI_DTLB,     0xb3,    4,128,        4 * 1024 },
93 	{ CAI_DTLB,     0xb4,    4,256,        4 * 1024 },
94 	{ CAI_DTLB2,    0x04,    4,  8, 4 * 1024 * 1024 },
95 	{ CAI_DTLB2,    0x05,    4, 32, 4 * 1024 * 1024 },
96 	{ CAI_ITLB,     0x50, 0xff, 64,        4 * 1024 },
97 	{ CAI_ITLB,     0x51, 0xff, 64,        4 * 1024 },
98 	{ CAI_ITLB,     0x52, 0xff, 64,        4 * 1024 },
99 	{ CAI_DTLB,     0x5b, 0xff, 64,        4 * 1024 },
100 	{ CAI_DTLB,     0x5c, 0xff,128,        4 * 1024 },
101 	{ CAI_DTLB,     0x5d, 0xff,256,        4 * 1024 },
102 	{ CAI_ICACHE,   0x06,  4,        8 * 1024, 32 },
103 	{ CAI_ICACHE,   0x08,  4,       16 * 1024, 32 },
104 	{ CAI_ICACHE,   0x30,  8,       32 * 1024, 64 },
105 	{ CAI_DCACHE,   0x0a,  2,        8 * 1024, 32 },
106 	{ CAI_DCACHE,   0x0c,  4,       16 * 1024, 32 },
107 	{ CAI_L2CACHE,  0x39,  4,      128 * 1024, 64 },
108 	{ CAI_L2CACHE,  0x3a,  6,      192 * 1024, 64 },
109 	{ CAI_L2CACHE,  0x3b,  2,      128 * 1024, 64 },
110 	{ CAI_L2CACHE,  0x3c,  4,      256 * 1024, 64 },
111 	{ CAI_L2CACHE,  0x3d,  6,      384 * 1024, 64 },
112 	{ CAI_L2CACHE,  0x3e,  4,      512 * 1024, 64 },
113 	{ CAI_L2CACHE,  0x40,  0,               0,  0 },
114 	{ CAI_L2CACHE,  0x41,  4,      128 * 1024, 32 },
115 	{ CAI_L2CACHE,  0x42,  4,      256 * 1024, 32 },
116 	{ CAI_L2CACHE,  0x43,  4,      512 * 1024, 32 },
117 	{ CAI_L2CACHE,  0x44,  4, 1 * 1024 * 1024, 32 },
118 	{ CAI_L2CACHE,  0x45,  4, 2 * 1024 * 1024, 32 },
119 	{ CAI_L2CACHE,  0x49, 16, 4 * 1024 * 1024, 64 },
120 	{ CAI_L2CACHE,  0x4e, 24, 6 * 1024 * 1024, 64 },
121 	{ CAI_DCACHE,   0x60,  8,       16 * 1024, 64 },
122 	{ CAI_DCACHE,   0x66,  4,        8 * 1024, 64 },
123 	{ CAI_DCACHE,   0x67,  4,       16 * 1024, 64 },
124 	{ CAI_DCACHE,   0x2c,  8,       32 * 1024, 64 },
125 	{ CAI_DCACHE,   0x68,  4,  	32 * 1024, 64 },
126 	{ CAI_ICACHE,   0x70,  8,       12 * 1024, 64 },
127 	{ CAI_ICACHE,   0x71,  8,       16 * 1024, 64 },
128 	{ CAI_ICACHE,   0x72,  8,       32 * 1024, 64 },
129 	{ CAI_ICACHE,   0x73,  8,       64 * 1024, 64 },
130 	{ CAI_L2CACHE,  0x78,  4, 1 * 1024 * 1024, 64 },
131 	{ CAI_L2CACHE,  0x79,  8,      128 * 1024, 64 },
132 	{ CAI_L2CACHE,  0x7a,  8,      256 * 1024, 64 },
133 	{ CAI_L2CACHE,  0x7b,  8,      512 * 1024, 64 },
134 	{ CAI_L2CACHE,  0x7c,  8, 1 * 1024 * 1024, 64 },
135 	{ CAI_L2CACHE,  0x7d,  8, 2 * 1024 * 1024, 64 },
136 	{ CAI_L2CACHE,  0x7f,  2,      512 * 1024, 64 },
137 	{ CAI_L2CACHE,  0x82,  8,      256 * 1024, 32 },
138 	{ CAI_L2CACHE,  0x83,  8,      512 * 1024, 32 },
139 	{ CAI_L2CACHE,  0x84,  8, 1 * 1024 * 1024, 32 },
140 	{ CAI_L2CACHE,  0x85,  8, 2 * 1024 * 1024, 32 },
141 	{ CAI_L2CACHE,  0x86,  4,      512 * 1024, 64 },
142 	{ CAI_L2CACHE,  0x87,  8, 1 * 1024 * 1024, 64 },
143 	{ 0,               0,  0,	        0,  0 },
144 };
145 
146 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = {
147 	{ 0, 0x01,    1, 0, 0 },
148 	{ 0, 0x02,    2, 0, 0 },
149 	{ 0, 0x04,    4, 0, 0 },
150 	{ 0, 0x06,    8, 0, 0 },
151 	{ 0, 0x08,   16, 0, 0 },
152 	{ 0, 0x0a,   32, 0, 0 },
153 	{ 0, 0x0b,   48, 0, 0 },
154 	{ 0, 0x0c,   64, 0, 0 },
155 	{ 0, 0x0d,   96, 0, 0 },
156 	{ 0, 0x0e,  128, 0, 0 },
157 	{ 0, 0x0f, 0xff, 0, 0 },
158 	{ 0, 0x00,    0, 0, 0 },
159 };
160 
161 static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] = {
162 	{ 0, 0x00,    0, 0, 0 },
163 	{ 0, 0x01,    1, 0, 0 },
164 	{ 0, 0x02,    2, 0, 0 },
165 	{ 0, 0x04,    4, 0, 0 },
166 	{ 0, 0x06,    8, 0, 0 },
167 	{ 0, 0x08,   16, 0, 0 },
168 	{ 0, 0x0a,   32, 0, 0 },
169 	{ 0, 0x0b,   48, 0, 0 },
170 	{ 0, 0x0c,   64, 0, 0 },
171 	{ 0, 0x0d,   96, 0, 0 },
172 	{ 0, 0x0e,  128, 0, 0 },
173 	{ 0, 0x0f, 0xff, 0, 0 },
174 	{ 0, 0x00,    0, 0, 0 },
175 };
176 
177 int cpu_vendor;
178 char cpu_brand_string[49];
179 
180 /*
181  * Info for CTL_HW
182  */
183 char	cpu_model[120];
184 
185 /*
186  * Note: these are just the ones that may not have a cpuid instruction.
187  * We deal with the rest in a different way.
188  */
189 const int i386_nocpuid_cpus[] = {
190 	CPUVENDOR_INTEL, CPUCLASS_386,	/* CPU_386SX */
191 	CPUVENDOR_INTEL, CPUCLASS_386,	/* CPU_386   */
192 	CPUVENDOR_INTEL, CPUCLASS_486,	/* CPU_486SX */
193 	CPUVENDOR_INTEL, CPUCLASS_486, 	/* CPU_486   */
194 	CPUVENDOR_CYRIX, CPUCLASS_486,	/* CPU_486DLC */
195 	CPUVENDOR_CYRIX, CPUCLASS_486,	/* CPU_6x86 */
196 	CPUVENDOR_NEXGEN, CPUCLASS_386,	/* CPU_NX586 */
197 };
198 
199 static const char cpu_vendor_names[][10] = {
200 	"Unknown", "Intel", "NS/Cyrix", "NexGen", "AMD", "IDT/VIA", "Transmeta"
201 };
202 
203 static const struct x86_cache_info *
204 cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc)
205 {
206 	int i;
207 
208 	for (i = 0; cai[i].cai_desc != 0; i++) {
209 		if (cai[i].cai_desc == desc)
210 			return (&cai[i]);
211 	}
212 
213 	return (NULL);
214 }
215 
216 static void
217 cpu_probe_p6(struct cpu_info *ci)
218 {
219 	u_int lp_max = 1;	/* logical processors per package */
220 	u_int smt_max;		/* smt per core */
221 	u_int core_max = 1;	/* core per package */
222 	int smt_bits, core_bits;
223 	uint32_t descs[4];
224 
225 	if (cpu_vendor != CPUVENDOR_INTEL ||
226 	    CPUID2FAMILY(ci->ci_signature) < 6)
227 		return;
228 
229 	/* Determine extended feature flags. */
230 	x86_cpuid(0x80000000, descs);
231 	if (descs[0] >= 0x80000001) {
232 		x86_cpuid(0x80000001, descs);
233 		ci->ci_feature3_flags |= descs[3];
234 	}
235 
236 	/* Determine topology. 253668.pdf 7.10.2. */
237 	ci->ci_packageid = ci->ci_initapicid;
238 	ci->ci_coreid = 0;
239 	ci->ci_smtid = 0;
240 	if ((ci->ci_feature_flags & CPUID_HTT) != 0) {
241 		x86_cpuid(1, descs);
242 		lp_max = (descs[1] >> 16) & 0xff;
243 	}
244 	x86_cpuid(0, descs);
245 	if (descs[0] >= 4) {
246 		x86_cpuid2(4, 0, descs);
247 		core_max = (descs[0] >> 26) + 1;
248 	}
249 	KASSERT(lp_max >= core_max);
250 	smt_max = lp_max / core_max;
251 	smt_bits = ilog2(smt_max - 1) + 1;
252 	core_bits = ilog2(core_max - 1) + 1;
253 	if (smt_bits + core_bits) {
254 		ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits);
255 	}
256 	if (core_bits) {
257 		u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1);
258 		ci->ci_coreid = __SHIFTOUT(ci->ci_initapicid, core_mask);
259 	}
260 	if (smt_bits) {
261 		u_int smt_mask = __BITS(0, smt_bits - 1);
262 		ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask);
263 	}
264 }
265 
266 static void
267 cpu_probe_amd_cache(struct cpu_info *ci)
268 {
269 	const struct x86_cache_info *cp;
270 	struct x86_cache_info *cai;
271 	int family, model;
272 	u_int descs[4];
273 	u_int lfunc;
274 
275 	family = CPUID2FAMILY(ci->ci_signature);
276 	model = CPUID2MODEL(ci->ci_signature);
277 
278 	/*
279 	 * K5 model 0 has none of this info.
280 	 */
281 	if (family == 5 && model == 0)
282 		return;
283 
284 	/*
285 	 * Get extended values for K8 and up.
286 	 */
287 	if (family == 0xf) {
288 		family += CPUID2EXTFAMILY(ci->ci_signature);
289 		model += CPUID2EXTMODEL(ci->ci_signature);
290 	}
291 
292 	/*
293 	 * Determine the largest extended function value.
294 	 */
295 	x86_cpuid(0x80000000, descs);
296 	lfunc = descs[0];
297 
298 	/*
299 	 * Determine L1 cache/TLB info.
300 	 */
301 	if (lfunc < 0x80000005) {
302 		/* No L1 cache info available. */
303 		return;
304 	}
305 
306 	x86_cpuid(0x80000005, descs);
307 
308 	/*
309 	 * K6-III and higher have large page TLBs.
310 	 */
311 	if ((family == 5 && model >= 9) || family >= 6) {
312 		cai = &ci->ci_cinfo[CAI_ITLB2];
313 		cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
314 		cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
315 		cai->cai_linesize = (4 * 1024 * 1024);
316 
317 		cai = &ci->ci_cinfo[CAI_DTLB2];
318 		cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
319 		cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
320 		cai->cai_linesize = (4 * 1024 * 1024);
321 	}
322 
323 	cai = &ci->ci_cinfo[CAI_ITLB];
324 	cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
325 	cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
326 	cai->cai_linesize = (4 * 1024);
327 
328 	cai = &ci->ci_cinfo[CAI_DTLB];
329 	cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
330 	cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
331 	cai->cai_linesize = (4 * 1024);
332 
333 	cai = &ci->ci_cinfo[CAI_DCACHE];
334 	cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
335 	cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
336 	cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]);
337 
338 	cai = &ci->ci_cinfo[CAI_ICACHE];
339 	cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
340 	cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
341 	cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
342 
343 	/*
344 	 * Determine L2 cache/TLB info.
345 	 */
346 	if (lfunc < 0x80000006) {
347 		/* No L2 cache info available. */
348 		return;
349 	}
350 
351 	x86_cpuid(0x80000006, descs);
352 
353 	cai = &ci->ci_cinfo[CAI_L2CACHE];
354 	cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
355 	cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
356 	cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
357 
358 	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
359 	    cai->cai_associativity);
360 	if (cp != NULL)
361 		cai->cai_associativity = cp->cai_associativity;
362 	else
363 		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
364 
365 	if (family < 0xf) {
366 		/* No L3 cache info available. */
367 		return;
368 	}
369 
370 	cai = &ci->ci_cinfo[CAI_L3CACHE];
371 	cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]);
372 	cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]);
373 	cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]);
374 
375 	cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info,
376 	    cai->cai_associativity);
377 	if (cp != NULL)
378 		cai->cai_associativity = cp->cai_associativity;
379 	else
380 		cai->cai_associativity = 0;	/* XXX Unknown reserved */
381 
382 	if (lfunc < 0x80000019) {
383 		/* No 1GB Page TLB */
384 		return;
385 	}
386 
387 	x86_cpuid(0x80000019, descs);
388 
389 	cai = &ci->ci_cinfo[CAI_L1_1GBDTLB];
390 	cai->cai_totalsize = AMD_L1_1GB_EAX_DTLB_ENTRIES(descs[1]);
391 	cai->cai_associativity = AMD_L1_1GB_EAX_DTLB_ASSOC(descs[1]);
392 	cai->cai_linesize = (1 * 1024);
393 
394 	cai = &ci->ci_cinfo[CAI_L1_1GBITLB];
395 	cai->cai_totalsize = AMD_L1_1GB_EAX_IUTLB_ENTRIES(descs[0]);
396 	cai->cai_associativity = AMD_L1_1GB_EAX_IUTLB_ASSOC(descs[0]);
397 	cai->cai_linesize = (1 * 1024);
398 
399 	cai = &ci->ci_cinfo[CAI_L2_1GBDTLB];
400 	cai->cai_totalsize = AMD_L2_1GB_EBX_DUTLB_ENTRIES(descs[1]);
401 	cai->cai_associativity = AMD_L2_1GB_EBX_DUTLB_ASSOC(descs[1]);
402 	cai->cai_linesize = (1 * 1024);
403 
404 	cai = &ci->ci_cinfo[CAI_L2_1GBITLB];
405 	cai->cai_totalsize = AMD_L2_1GB_EBX_IUTLB_ENTRIES(descs[0]);
406 	cai->cai_associativity = AMD_L2_1GB_EBX_IUTLB_ASSOC(descs[0]);
407 	cai->cai_linesize = (1 * 1024);
408 }
409 
410 static void
411 cpu_probe_k5(struct cpu_info *ci)
412 {
413 	int flag;
414 
415 	if (cpu_vendor != CPUVENDOR_AMD ||
416 	    CPUID2FAMILY(ci->ci_signature) != 5)
417 		return;
418 
419 	if (CPUID2MODEL(ci->ci_signature) == 0) {
420 		/*
421 		 * According to the AMD Processor Recognition App Note,
422 		 * the AMD-K5 Model 0 uses the wrong bit to indicate
423 		 * support for global PTEs, instead using bit 9 (APIC)
424 		 * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
425 		 */
426 		flag = ci->ci_feature_flags;
427 		if ((flag & CPUID_APIC) != 0)
428 			flag = (flag & ~CPUID_APIC) | CPUID_PGE;
429 		ci->ci_feature_flags = flag;
430 	}
431 
432 	cpu_probe_amd_cache(ci);
433 }
434 
435 static void
436 cpu_probe_k678(struct cpu_info *ci)
437 {
438 	uint32_t descs[4];
439 
440 	if (cpu_vendor != CPUVENDOR_AMD ||
441 	    CPUID2FAMILY(ci->ci_signature) < 6)
442 		return;
443 
444 	/* Determine the extended feature flags. */
445 	x86_cpuid(0x80000000, descs);
446 	if (descs[0] >= 0x80000001) {
447 		x86_cpuid(0x80000001, descs);
448 		ci->ci_feature_flags |= descs[3];
449 	}
450 
451 	cpu_probe_amd_cache(ci);
452 }
453 
454 static inline uint8_t
455 cyrix_read_reg(uint8_t reg)
456 {
457 
458 	outb(0x22, reg);
459 	return inb(0x23);
460 }
461 
462 static inline void
463 cyrix_write_reg(uint8_t reg, uint8_t data)
464 {
465 
466 	outb(0x22, reg);
467 	outb(0x23, data);
468 }
469 
470 static void
471 cpu_probe_cyrix_cmn(struct cpu_info *ci)
472 {
473 	/*
474 	 * i8254 latch check routine:
475 	 *     National Geode (formerly Cyrix MediaGX) has a serious bug in
476 	 *     its built-in i8254-compatible clock module (cs5510 cs5520).
477 	 *     Set the variable 'clock_broken_latch' to indicate it.
478 	 *
479 	 * This bug is not present in the cs5530, and the flag
480 	 * is disabled again in sys/arch/i386/pci/pcib.c if this later
481 	 * model device is detected. Ideally, this work-around should not
482 	 * even be in here, it should be in there. XXX
483 	 */
484 	uint8_t c3;
485 #ifndef XEN
486 	extern int clock_broken_latch;
487 
488 	switch (ci->ci_signature) {
489 	case 0x440:     /* Cyrix MediaGX */
490 	case 0x540:     /* GXm */
491 		clock_broken_latch = 1;
492 		break;
493 	}
494 #endif
495 
496 	/* set up various cyrix registers */
497 	/*
498 	 * Enable suspend on halt (powersave mode).
499 	 * When powersave mode is enabled, the TSC stops counting
500 	 * while the CPU is halted in idle() waiting for an interrupt.
501 	 * This means we can't use the TSC for interval time in
502 	 * microtime(9), and thus it is disabled here.
503 	 *
504 	 * It still makes a perfectly good cycle counter
505 	 * for program profiling, so long as you remember you're
506 	 * counting cycles, and not time. Further, if you don't
507 	 * mind not using powersave mode, the TSC works just fine,
508 	 * so this should really be optional. XXX
509 	 */
510 	cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08);
511 
512 	/*
513 	 * Do not disable the TSC on the Geode GX, it's reported to
514 	 * work fine.
515 	 */
516 	if (ci->ci_signature != 0x552)
517 		ci->ci_feature_flags &= ~CPUID_TSC;
518 
519 	/* enable access to ccr4/ccr5 */
520 	c3 = cyrix_read_reg(0xC3);
521 	cyrix_write_reg(0xC3, c3 | 0x10);
522 	/* cyrix's workaround  for the "coma bug" */
523 	cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8);
524 	cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f);
525 	cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff);
526 	cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87);
527 	/* disable access to ccr4/ccr5 */
528 	cyrix_write_reg(0xC3, c3);
529 
530 	/*
531 	 * XXX disable page zero in the idle loop, it seems to
532 	 * cause panics on these CPUs.
533 	 */
534 	vm_page_zero_enable = FALSE;
535 }
536 
537 static void
538 cpu_probe_cyrix(struct cpu_info *ci)
539 {
540 
541 	if (cpu_vendor != CPUVENDOR_CYRIX ||
542 	    CPUID2FAMILY(ci->ci_signature) < 4 ||
543 	    CPUID2FAMILY(ci->ci_signature) > 6)
544 		return;
545 
546 	cpu_probe_cyrix_cmn(ci);
547 }
548 
549 static void
550 cpu_probe_winchip(struct cpu_info *ci)
551 {
552 
553 	if (cpu_vendor != CPUVENDOR_IDT ||
554 	    CPUID2FAMILY(ci->ci_signature) != 5)
555 	    	return;
556 
557 	if (CPUID2MODEL(ci->ci_signature) == 4) {
558 		/* WinChip C6 */
559 		ci->ci_feature_flags &= ~CPUID_TSC;
560 	}
561 }
562 
563 static void
564 cpu_probe_c3(struct cpu_info *ci)
565 {
566 	u_int family, model, stepping, descs[4], lfunc, msr;
567 	struct x86_cache_info *cai;
568 
569 	if (cpu_vendor != CPUVENDOR_IDT ||
570 	    CPUID2FAMILY(ci->ci_signature) != 5)
571 	    	return;
572 
573 	family = CPUID2FAMILY(ci->ci_signature);
574 	model = CPUID2MODEL(ci->ci_signature);
575 	stepping = CPUID2STEPPING(ci->ci_signature);
576 
577 	/* Determine the largest extended function value. */
578 	x86_cpuid(0x80000000, descs);
579 	lfunc = descs[0];
580 
581 	/* Determine the extended feature flags. */
582 	if (lfunc >= 0x80000001) {
583 		x86_cpuid(0x80000001, descs);
584 		ci->ci_feature_flags |= descs[3];
585 	}
586 
587 	if (model >= 0x9) {
588 		/* Nehemiah or Esther */
589 		x86_cpuid(0xc0000000, descs);
590 		lfunc = descs[0];
591 		if (lfunc >= 0xc0000001) {	/* has ACE, RNG */
592 			x86_cpuid(0xc0000001, descs);
593 			lfunc = descs[3];
594 			if (model > 0x9 || stepping >= 8) {	/* ACE */
595 				if (lfunc & CPUID_VIA_HAS_ACE) {
596 					ci->ci_padlock_flags = lfunc;
597 					if ((lfunc & CPUID_VIA_DO_ACE) == 0) {
598 						msr = rdmsr(MSR_VIA_ACE);
599 						wrmsr(MSR_VIA_ACE, msr |
600 						    MSR_VIA_ACE_ENABLE);
601 						ci->ci_padlock_flags |=
602 						    CPUID_VIA_DO_ACE;
603 					}
604 				}
605 			}
606 		}
607 	}
608 
609 	/*
610 	 * Determine L1 cache/TLB info.
611 	 */
612 	if (lfunc < 0x80000005) {
613 		/* No L1 cache info available. */
614 		return;
615 	}
616 
617 	x86_cpuid(0x80000005, descs);
618 
619 	cai = &ci->ci_cinfo[CAI_ITLB];
620 	cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]);
621 	cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]);
622 	cai->cai_linesize = (4 * 1024);
623 
624 	cai = &ci->ci_cinfo[CAI_DTLB];
625 	cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]);
626 	cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]);
627 	cai->cai_linesize = (4 * 1024);
628 
629 	cai = &ci->ci_cinfo[CAI_DCACHE];
630 	cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]);
631 	cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]);
632 	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]);
633 	if (model == 9 && stepping == 8) {
634 		/* Erratum: stepping 8 reports 4 when it should be 2 */
635 		cai->cai_associativity = 2;
636 	}
637 
638 	cai = &ci->ci_cinfo[CAI_ICACHE];
639 	cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]);
640 	cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]);
641 	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]);
642 	if (model == 9 && stepping == 8) {
643 		/* Erratum: stepping 8 reports 4 when it should be 2 */
644 		cai->cai_associativity = 2;
645 	}
646 
647 	/*
648 	 * Determine L2 cache/TLB info.
649 	 */
650 	if (lfunc < 0x80000006) {
651 		/* No L2 cache info available. */
652 		return;
653 	}
654 
655 	x86_cpuid(0x80000006, descs);
656 
657 	cai = &ci->ci_cinfo[CAI_L2CACHE];
658 	if (model >= 9) {
659 		cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]);
660 		cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]);
661 		cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]);
662 	} else {
663 		cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]);
664 		cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]);
665 		cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]);
666 	}
667 }
668 
669 static void
670 cpu_probe_geode(struct cpu_info *ci)
671 {
672 
673 	if (memcmp("Geode by NSC", ci->ci_vendor, 12) != 0 ||
674 	    CPUID2FAMILY(ci->ci_signature) != 5)
675 	    	return;
676 
677 	cpu_probe_cyrix_cmn(ci);
678 	cpu_probe_amd_cache(ci);
679 }
680 
681 void
682 cpu_probe(struct cpu_info *ci)
683 {
684 	const struct x86_cache_info *cai;
685 	u_int descs[4];
686 	int iterations, i, j;
687 	uint8_t desc;
688 	uint32_t miscbytes;
689 	uint32_t brand[12];
690 
691 	cpu_vendor = i386_nocpuid_cpus[cpu << 1];
692 	cpu_class = i386_nocpuid_cpus[(cpu << 1) + 1];
693 
694 	if (cpuid_level < 0)
695 		return;
696 
697 	x86_cpuid(0, descs);
698 	cpuid_level = descs[0];
699 	ci->ci_vendor[0] = descs[1];
700 	ci->ci_vendor[2] = descs[2];
701 	ci->ci_vendor[1] = descs[3];
702 	ci->ci_vendor[3] = 0;
703 
704 	if (memcmp(ci->ci_vendor, "GenuineIntel", 12) == 0)
705 		cpu_vendor = CPUVENDOR_INTEL;
706 	else if (memcmp(ci->ci_vendor,  "AuthenticAMD", 12) == 0)
707 		cpu_vendor = CPUVENDOR_AMD;
708 	else if (memcmp(ci->ci_vendor,  "CyrixInstead", 12) == 0)
709 		cpu_vendor = CPUVENDOR_CYRIX;
710 	else if (memcmp(ci->ci_vendor,  "Geode by NSC", 12) == 0)
711 		cpu_vendor = CPUVENDOR_CYRIX;
712 	else if (memcmp(ci->ci_vendor, "CentaurHauls", 12) == 0)
713 		cpu_vendor = CPUVENDOR_IDT;
714 	else if (memcmp(ci->ci_vendor, "GenuineTMx86", 12) == 0)
715 		cpu_vendor = CPUVENDOR_TRANSMETA;
716 	else
717 		cpu_vendor = CPUVENDOR_UNKNOWN;
718 
719 	x86_cpuid(0x80000000, brand);
720 	if (brand[0] >= 0x80000004) {
721 		x86_cpuid(0x80000002, brand);
722 		x86_cpuid(0x80000003, brand + 4);
723 		x86_cpuid(0x80000004, brand + 8);
724 		for (i = 0; i < 48; i++) {
725 			if (((char *) brand)[i] != ' ')
726 				break;
727 		}
728 		memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i);
729 	}
730 
731 	if (cpuid_level >= 1) {
732 		x86_cpuid(1, descs);
733 		ci->ci_signature = descs[0];
734 		miscbytes = descs[1];
735 		ci->ci_feature2_flags = descs[2];
736 		ci->ci_feature_flags = descs[3];
737 
738 		/* Determine family + class. */
739 		cpu_class = CPUID2FAMILY(ci->ci_signature) + (CPUCLASS_386 - 3);
740 		if (cpu_class > CPUCLASS_686)
741 			cpu_class = CPUCLASS_686;
742 
743 		/* CLFLUSH line size is next 8 bits */
744 		if (ci->ci_feature_flags & CPUID_CFLUSH)
745 			ci->ci_cflush_lsize = ((miscbytes >> 8) & 0xff) << 3;
746 		ci->ci_initapicid = (miscbytes >> 24) & 0xff;
747 	}
748 
749 	if (cpuid_level >= 2) {
750 		/* Parse the cache info from `cpuid', if we have it. */
751 		x86_cpuid(2, descs);
752 		iterations = descs[0] & 0xff;
753 		while (iterations-- > 0) {
754 			for (i = 0; i < 4; i++) {
755 				if (descs[i] & 0x80000000)
756 					continue;
757 				for (j = 0; j < 4; j++) {
758 					if (i == 0 && j == 0)
759 						continue;
760 					desc = (descs[i] >> (j * 8)) & 0xff;
761 					if (desc == 0)
762 						continue;
763 					cai = cache_info_lookup(
764 					    intel_cpuid_cache_info, desc);
765 					if (cai != NULL) {
766 						ci->ci_cinfo[cai->cai_index] =
767 						    *cai;
768 					}
769 				}
770 			}
771 		}
772 	}
773 
774 	cpu_probe_p6(ci);
775 	cpu_probe_k5(ci);
776 	cpu_probe_k678(ci);
777 	cpu_probe_cyrix(ci);
778 	cpu_probe_winchip(ci);
779 	cpu_probe_c3(ci);
780 	cpu_probe_geode(ci);
781 
782 	if (cpu_vendor != CPUVENDOR_AMD && (ci->ci_feature_flags & CPUID_TM) &&
783 	    (rdmsr(MSR_MISC_ENABLE) & (1 << 3)) == 0) {
784 		/* Enable thermal monitor 1. */
785 		wrmsr(MSR_MISC_ENABLE, rdmsr(MSR_MISC_ENABLE) | (1<<3));
786 	}
787 
788 	if ((cpu_feature | cpu_feature2) == 0) {
789 		/* If first. */
790 		cpu_feature = ci->ci_feature_flags;
791 		cpu_feature2 = ci->ci_feature2_flags;
792 	} else {
793 		/* If not first. */
794 		cpu_feature &= ci->ci_feature_flags;
795 		cpu_feature2 &= ci->ci_feature2_flags;
796 	}
797 }
798 
799 void
800 cpu_identify(struct cpu_info *ci)
801 {
802 
803 	snprintf(cpu_model, sizeof(cpu_model), "%s %d86-class",
804 	    cpu_vendor_names[cpu_vendor], cpu_class + 3);
805 	aprint_normal(": %s", cpu_model);
806 	if (ci->ci_data.cpu_cc_freq != 0)
807 		aprint_normal(", %dMHz", (int)(ci->ci_data.cpu_cc_freq / 1000000));
808 	if (ci->ci_signature != 0)
809 		aprint_normal(", id 0x%x", ci->ci_signature);
810 	aprint_normal("\n");
811 
812 	if (cpu_brand_string[0] == '\0') {
813 		strlcpy(cpu_brand_string, cpu_model, sizeof(cpu_brand_string));
814 	}
815 	if (cpu_class == CPUCLASS_386) {
816 		panic("NetBSD requires an 80486DX or later processor");
817 	}
818 	if (cpu == CPU_486DLC) {
819 		aprint_error("WARNING: BUGGY CYRIX CACHE\n");
820 	}
821 
822 #ifdef i386 /* XXX for now */
823 	if (cpu_vendor == CPUVENDOR_TRANSMETA) {
824 		u_int descs[4];
825 		x86_cpuid(0x80860000, descs);
826 		if (descs[0] >= 0x80860007)
827 			tmx86_init_longrun();
828 	}
829 
830 	/* If we have FXSAVE/FXRESTOR, use them. */
831 	if (cpu_feature & CPUID_FXSR) {
832 		i386_use_fxsave = 1;
833 		/*
834 		 * If we have SSE/SSE2, enable XMM exceptions, and
835 		 * notify userland.
836 		 */
837 		if (cpu_feature & CPUID_SSE)
838 			i386_has_sse = 1;
839 		if (cpu_feature & CPUID_SSE2)
840 			i386_has_sse2 = 1;
841 	} else
842 		i386_use_fxsave = 0;
843 #endif	/* i386 */
844 
845 #ifdef ENHANCED_SPEEDSTEP
846 	if (cpu_feature2 & CPUID2_EST) {
847 		if (rdmsr(MSR_MISC_ENABLE) & (1 << 16))
848 			est_init(cpu_vendor);
849 	}
850 #endif /* ENHANCED_SPEEDSTEP */
851 
852 #ifdef INTEL_CORETEMP
853 	if (cpu_vendor == CPUVENDOR_INTEL && cpuid_level >= 0x06)
854 		coretemp_register(ci);
855 #endif
856 
857 #if defined(POWERNOW_K7) || defined(POWERNOW_K8)
858 	if (cpu_vendor == CPUVENDOR_AMD && powernow_probe(ci)) {
859 		switch (CPUID2FAMILY(ci->ci_signature)) {
860 #ifdef POWERNOW_K7
861 		case 6:
862 			k7_powernow_init();
863 			break;
864 #endif
865 #ifdef POWERNOW_K8
866 		case 15:
867 			k8_powernow_init();
868 			break;
869 #endif
870 		default:
871 			break;
872 		}
873 	}
874 #endif /* POWERNOW_K7 || POWERNOW_K8 */
875 
876 #ifdef INTEL_ONDEMAND_CLOCKMOD
877 	if (cpuid_level >= 1) {
878 		clockmod_init();
879 	}
880 #endif
881 }
882