xref: /netbsd-src/sys/arch/x86/x86/identcpu.c (revision b757af438b42b93f8c6571f026d8b8ef3eaf5fc9)
1 /*	$NetBSD: identcpu.c,v 1.30 2012/02/23 14:45:55 chs 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 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.30 2012/02/23 14:45:55 chs Exp $");
34 
35 #include "opt_xen.h"
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 
41 #include <uvm/uvm_extern.h>
42 
43 #include <machine/specialreg.h>
44 #include <machine/pio.h>
45 #include <machine/cpu.h>
46 
47 #include <x86/cputypes.h>
48 #include <x86/cacheinfo.h>
49 #include <x86/cpuvar.h>
50 #include <x86/cpu_msr.h>
51 
52 static const struct x86_cache_info intel_cpuid_cache_info[] = INTEL_CACHE_INFO;
53 
54 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] =
55 	AMD_L2CACHE_INFO;
56 
57 static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] =
58 	AMD_L3CACHE_INFO;
59 
60 int cpu_vendor;
61 char cpu_brand_string[49];
62 
63 /*
64  * Info for CTL_HW
65  */
66 char	cpu_model[120];
67 
68 /*
69  * Note: these are just the ones that may not have a cpuid instruction.
70  * We deal with the rest in a different way.
71  */
72 const int i386_nocpuid_cpus[] = {
73 	CPUVENDOR_INTEL, CPUCLASS_386,	/* CPU_386SX */
74 	CPUVENDOR_INTEL, CPUCLASS_386,	/* CPU_386   */
75 	CPUVENDOR_INTEL, CPUCLASS_486,	/* CPU_486SX */
76 	CPUVENDOR_INTEL, CPUCLASS_486, 	/* CPU_486   */
77 	CPUVENDOR_CYRIX, CPUCLASS_486,	/* CPU_486DLC */
78 	CPUVENDOR_CYRIX, CPUCLASS_486,	/* CPU_6x86 */
79 	CPUVENDOR_NEXGEN, CPUCLASS_386,	/* CPU_NX586 */
80 };
81 
82 static const char cpu_vendor_names[][10] = {
83 	"Unknown", "Intel", "NS/Cyrix", "NexGen", "AMD", "IDT/VIA", "Transmeta",
84 	"Vortex86"
85 };
86 
87 static const struct x86_cache_info *
88 cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc)
89 {
90 	int i;
91 
92 	for (i = 0; cai[i].cai_desc != 0; i++) {
93 		if (cai[i].cai_desc == desc)
94 			return (&cai[i]);
95 	}
96 
97 	return (NULL);
98 }
99 
100 
101 static void
102 cpu_probe_amd_cache(struct cpu_info *ci)
103 {
104 	const struct x86_cache_info *cp;
105 	struct x86_cache_info *cai;
106 	int family, model;
107 	u_int descs[4];
108 	u_int lfunc;
109 
110 	family = CPUID2FAMILY(ci->ci_signature);
111 	model = CPUID2MODEL(ci->ci_signature);
112 
113 	/*
114 	 * K5 model 0 has none of this info.
115 	 */
116 	if (family == 5 && model == 0)
117 		return;
118 
119 	/*
120 	 * Get extended values for K8 and up.
121 	 */
122 	if (family == 0xf) {
123 		family += CPUID2EXTFAMILY(ci->ci_signature);
124 		model += CPUID2EXTMODEL(ci->ci_signature);
125 	}
126 
127 	/*
128 	 * Determine the largest extended function value.
129 	 */
130 	x86_cpuid(0x80000000, descs);
131 	lfunc = descs[0];
132 
133 	/*
134 	 * Determine L1 cache/TLB info.
135 	 */
136 	if (lfunc < 0x80000005) {
137 		/* No L1 cache info available. */
138 		return;
139 	}
140 
141 	x86_cpuid(0x80000005, descs);
142 
143 	/*
144 	 * K6-III and higher have large page TLBs.
145 	 */
146 	if ((family == 5 && model >= 9) || family >= 6) {
147 		cai = &ci->ci_cinfo[CAI_ITLB2];
148 		cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
149 		cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
150 		cai->cai_linesize = (4 * 1024 * 1024);
151 
152 		cai = &ci->ci_cinfo[CAI_DTLB2];
153 		cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
154 		cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
155 		cai->cai_linesize = (4 * 1024 * 1024);
156 	}
157 
158 	cai = &ci->ci_cinfo[CAI_ITLB];
159 	cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
160 	cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
161 	cai->cai_linesize = (4 * 1024);
162 
163 	cai = &ci->ci_cinfo[CAI_DTLB];
164 	cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
165 	cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
166 	cai->cai_linesize = (4 * 1024);
167 
168 	cai = &ci->ci_cinfo[CAI_DCACHE];
169 	cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
170 	cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
171 	cai->cai_linesize = AMD_L1_ECX_DC_LS(descs[2]);
172 
173 	cai = &ci->ci_cinfo[CAI_ICACHE];
174 	cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
175 	cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
176 	cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
177 
178 	/*
179 	 * Determine L2 cache/TLB info.
180 	 */
181 	if (lfunc < 0x80000006) {
182 		/* No L2 cache info available. */
183 		return;
184 	}
185 
186 	x86_cpuid(0x80000006, descs);
187 
188 	cai = &ci->ci_cinfo[CAI_L2CACHE];
189 	cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
190 	cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
191 	cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
192 
193 	cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
194 	    cai->cai_associativity);
195 	if (cp != NULL)
196 		cai->cai_associativity = cp->cai_associativity;
197 	else
198 		cai->cai_associativity = 0;	/* XXX Unknown/reserved */
199 
200 	if (family < 0xf) {
201 		/* No L3 cache info available. */
202 		return;
203 	}
204 
205 	cai = &ci->ci_cinfo[CAI_L3CACHE];
206 	cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]);
207 	cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]);
208 	cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]);
209 
210 	cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info,
211 	    cai->cai_associativity);
212 	if (cp != NULL)
213 		cai->cai_associativity = cp->cai_associativity;
214 	else
215 		cai->cai_associativity = 0;	/* XXX Unknown reserved */
216 
217 	if (lfunc < 0x80000019) {
218 		/* No 1GB Page TLB */
219 		return;
220 	}
221 
222 	x86_cpuid(0x80000019, descs);
223 
224 	cai = &ci->ci_cinfo[CAI_L1_1GBDTLB];
225 	cai->cai_totalsize = AMD_L1_1GB_EAX_DTLB_ENTRIES(descs[1]);
226 	cai->cai_associativity = AMD_L1_1GB_EAX_DTLB_ASSOC(descs[1]);
227 	cai->cai_linesize = (1 * 1024);
228 
229 	cai = &ci->ci_cinfo[CAI_L1_1GBITLB];
230 	cai->cai_totalsize = AMD_L1_1GB_EAX_IUTLB_ENTRIES(descs[0]);
231 	cai->cai_associativity = AMD_L1_1GB_EAX_IUTLB_ASSOC(descs[0]);
232 	cai->cai_linesize = (1 * 1024);
233 
234 	cai = &ci->ci_cinfo[CAI_L2_1GBDTLB];
235 	cai->cai_totalsize = AMD_L2_1GB_EBX_DUTLB_ENTRIES(descs[1]);
236 	cai->cai_associativity = AMD_L2_1GB_EBX_DUTLB_ASSOC(descs[1]);
237 	cai->cai_linesize = (1 * 1024);
238 
239 	cai = &ci->ci_cinfo[CAI_L2_1GBITLB];
240 	cai->cai_totalsize = AMD_L2_1GB_EBX_IUTLB_ENTRIES(descs[0]);
241 	cai->cai_associativity = AMD_L2_1GB_EBX_IUTLB_ASSOC(descs[0]);
242 	cai->cai_linesize = (1 * 1024);
243 }
244 
245 static void
246 cpu_probe_k5(struct cpu_info *ci)
247 {
248 	int flag;
249 
250 	if (cpu_vendor != CPUVENDOR_AMD ||
251 	    CPUID2FAMILY(ci->ci_signature) != 5)
252 		return;
253 
254 	if (CPUID2MODEL(ci->ci_signature) == 0) {
255 		/*
256 		 * According to the AMD Processor Recognition App Note,
257 		 * the AMD-K5 Model 0 uses the wrong bit to indicate
258 		 * support for global PTEs, instead using bit 9 (APIC)
259 		 * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
260 		 */
261 		flag = ci->ci_feat_val[0];
262 		if ((flag & CPUID_APIC) != 0)
263 			flag = (flag & ~CPUID_APIC) | CPUID_PGE;
264 		ci->ci_feat_val[0] = flag;
265 	}
266 
267 	cpu_probe_amd_cache(ci);
268 }
269 
270 static void
271 cpu_probe_k678(struct cpu_info *ci)
272 {
273 	uint32_t descs[4];
274 
275 	if (cpu_vendor != CPUVENDOR_AMD ||
276 	    CPUID2FAMILY(ci->ci_signature) < 6)
277 		return;
278 
279 	/* Determine the extended feature flags. */
280 	x86_cpuid(0x80000000, descs);
281 	if (descs[0] >= 0x80000001) {
282 		x86_cpuid(0x80000001, descs);
283 		ci->ci_feat_val[3] = descs[2]; /* %ecx */
284 		ci->ci_feat_val[2] = descs[3]; /* %edx */
285 	}
286 
287 	cpu_probe_amd_cache(ci);
288 }
289 
290 static inline uint8_t
291 cyrix_read_reg(uint8_t reg)
292 {
293 
294 	outb(0x22, reg);
295 	return inb(0x23);
296 }
297 
298 static inline void
299 cyrix_write_reg(uint8_t reg, uint8_t data)
300 {
301 
302 	outb(0x22, reg);
303 	outb(0x23, data);
304 }
305 
306 static void
307 cpu_probe_cyrix_cmn(struct cpu_info *ci)
308 {
309 	/*
310 	 * i8254 latch check routine:
311 	 *     National Geode (formerly Cyrix MediaGX) has a serious bug in
312 	 *     its built-in i8254-compatible clock module (cs5510 cs5520).
313 	 *     Set the variable 'clock_broken_latch' to indicate it.
314 	 *
315 	 * This bug is not present in the cs5530, and the flag
316 	 * is disabled again in sys/arch/i386/pci/pcib.c if this later
317 	 * model device is detected. Ideally, this work-around should not
318 	 * even be in here, it should be in there. XXX
319 	 */
320 	uint8_t c3;
321 #ifndef XEN
322 	extern int clock_broken_latch;
323 
324 	switch (ci->ci_signature) {
325 	case 0x440:     /* Cyrix MediaGX */
326 	case 0x540:     /* GXm */
327 		clock_broken_latch = 1;
328 		break;
329 	}
330 #endif
331 
332 	/* set up various cyrix registers */
333 	/*
334 	 * Enable suspend on halt (powersave mode).
335 	 * When powersave mode is enabled, the TSC stops counting
336 	 * while the CPU is halted in idle() waiting for an interrupt.
337 	 * This means we can't use the TSC for interval time in
338 	 * microtime(9), and thus it is disabled here.
339 	 *
340 	 * It still makes a perfectly good cycle counter
341 	 * for program profiling, so long as you remember you're
342 	 * counting cycles, and not time. Further, if you don't
343 	 * mind not using powersave mode, the TSC works just fine,
344 	 * so this should really be optional. XXX
345 	 */
346 	cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08);
347 
348 	/*
349 	 * Do not disable the TSC on the Geode GX, it's reported to
350 	 * work fine.
351 	 */
352 	if (ci->ci_signature != 0x552)
353 		ci->ci_feat_val[0] &= ~CPUID_TSC;
354 
355 	/* enable access to ccr4/ccr5 */
356 	c3 = cyrix_read_reg(0xC3);
357 	cyrix_write_reg(0xC3, c3 | 0x10);
358 	/* cyrix's workaround  for the "coma bug" */
359 	cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8);
360 	cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f);
361 	cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff);
362 	cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87);
363 	/* disable access to ccr4/ccr5 */
364 	cyrix_write_reg(0xC3, c3);
365 }
366 
367 static void
368 cpu_probe_cyrix(struct cpu_info *ci)
369 {
370 
371 	if (cpu_vendor != CPUVENDOR_CYRIX ||
372 	    CPUID2FAMILY(ci->ci_signature) < 4 ||
373 	    CPUID2FAMILY(ci->ci_signature) > 6)
374 		return;
375 
376 	cpu_probe_cyrix_cmn(ci);
377 }
378 
379 static void
380 cpu_probe_winchip(struct cpu_info *ci)
381 {
382 
383 	if (cpu_vendor != CPUVENDOR_IDT ||
384 	    CPUID2FAMILY(ci->ci_signature) != 5)
385 	    	return;
386 
387 	if (CPUID2MODEL(ci->ci_signature) == 4) {
388 		/* WinChip C6 */
389 		ci->ci_feat_val[0] &= ~CPUID_TSC;
390 	}
391 }
392 
393 static void
394 cpu_probe_c3(struct cpu_info *ci)
395 {
396 	u_int family, model, stepping, descs[4], lfunc, msr;
397 	struct x86_cache_info *cai;
398 
399 	if (cpu_vendor != CPUVENDOR_IDT ||
400 	    CPUID2FAMILY(ci->ci_signature) < 6)
401 	    	return;
402 
403 	family = CPUID2FAMILY(ci->ci_signature);
404 	model = CPUID2MODEL(ci->ci_signature);
405 	stepping = CPUID2STEPPING(ci->ci_signature);
406 
407 	/* Determine the largest extended function value. */
408 	x86_cpuid(0x80000000, descs);
409 	lfunc = descs[0];
410 
411 	/* Determine the extended feature flags. */
412 	if (lfunc >= 0x80000001) {
413 		x86_cpuid(0x80000001, descs);
414 		ci->ci_feat_val[2] = descs[3];
415 	}
416 
417 	if (family > 6 || model > 0x9 || (model == 0x9 && stepping >= 3)) {
418 		/* Nehemiah or Esther */
419 		x86_cpuid(0xc0000000, descs);
420 		lfunc = descs[0];
421 		if (lfunc >= 0xc0000001) {	/* has ACE, RNG */
422 		    int rng_enable = 0, ace_enable = 0;
423 		    x86_cpuid(0xc0000001, descs);
424 		    lfunc = descs[3];
425 		    ci->ci_feat_val[4] = lfunc;
426 		    /* Check for and enable RNG */
427 		    if (lfunc & CPUID_VIA_HAS_RNG) {
428 		    	if (!(lfunc & CPUID_VIA_DO_RNG)) {
429 			    rng_enable++;
430 			    ci->ci_feat_val[4] |= CPUID_VIA_DO_RNG;
431 			}
432 		    }
433 		    /* Check for and enable ACE (AES-CBC) */
434 		    if (lfunc & CPUID_VIA_HAS_ACE) {
435 			if (!(lfunc & CPUID_VIA_DO_ACE)) {
436 			    ace_enable++;
437 			    ci->ci_feat_val[4] |= CPUID_VIA_DO_ACE;
438 			}
439 		    }
440 		    /* Check for and enable SHA */
441 		    if (lfunc & CPUID_VIA_HAS_PHE) {
442 			if (!(lfunc & CPUID_VIA_DO_PHE)) {
443 			    ace_enable++;
444 			    ci->ci_feat_val[4] |= CPUID_VIA_DO_PHE;
445 			}
446 		    }
447 		    /* Check for and enable ACE2 (AES-CTR) */
448 		    if (lfunc & CPUID_VIA_HAS_ACE2) {
449 			if (!(lfunc & CPUID_VIA_DO_ACE2)) {
450 			    ace_enable++;
451 			    ci->ci_feat_val[4] |= CPUID_VIA_DO_ACE2;
452 			}
453 		    }
454 		    /* Check for and enable PMM (modmult engine) */
455 		    if (lfunc & CPUID_VIA_HAS_PMM) {
456 			if (!(lfunc & CPUID_VIA_DO_PMM)) {
457 			    ace_enable++;
458 			    ci->ci_feat_val[4] |= CPUID_VIA_DO_PMM;
459 			}
460 		    }
461 
462 		    /* Actually do the enables. */
463 		    if (rng_enable) {
464 			msr = rdmsr(MSR_VIA_RNG);
465 			wrmsr(MSR_VIA_RNG, msr | MSR_VIA_RNG_ENABLE);
466 		    }
467 		    if (ace_enable) {
468 			msr = rdmsr(MSR_VIA_ACE);
469 			wrmsr(MSR_VIA_ACE, msr | MSR_VIA_ACE_ENABLE);
470 		    }
471 
472 		}
473 	}
474 
475 	/*
476 	 * Determine L1 cache/TLB info.
477 	 */
478 	if (lfunc < 0x80000005) {
479 		/* No L1 cache info available. */
480 		return;
481 	}
482 
483 	x86_cpuid(0x80000005, descs);
484 
485 	cai = &ci->ci_cinfo[CAI_ITLB];
486 	cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]);
487 	cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]);
488 	cai->cai_linesize = (4 * 1024);
489 
490 	cai = &ci->ci_cinfo[CAI_DTLB];
491 	cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]);
492 	cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]);
493 	cai->cai_linesize = (4 * 1024);
494 
495 	cai = &ci->ci_cinfo[CAI_DCACHE];
496 	cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]);
497 	cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]);
498 	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]);
499 	if (family == 6 && model == 9 && stepping == 8) {
500 		/* Erratum: stepping 8 reports 4 when it should be 2 */
501 		cai->cai_associativity = 2;
502 	}
503 
504 	cai = &ci->ci_cinfo[CAI_ICACHE];
505 	cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]);
506 	cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]);
507 	cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]);
508 	if (family == 6 && model == 9 && stepping == 8) {
509 		/* Erratum: stepping 8 reports 4 when it should be 2 */
510 		cai->cai_associativity = 2;
511 	}
512 
513 	/*
514 	 * Determine L2 cache/TLB info.
515 	 */
516 	if (lfunc < 0x80000006) {
517 		/* No L2 cache info available. */
518 		return;
519 	}
520 
521 	x86_cpuid(0x80000006, descs);
522 
523 	cai = &ci->ci_cinfo[CAI_L2CACHE];
524 	if (family > 6 || model >= 9) {
525 		cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]);
526 		cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]);
527 		cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]);
528 	} else {
529 		cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]);
530 		cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]);
531 		cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]);
532 	}
533 }
534 
535 static void
536 cpu_probe_geode(struct cpu_info *ci)
537 {
538 
539 	if (memcmp("Geode by NSC", ci->ci_vendor, 12) != 0 ||
540 	    CPUID2FAMILY(ci->ci_signature) != 5)
541 	    	return;
542 
543 	cpu_probe_cyrix_cmn(ci);
544 	cpu_probe_amd_cache(ci);
545 }
546 
547 static void
548 cpu_probe_vortex86(struct cpu_info *ci)
549 {
550 #define PCI_MODE1_ADDRESS_REG	0x0cf8
551 #define PCI_MODE1_DATA_REG	0x0cfc
552 #define PCI_MODE1_ENABLE	0x80000000UL
553 
554 	uint32_t reg;
555 
556 	if (cpu_vendor != CPUVENDOR_VORTEX86)
557 		return;
558 	/*
559 	 * CPU model available from "Customer ID register" in
560 	 * North Bridge Function 0 PCI space
561 	 * we can't use pci_conf_read() because the PCI subsystem is not
562 	 * not initialised early enough
563 	 */
564 
565 	outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE | 0x90);
566 	reg = inl(PCI_MODE1_DATA_REG);
567 
568 	switch(reg) {
569 	case 0x31504d44:
570 		strcpy(cpu_brand_string, "Vortex86SX");
571 		break;
572 	case 0x32504d44:
573 		strcpy(cpu_brand_string, "Vortex86DX");
574 		break;
575 	case 0x33504d44:
576 		strcpy(cpu_brand_string, "Vortex86MX");
577 		break;
578 	default:
579 		strcpy(cpu_brand_string, "Unknown Vortex86");
580 		break;
581 	}
582 
583 #undef PCI_MODE1_ENABLE
584 #undef PCI_MODE1_ADDRESS_REG
585 #undef PCI_MODE1_DATA_REG
586 }
587 
588 void
589 cpu_probe(struct cpu_info *ci)
590 {
591 	const struct x86_cache_info *cai;
592 	u_int descs[4];
593 	int iterations, i, j;
594 	uint8_t desc;
595 	uint32_t miscbytes;
596 	uint32_t brand[12];
597 
598 	cpu_vendor = i386_nocpuid_cpus[cpu << 1];
599 	cpu_class = i386_nocpuid_cpus[(cpu << 1) + 1];
600 
601 	if (cpuid_level < 0)
602 		return;
603 
604 	for (i = 0; i < __arraycount(ci->ci_feat_val); i++) {
605 		ci->ci_feat_val[i] = 0;
606 	}
607 
608 	x86_cpuid(0, descs);
609 	cpuid_level = descs[0];
610 	ci->ci_vendor[0] = descs[1];
611 	ci->ci_vendor[2] = descs[2];
612 	ci->ci_vendor[1] = descs[3];
613 	ci->ci_vendor[3] = 0;
614 
615 	if (memcmp(ci->ci_vendor, "GenuineIntel", 12) == 0)
616 		cpu_vendor = CPUVENDOR_INTEL;
617 	else if (memcmp(ci->ci_vendor,  "AuthenticAMD", 12) == 0)
618 		cpu_vendor = CPUVENDOR_AMD;
619 	else if (memcmp(ci->ci_vendor,  "CyrixInstead", 12) == 0)
620 		cpu_vendor = CPUVENDOR_CYRIX;
621 	else if (memcmp(ci->ci_vendor,  "Geode by NSC", 12) == 0)
622 		cpu_vendor = CPUVENDOR_CYRIX;
623 	else if (memcmp(ci->ci_vendor, "CentaurHauls", 12) == 0)
624 		cpu_vendor = CPUVENDOR_IDT;
625 	else if (memcmp(ci->ci_vendor, "GenuineTMx86", 12) == 0)
626 		cpu_vendor = CPUVENDOR_TRANSMETA;
627 	else if (memcmp(ci->ci_vendor, "Vortex86 SoC", 12) == 0)
628 		cpu_vendor = CPUVENDOR_VORTEX86;
629 	else
630 		cpu_vendor = CPUVENDOR_UNKNOWN;
631 
632 	x86_cpuid(0x80000000, brand);
633 	if (brand[0] >= 0x80000004) {
634 		x86_cpuid(0x80000002, brand);
635 		x86_cpuid(0x80000003, brand + 4);
636 		x86_cpuid(0x80000004, brand + 8);
637 		for (i = 0; i < 48; i++) {
638 			if (((char *) brand)[i] != ' ')
639 				break;
640 		}
641 		memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i);
642 	}
643 
644 	if (cpuid_level >= 1) {
645 		x86_cpuid(1, descs);
646 		ci->ci_signature = descs[0];
647 		miscbytes = descs[1];
648 		ci->ci_feat_val[1] = descs[2];
649 		ci->ci_feat_val[0] = descs[3];
650 
651 		/* Determine family + class. */
652 		cpu_class = CPUID2FAMILY(ci->ci_signature) + (CPUCLASS_386 - 3);
653 		if (cpu_class > CPUCLASS_686)
654 			cpu_class = CPUCLASS_686;
655 
656 		/* CLFLUSH line size is next 8 bits */
657 		if (ci->ci_feat_val[0] & CPUID_CFLUSH)
658 			ci->ci_cflush_lsize = ((miscbytes >> 8) & 0xff) << 3;
659 		ci->ci_initapicid = (miscbytes >> 24) & 0xff;
660 	}
661 
662 	if (cpuid_level >= 2) {
663 		/* Parse the cache info from `cpuid', if we have it. */
664 		x86_cpuid(2, descs);
665 		iterations = descs[0] & 0xff;
666 		while (iterations-- > 0) {
667 			for (i = 0; i < 4; i++) {
668 				if (descs[i] & 0x80000000)
669 					continue;
670 				for (j = 0; j < 4; j++) {
671 					if (i == 0 && j == 0)
672 						continue;
673 					desc = (descs[i] >> (j * 8)) & 0xff;
674 					if (desc == 0)
675 						continue;
676 					cai = cache_info_lookup(
677 					    intel_cpuid_cache_info, desc);
678 					if (cai != NULL) {
679 						ci->ci_cinfo[cai->cai_index] =
680 						    *cai;
681 					}
682 				}
683 			}
684 		}
685 	}
686 
687 	cpu_probe_k5(ci);
688 	cpu_probe_k678(ci);
689 	cpu_probe_cyrix(ci);
690 	cpu_probe_winchip(ci);
691 	cpu_probe_c3(ci);
692 	cpu_probe_geode(ci);
693 	cpu_probe_vortex86(ci);
694 
695 	x86_cpu_topology(ci);
696 
697 	if (cpu_vendor != CPUVENDOR_AMD && (ci->ci_feat_val[0] & CPUID_TM) &&
698 	    (rdmsr(MSR_MISC_ENABLE) & (1 << 3)) == 0) {
699 		/* Enable thermal monitor 1. */
700 		wrmsr(MSR_MISC_ENABLE, rdmsr(MSR_MISC_ENABLE) | (1<<3));
701 	}
702 
703 	ci->ci_feat_val[0] &= ~CPUID_FEAT_BLACKLIST;
704 	if (ci == &cpu_info_primary) {
705 		/* If first. Boot Processor is the cpu_feature reference. */
706 		for (i = 0; i < __arraycount(cpu_feature); i++) {
707 			cpu_feature[i] = ci->ci_feat_val[i];
708 		}
709 #ifndef XEN
710 		/* Early patch of text segment. */
711 		x86_patch(true);
712 #endif
713 	} else {
714 		/*
715 		 * If not first. Warn about cpu_feature mismatch for
716 		 * secondary CPUs.
717 		 */
718 		for (i = 0; i < __arraycount(cpu_feature); i++) {
719 			if (cpu_feature[i] != ci->ci_feat_val[i])
720 				aprint_error_dev(ci->ci_dev,
721 				    "feature mismatch: cpu_feature[%d] is "
722 				    "%#x, but CPU reported %#x\n",
723 				    i, cpu_feature[i], ci->ci_feat_val[i]);
724 		}
725 	}
726 }
727 
728 void
729 cpu_identify(struct cpu_info *ci)
730 {
731 
732 	snprintf(cpu_model, sizeof(cpu_model), "%s %d86-class",
733 	    cpu_vendor_names[cpu_vendor], cpu_class + 3);
734 	if (cpu_brand_string[0] != '\0') {
735 		aprint_normal(": %s", cpu_brand_string);
736 	} else {
737 		aprint_normal(": %s", cpu_model);
738 		if (ci->ci_data.cpu_cc_freq != 0)
739 			aprint_normal(", %dMHz",
740 			    (int)(ci->ci_data.cpu_cc_freq / 1000000));
741 	}
742 	if (ci->ci_signature != 0)
743 		aprint_normal(", id 0x%x", ci->ci_signature);
744 	aprint_normal("\n");
745 
746 	if (cpu_brand_string[0] == '\0') {
747 		strlcpy(cpu_brand_string, cpu_model, sizeof(cpu_brand_string));
748 	}
749 	if (cpu_class == CPUCLASS_386) {
750 		panic("NetBSD requires an 80486DX or later processor");
751 	}
752 	if (cpu == CPU_486DLC) {
753 		aprint_error("WARNING: BUGGY CYRIX CACHE\n");
754 	}
755 
756 	if ((cpu_vendor == CPUVENDOR_AMD) /* check enablement of an */
757 	  && (device_unit(ci->ci_dev) == 0) /* AMD feature only once */
758 	  && ((cpu_feature[3] & CPUID_SVM) == CPUID_SVM)
759 #if defined(XEN) && !defined(DOM0OPS)
760 	  && (false)  /* on Xen rdmsr is for Dom0 only */
761 #endif
762 	  )
763 	{
764 		uint64_t val;
765 
766 		val = rdmsr(MSR_VMCR);
767 		if (((val & VMCR_SVMED) == VMCR_SVMED)
768 		  && ((val & VMCR_LOCK) == VMCR_LOCK))
769 		{
770 			aprint_normal_dev(ci->ci_dev,
771 				"SVM disabled by the BIOS\n");
772 		}
773 	}
774 
775 #ifdef i386 /* XXX for now */
776 	if (cpu_vendor == CPUVENDOR_TRANSMETA) {
777 		u_int descs[4];
778 		x86_cpuid(0x80860000, descs);
779 		if (descs[0] >= 0x80860007)
780 			tmx86_init_longrun();
781 	}
782 
783 	/* If we have FXSAVE/FXRESTOR, use them. */
784 	if (cpu_feature[0] & CPUID_FXSR) {
785 		i386_use_fxsave = 1;
786 		/*
787 		 * If we have SSE/SSE2, enable XMM exceptions, and
788 		 * notify userland.
789 		 */
790 		if (cpu_feature[0] & CPUID_SSE)
791 			i386_has_sse = 1;
792 		if (cpu_feature[0] & CPUID_SSE2)
793 			i386_has_sse2 = 1;
794 	} else
795 		i386_use_fxsave = 0;
796 #endif	/* i386 */
797 }
798