i386/identcpu.c: Add support for VIA C7
[dragonfly.git] / sys / platform / pc32 / i386 / identcpu.c
blob551a11bbb36aa7002001ed1841fd9a0cbaa75152
1 /*
2 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
3 * Copyright (c) 1992 Terrence R. Lambert.
4 * Copyright (c) 1997 KATO Takenori.
5 * Copyright (c) 2001 Tamotsu Hattori.
6 * Copyright (c) 2001 Mitsuru IWASAKI.
7 * All rights reserved.
9 * This code is derived from software contributed to Berkeley by
10 * William Jolitz.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
40 * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
41 * $FreeBSD: src/sys/i386/i386/identcpu.c,v 1.80.2.15 2003/04/11 17:06:41 jhb Exp $
42 * $DragonFly: src/sys/platform/pc32/i386/identcpu.c,v 1.24 2008/11/24 13:14:21 swildner Exp $
45 #include "opt_cpu.h"
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/sysctl.h>
51 #include <sys/lock.h>
53 #include <machine/asmacros.h>
54 #include <machine/clock.h>
55 #include <machine/cputypes.h>
56 #include <machine/segments.h>
57 #include <machine/specialreg.h>
58 #include <machine/md_var.h>
60 #include <machine_base/isa/intr_machdep.h>
62 #define IDENTBLUE_CYRIX486 0
63 #define IDENTBLUE_IBMCPU 1
64 #define IDENTBLUE_CYRIXM2 2
66 /* XXX - should be in header file: */
67 void printcpuinfo(void);
68 void finishidentcpu(void);
69 #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
70 void enable_K5_wt_alloc(void);
71 void enable_K6_wt_alloc(void);
72 void enable_K6_2_wt_alloc(void);
73 #endif
74 void panicifcpuunsupported(void);
76 static void identifycyrix(void);
77 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
78 static void print_AMD_features(void);
79 #endif
80 static void print_AMD_info(void);
81 static void print_AMD_assoc(int i);
82 static void print_transmeta_info(void);
83 static void setup_tmx86_longrun(void);
84 static void print_via_padlock_info(void);
86 int cpu_class = CPUCLASS_386;
87 u_int cpu_exthigh; /* Highest arg to extended CPUID */
88 u_int cyrix_did; /* Device ID of Cyrix CPU */
89 char machine[] = MACHINE;
90 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
91 machine, 0, "Machine class");
93 static char cpu_model[128];
94 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD,
95 cpu_model, 0, "Machine model");
97 static char cpu_brand[48];
99 #define MAX_ADDITIONAL_INFO 16
101 static const char *additional_cpu_info_ary[MAX_ADDITIONAL_INFO];
102 static u_int additional_cpu_info_count;
104 #define MAX_BRAND_INDEX 23
107 * Brand ID's according to Intel document AP-485, number 241618-31, published
108 * September 2006, page 42.
110 static const char *cpu_brandtable[MAX_BRAND_INDEX + 1] = {
111 NULL, /* No brand */
112 "Intel Celeron",
113 "Intel Pentium III",
114 "Intel Pentium III Xeon",
115 "Intel Pentium III",
116 NULL, /* Unspecified */
117 "Mobile Intel Pentium III-M",
118 "Mobile Intel Celeron",
119 "Intel Pentium 4",
120 "Intel Pentium 4",
121 "Intel Celeron",
122 "Intel Xeon",
123 "Intel Xeon MP",
124 NULL, /* Unspecified */
125 "Mobile Intel Pentium 4-M",
126 "Mobile Intel Celeron",
127 NULL, /* Unspecified */
128 "Mobile Genuine Intel",
129 "Intel Celeron M",
130 "Mobile Intel Celeron",
131 "Intel Celeron",
132 "Mobile Genuine Intel",
133 "Intel Pentium M",
134 "Mobile Intel Celeron"
137 static struct cpu_nameclass i386_cpus[] = {
138 { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */
139 { "i386SX", CPUCLASS_386 }, /* CPU_386SX */
140 { "i386DX", CPUCLASS_386 }, /* CPU_386 */
141 { "i486SX", CPUCLASS_486 }, /* CPU_486SX */
142 { "i486DX", CPUCLASS_486 }, /* CPU_486 */
143 { "Pentium", CPUCLASS_586 }, /* CPU_586 */
144 { "Cyrix 486", CPUCLASS_486 }, /* CPU_486DLC */
145 { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */
146 { "Cyrix 5x86", CPUCLASS_486 }, /* CPU_M1SC */
147 { "Cyrix 6x86", CPUCLASS_486 }, /* CPU_M1 */
148 { "Blue Lightning", CPUCLASS_486 }, /* CPU_BLUE */
149 { "Cyrix 6x86MX", CPUCLASS_686 }, /* CPU_M2 */
150 { "NexGen 586", CPUCLASS_386 }, /* CPU_NX586 (XXX) */
151 { "Cyrix 486S/DX", CPUCLASS_486 }, /* CPU_CY486DX */
152 { "Pentium II", CPUCLASS_686 }, /* CPU_PII */
153 { "Pentium III", CPUCLASS_686 }, /* CPU_PIII */
154 { "Pentium 4", CPUCLASS_686 }, /* CPU_P4 */
157 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
158 int has_f00f_bug = 0; /* Initialized so that it can be patched. */
159 #endif
161 void
162 printcpuinfo(void)
164 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
165 u_int regs[4], i;
166 #endif
167 char *brand;
169 cpu_class = i386_cpus[cpu].cpu_class;
170 kprintf("CPU: ");
171 strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof (cpu_model));
173 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
174 /* Check for extended CPUID information and a processor name. */
175 if (cpu_high > 0 &&
176 (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
177 strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
178 strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
179 strcmp(cpu_vendor, "TransmetaCPU") == 0)) {
180 do_cpuid(0x80000000, regs);
181 if (regs[0] >= 0x80000000) {
182 cpu_exthigh = regs[0];
183 if (cpu_exthigh >= 0x80000004) {
184 brand = cpu_brand;
185 for (i = 0x80000002; i < 0x80000005; i++) {
186 do_cpuid(i, regs);
187 memcpy(brand, regs, sizeof(regs));
188 brand += sizeof(regs);
194 if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
195 if ((cpu_id & 0xf00) > 0x300) {
196 u_int brand_index;
198 cpu_model[0] = '\0';
200 switch (cpu_id & 0x3000) {
201 case 0x1000:
202 strcpy(cpu_model, "Overdrive ");
203 break;
204 case 0x2000:
205 strcpy(cpu_model, "Dual ");
206 break;
209 switch (cpu_id & 0xf00) {
210 case 0x400:
211 strcat(cpu_model, "i486 ");
212 /* Check the particular flavor of 486 */
213 switch (cpu_id & 0xf0) {
214 case 0x00:
215 case 0x10:
216 strcat(cpu_model, "DX");
217 break;
218 case 0x20:
219 strcat(cpu_model, "SX");
220 break;
221 case 0x30:
222 strcat(cpu_model, "DX2");
223 break;
224 case 0x40:
225 strcat(cpu_model, "SL");
226 break;
227 case 0x50:
228 strcat(cpu_model, "SX2");
229 break;
230 case 0x70:
231 strcat(cpu_model,
232 "DX2 Write-Back Enhanced");
233 break;
234 case 0x80:
235 strcat(cpu_model, "DX4");
236 break;
238 break;
239 case 0x500:
240 /* Check the particular flavor of 586 */
241 strcat(cpu_model, "Pentium");
242 switch (cpu_id & 0xf0) {
243 case 0x00:
244 strcat(cpu_model, " A-step");
245 break;
246 case 0x10:
247 strcat(cpu_model, "/P5");
248 break;
249 case 0x20:
250 strcat(cpu_model, "/P54C");
251 break;
252 case 0x30:
253 strcat(cpu_model, "/P54T Overdrive");
254 break;
255 case 0x40:
256 strcat(cpu_model, "/P55C");
257 break;
258 case 0x70:
259 strcat(cpu_model, "/P54C");
260 break;
261 case 0x80:
262 strcat(cpu_model, "/P55C (quarter-micron)");
263 break;
264 default:
265 /* nothing */
266 break;
268 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
270 * XXX - If/when Intel fixes the bug, this
271 * should also check the version of the
272 * CPU, not just that it's a Pentium.
274 has_f00f_bug = 1;
275 #endif
276 break;
277 case 0x600:
278 /* Check the particular flavor of 686 */
279 switch (cpu_id & 0xf0) {
280 case 0x00:
281 strcat(cpu_model, "Pentium Pro A-step");
282 break;
283 case 0x10:
284 strcat(cpu_model, "Pentium Pro");
285 break;
286 case 0x30:
287 case 0x50:
288 case 0x60:
289 strcat(cpu_model,
290 "Pentium II/Pentium II Xeon/Celeron");
291 cpu = CPU_PII;
292 break;
293 case 0x70:
294 case 0x80:
295 case 0xa0:
296 case 0xb0:
297 strcat(cpu_model,
298 "Pentium III/Pentium III Xeon/Celeron");
299 cpu = CPU_PIII;
300 break;
301 default:
302 strcat(cpu_model, "Unknown 80686");
303 break;
305 break;
306 case 0xf00:
307 strcat(cpu_model, "Pentium 4");
308 cpu = CPU_P4;
309 break;
310 default:
311 strcat(cpu_model, "unknown");
312 break;
316 * If we didn't get a brand name from the extended
317 * CPUID, try to look it up in the brand table.
319 if (cpu_high > 0 && *cpu_brand == '\0') {
320 brand_index = cpu_procinfo & CPUID_BRAND_INDEX;
321 if (brand_index <= MAX_BRAND_INDEX &&
322 cpu_brandtable[brand_index] != NULL)
323 strcpy(cpu_brand,
324 cpu_brandtable[brand_index]);
327 } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
329 * Values taken from AMD Processor Recognition
330 * http://www.amd.com/K6/k6docs/pdf/20734g.pdf
331 * (also describes ``Features'' encodings.
333 strcpy(cpu_model, "AMD ");
334 switch (cpu_id & 0xFF0) {
335 case 0x410:
336 strcat(cpu_model, "Standard Am486DX");
337 break;
338 case 0x430:
339 strcat(cpu_model, "Enhanced Am486DX2 Write-Through");
340 break;
341 case 0x470:
342 strcat(cpu_model, "Enhanced Am486DX2 Write-Back");
343 break;
344 case 0x480:
345 strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Through");
346 break;
347 case 0x490:
348 strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Back");
349 break;
350 case 0x4E0:
351 strcat(cpu_model, "Am5x86 Write-Through");
352 break;
353 case 0x4F0:
354 strcat(cpu_model, "Am5x86 Write-Back");
355 break;
356 case 0x500:
357 strcat(cpu_model, "K5 model 0");
358 tsc_is_broken = 1;
359 break;
360 case 0x510:
361 strcat(cpu_model, "K5 model 1");
362 break;
363 case 0x520:
364 strcat(cpu_model, "K5 PR166 (model 2)");
365 break;
366 case 0x530:
367 strcat(cpu_model, "K5 PR200 (model 3)");
368 break;
369 case 0x560:
370 strcat(cpu_model, "K6");
371 break;
372 case 0x570:
373 strcat(cpu_model, "K6 266 (model 1)");
374 break;
375 case 0x580:
376 strcat(cpu_model, "K6-2");
377 break;
378 case 0x590:
379 strcat(cpu_model, "K6-III");
380 break;
381 default:
382 strcat(cpu_model, "Unknown");
383 break;
385 #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
386 if ((cpu_id & 0xf00) == 0x500) {
387 if (((cpu_id & 0x0f0) > 0)
388 && ((cpu_id & 0x0f0) < 0x60)
389 && ((cpu_id & 0x00f) > 3))
390 enable_K5_wt_alloc();
391 else if (((cpu_id & 0x0f0) > 0x80)
392 || (((cpu_id & 0x0f0) == 0x80)
393 && (cpu_id & 0x00f) > 0x07))
394 enable_K6_2_wt_alloc();
395 else if ((cpu_id & 0x0f0) > 0x50)
396 enable_K6_wt_alloc();
398 #endif
399 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
400 strcpy(cpu_model, "Cyrix ");
401 switch (cpu_id & 0xff0) {
402 case 0x440:
403 strcat(cpu_model, "MediaGX");
404 break;
405 case 0x520:
406 strcat(cpu_model, "6x86");
407 break;
408 case 0x540:
409 cpu_class = CPUCLASS_586;
410 strcat(cpu_model, "GXm");
411 break;
412 case 0x600:
413 strcat(cpu_model, "6x86MX");
414 break;
415 default:
417 * Even though CPU supports the cpuid
418 * instruction, it can be disabled.
419 * Therefore, this routine supports all Cyrix
420 * CPUs.
422 switch (cyrix_did & 0xf0) {
423 case 0x00:
424 switch (cyrix_did & 0x0f) {
425 case 0x00:
426 strcat(cpu_model, "486SLC");
427 break;
428 case 0x01:
429 strcat(cpu_model, "486DLC");
430 break;
431 case 0x02:
432 strcat(cpu_model, "486SLC2");
433 break;
434 case 0x03:
435 strcat(cpu_model, "486DLC2");
436 break;
437 case 0x04:
438 strcat(cpu_model, "486SRx");
439 break;
440 case 0x05:
441 strcat(cpu_model, "486DRx");
442 break;
443 case 0x06:
444 strcat(cpu_model, "486SRx2");
445 break;
446 case 0x07:
447 strcat(cpu_model, "486DRx2");
448 break;
449 case 0x08:
450 strcat(cpu_model, "486SRu");
451 break;
452 case 0x09:
453 strcat(cpu_model, "486DRu");
454 break;
455 case 0x0a:
456 strcat(cpu_model, "486SRu2");
457 break;
458 case 0x0b:
459 strcat(cpu_model, "486DRu2");
460 break;
461 default:
462 strcat(cpu_model, "Unknown");
463 break;
465 break;
466 case 0x10:
467 switch (cyrix_did & 0x0f) {
468 case 0x00:
469 strcat(cpu_model, "486S");
470 break;
471 case 0x01:
472 strcat(cpu_model, "486S2");
473 break;
474 case 0x02:
475 strcat(cpu_model, "486Se");
476 break;
477 case 0x03:
478 strcat(cpu_model, "486S2e");
479 break;
480 case 0x0a:
481 strcat(cpu_model, "486DX");
482 break;
483 case 0x0b:
484 strcat(cpu_model, "486DX2");
485 break;
486 case 0x0f:
487 strcat(cpu_model, "486DX4");
488 break;
489 default:
490 strcat(cpu_model, "Unknown");
491 break;
493 break;
494 case 0x20:
495 if ((cyrix_did & 0x0f) < 8)
496 strcat(cpu_model, "6x86"); /* Where did you get it? */
497 else
498 strcat(cpu_model, "5x86");
499 break;
500 case 0x30:
501 strcat(cpu_model, "6x86");
502 break;
503 case 0x40:
504 if ((cyrix_did & 0xf000) == 0x3000) {
505 cpu_class = CPUCLASS_586;
506 strcat(cpu_model, "GXm");
507 } else
508 strcat(cpu_model, "MediaGX");
509 break;
510 case 0x50:
511 strcat(cpu_model, "6x86MX");
512 break;
513 case 0xf0:
514 switch (cyrix_did & 0x0f) {
515 case 0x0d:
516 strcat(cpu_model, "Overdrive CPU");
517 break;
518 case 0x0e:
519 strcpy(cpu_model, "Texas Instruments 486SXL");
520 break;
521 case 0x0f:
522 strcat(cpu_model, "486SLC/DLC");
523 break;
524 default:
525 strcat(cpu_model, "Unknown");
526 break;
528 break;
529 default:
530 strcat(cpu_model, "Unknown");
531 break;
533 break;
535 } else if (strcmp(cpu_vendor, "RiseRiseRise") == 0) {
536 strcpy(cpu_model, "Rise ");
537 switch (cpu_id & 0xff0) {
538 case 0x500:
539 strcat(cpu_model, "mP6");
540 break;
541 default:
542 strcat(cpu_model, "Unknown");
544 } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) {
545 switch (cpu_id & 0xff0) {
546 case 0x540:
547 strcpy(cpu_model, "IDT WinChip C6");
548 tsc_is_broken = 1;
549 break;
550 case 0x580:
551 strcpy(cpu_model, "IDT WinChip 2");
552 break;
553 case 0x660:
554 strcpy(cpu_model, "VIA C3 Samuel");
555 break;
556 case 0x670:
557 if (cpu_id & 0x8)
558 strcpy(cpu_model, "VIA C3 Ezra");
559 else
560 strcpy(cpu_model, "VIA C3 Samuel 2");
561 break;
562 case 0x680:
563 strcpy(cpu_model, "VIA C3 Ezra-T");
564 break;
565 case 0x690:
566 strcpy(cpu_model, "VIA C3 Nehemiah");
567 break;
568 case 0x6a0:
569 case 0x6d0:
570 strcpy(cpu_model, "VIA C7 Esther");
571 break;
572 default:
573 strcpy(cpu_model, "VIA/IDT Unknown");
575 } else if (strcmp(cpu_vendor, "IBM") == 0) {
576 strcpy(cpu_model, "Blue Lightning CPU");
580 * Replace cpu_model with cpu_brand minus leading spaces if
581 * we have one.
583 brand = cpu_brand;
584 while (*brand == ' ')
585 ++brand;
586 if (*brand != '\0')
587 strcpy(cpu_model, brand);
589 #endif
591 kprintf("%s (", cpu_model);
592 switch(cpu_class) {
593 case CPUCLASS_286:
594 kprintf("286");
595 break;
596 case CPUCLASS_386:
597 kprintf("386");
598 break;
599 #if defined(I486_CPU)
600 case CPUCLASS_486:
601 kprintf("486");
602 /* bzero = i486_bzero; */
603 break;
604 #endif
605 #if defined(I586_CPU)
606 case CPUCLASS_586:
607 kprintf("%lld.%02lld-MHz ",
608 (tsc_frequency + 4999LL) / 1000000LL,
609 ((tsc_frequency + 4999LL) / 10000LL) % 100LL);
610 kprintf("586");
611 break;
612 #endif
613 #if defined(I686_CPU)
614 case CPUCLASS_686:
615 kprintf("%lld.%02lld-MHz ",
616 (tsc_frequency + 4999LL) / 1000000LL,
617 ((tsc_frequency + 4999LL) / 10000LL) % 100LL);
618 kprintf("686");
619 break;
620 #endif
621 default:
622 kprintf("Unknown"); /* will panic below... */
624 kprintf("-class CPU)\n");
625 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
626 if(*cpu_vendor)
627 kprintf(" Origin = \"%s\"",cpu_vendor);
628 if(cpu_id)
629 kprintf(" Id = 0x%x", cpu_id);
631 if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
632 strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
633 strcmp(cpu_vendor, "RiseRiseRise") == 0 ||
634 strcmp(cpu_vendor, "CentaurHauls") == 0 ||
635 ((strcmp(cpu_vendor, "CyrixInstead") == 0) &&
636 ((cpu_id & 0xf00) > 0x500))) {
637 kprintf(" Stepping = %u", cpu_id & 0xf);
638 if (strcmp(cpu_vendor, "CyrixInstead") == 0)
639 kprintf(" DIR=0x%04x", cyrix_did);
640 if (cpu_high > 0) {
642 * Here we should probably set up flags indicating
643 * whether or not various features are available.
644 * The interesting ones are probably VME, PSE, PAE,
645 * and PGE. The code already assumes without bothering
646 * to check that all CPUs >= Pentium have a TSC and
647 * MSRs.
649 kprintf("\n Features=0x%b", cpu_feature,
650 "\020"
651 "\001FPU" /* Integral FPU */
652 "\002VME" /* Extended VM86 mode support */
653 "\003DE" /* Debugging Extensions (CR4.DE) */
654 "\004PSE" /* 4MByte page tables */
655 "\005TSC" /* Timestamp counter */
656 "\006MSR" /* Machine specific registers */
657 "\007PAE" /* Physical address extension */
658 "\010MCE" /* Machine Check support */
659 "\011CX8" /* CMPEXCH8 instruction */
660 "\012APIC" /* SMP local APIC */
661 "\013oldMTRR" /* Previous implementation of MTRR */
662 "\014SEP" /* Fast System Call */
663 "\015MTRR" /* Memory Type Range Registers */
664 "\016PGE" /* PG_G (global bit) support */
665 "\017MCA" /* Machine Check Architecture */
666 "\020CMOV" /* CMOV instruction */
667 "\021PAT" /* Page attributes table */
668 "\022PSE36" /* 36 bit address space support */
669 "\023PN" /* Processor Serial number */
670 "\024CLFLUSH" /* Has the CLFLUSH instruction */
671 "\025<b20>"
672 "\026DTS" /* Debug Trace Store */
673 "\027ACPI" /* ACPI support */
674 "\030MMX" /* MMX instructions */
675 "\031FXSR" /* FXSAVE/FXRSTOR */
676 "\032SSE" /* Streaming SIMD Extensions */
677 "\033SSE2" /* Streaming SIMD Extensions #2 */
678 "\034SS" /* Self snoop */
679 "\035HTT" /* Hyperthreading (see EBX bit 16-23) */
680 "\036TM" /* Thermal Monitor clock slowdown */
681 "\037IA64" /* CPU can execute IA64 instructions */
682 "\040PBE" /* Pending Break Enable */
685 if (cpu_feature2 != 0) {
686 kprintf("\n Features2=0x%b", cpu_feature2,
687 "\020"
688 "\001SSE3" /* SSE3 */
689 "\002<b1>"
690 "\003DTES64" /* 64-bit Debug Trace */
691 "\004MON" /* MONITOR/MWAIT Instructions */
692 "\005DS_CPL" /* CPL Qualified Debug Store */
693 "\006VMX" /* Virtual Machine Extensions */
694 "\007SMX" /* Safer Mode Extensions */
695 "\010EST" /* Enhanced SpeedStep */
696 "\011TM2" /* Thermal Monitor 2 */
697 "\012SSSE3" /* SSSE3 */
698 "\013CNXT-ID" /* L1 context ID available */
699 "\014<b11>"
700 "\015<b12>"
701 "\016CX16" /* CMPXCHG16B Instruction */
702 "\017xTPR" /* Send Task Priority Messages*/
703 "\020PDCM" /* Perf/Debug Capability MSR */
704 "\021<b16>"
705 "\022<b17>"
706 "\023DCA" /* Direct Cache Access */
707 "\024SSE4.1"
708 "\025SSE4.2"
709 "\026x2APIC" /* xAPIC Extensions */
710 "\027MOVBE" /* MOVBE instruction */
711 "\030POPCNT"
712 "\031<b24>"
713 "\032<b25>"
714 "\033XSAVE"
715 "\034OSXSAVE"
716 "\035<b28>"
717 "\036<b29>"
718 "\037<b30>"
719 "\040<b31>"
724 * If this CPU supports hyperthreading then mention
725 * the number of logical CPU's it contains.
727 if (cpu_feature & CPUID_HTT &&
728 (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1)
729 kprintf("\n Hyperthreading: %d logical CPUs",
730 (cpu_procinfo & CPUID_HTT_CORES) >> 16);
732 if (strcmp(cpu_vendor, "AuthenticAMD") == 0 &&
733 cpu_exthigh >= 0x80000001)
734 print_AMD_features();
735 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
736 kprintf(" DIR=0x%04x", cyrix_did);
737 kprintf(" Stepping=%u", (cyrix_did & 0xf000) >> 12);
738 kprintf(" Revision=%u", (cyrix_did & 0x0f00) >> 8);
739 #ifndef CYRIX_CACHE_REALLY_WORKS
740 if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700)
741 kprintf("\n CPU cache: write-through mode");
742 #endif
744 if (strcmp(cpu_vendor, "CentaurHauls") == 0)
745 print_via_padlock_info();
747 /* Avoid ugly blank lines: only print newline when we have to. */
748 if (*cpu_vendor || cpu_id)
749 kprintf("\n");
751 #endif
752 if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
753 strcmp(cpu_vendor, "TransmetaCPU") == 0) {
754 setup_tmx86_longrun();
757 for (i = 0; i < additional_cpu_info_count; ++i) {
758 kprintf(" %s\n", additional_cpu_info_ary[i]);
761 if (!bootverbose)
762 return;
764 if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
765 print_AMD_info();
766 else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
767 strcmp(cpu_vendor, "TransmetaCPU") == 0)
768 print_transmeta_info();
770 #ifdef I686_CPU
772 * XXX - Do PPro CPUID level=2 stuff here?
774 * No, but maybe in a print_Intel_info() function called from here.
776 #endif
779 void
780 panicifcpuunsupported(void)
783 #if !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
784 #error This kernel is not configured for one of the supported CPUs
785 #endif
787 * Now that we have told the user what they have,
788 * let them know if that machine type isn't configured.
790 switch (cpu_class) {
792 * A 286 and 386 should not make it this far, anyway.
794 case CPUCLASS_286:
795 case CPUCLASS_386:
796 #if !defined(I486_CPU)
797 case CPUCLASS_486:
798 #endif
799 #if !defined(I586_CPU)
800 case CPUCLASS_586:
801 #endif
802 #if !defined(I686_CPU)
803 case CPUCLASS_686:
804 #endif
805 panic("CPU class not configured");
806 default:
807 break;
812 static volatile u_int trap_by_rdmsr;
815 * Special exception 6 handler.
816 * The rdmsr instruction generates invalid opcodes fault on 486-class
817 * Cyrix CPU. Stacked eip register points the rdmsr instruction in the
818 * function identblue() when this handler is called. Stacked eip should
819 * be advanced.
821 inthand_t bluetrap6;
823 __asm(
824 " .text \n"
825 " .p2align 2,0x90 \n"
826 " .type " __XSTRING(CNAME(bluetrap6)) ",@function \n"
827 __XSTRING(CNAME(bluetrap6)) ": \n"
828 " ss \n"
829 " movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
830 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
831 " iret \n"
835 * Special exception 13 handler.
836 * Accessing non-existent MSR generates general protection fault.
838 inthand_t bluetrap13;
840 __asm(
841 " .text \n"
842 " .p2align 2,0x90 \n"
843 " .type " __XSTRING(CNAME(bluetrap13)) ",@function \n"
844 __XSTRING(CNAME(bluetrap13)) ": \n"
845 " ss \n"
846 " movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
847 " popl %eax # discard errorcode. \n"
848 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
849 " iret \n"
853 * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not
854 * support cpuid instruction. This function should be called after
855 * loading interrupt descriptor table register.
857 * I don't like this method that handles fault, but I couldn't get
858 * information for any other methods. Does blue giant know?
860 static int
861 identblue(void)
864 trap_by_rdmsr = 0;
867 * Cyrix 486-class CPU does not support rdmsr instruction.
868 * The rdmsr instruction generates invalid opcode fault, and exception
869 * will be trapped by bluetrap6() on Cyrix 486-class CPU. The
870 * bluetrap6() set the magic number to trap_by_rdmsr.
872 setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
875 * Certain BIOS disables cpuid instruction of Cyrix 6x86MX CPU.
876 * In this case, rdmsr generates general protection fault, and
877 * exception will be trapped by bluetrap13().
879 setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
881 rdmsr(0x1002); /* Cyrix CPU generates fault. */
883 if (trap_by_rdmsr == 0xa8c1d)
884 return IDENTBLUE_CYRIX486;
885 else if (trap_by_rdmsr == 0xa89c4)
886 return IDENTBLUE_CYRIXM2;
887 return IDENTBLUE_IBMCPU;
892 * identifycyrix() set lower 16 bits of cyrix_did as follows:
894 * F E D C B A 9 8 7 6 5 4 3 2 1 0
895 * +-------+-------+---------------+
896 * | SID | RID | Device ID |
897 * | (DIR 1) | (DIR 0) |
898 * +-------+-------+---------------+
900 static void
901 identifycyrix(void)
903 int ccr2_test = 0, dir_test = 0;
904 u_char ccr2, ccr3;
906 mpintr_lock();
908 ccr2 = read_cyrix_reg(CCR2);
909 write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW);
910 read_cyrix_reg(CCR2);
911 if (read_cyrix_reg(CCR2) != ccr2)
912 ccr2_test = 1;
913 write_cyrix_reg(CCR2, ccr2);
915 ccr3 = read_cyrix_reg(CCR3);
916 write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3);
917 read_cyrix_reg(CCR3);
918 if (read_cyrix_reg(CCR3) != ccr3)
919 dir_test = 1; /* CPU supports DIRs. */
920 write_cyrix_reg(CCR3, ccr3);
922 if (dir_test) {
923 /* Device ID registers are available. */
924 cyrix_did = read_cyrix_reg(DIR1) << 8;
925 cyrix_did += read_cyrix_reg(DIR0);
926 } else if (ccr2_test)
927 cyrix_did = 0x0010; /* 486S A-step */
928 else
929 cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */
931 mpintr_unlock();
935 * Final stage of CPU identification. -- Should I check TI?
937 void
938 finishidentcpu(void)
940 int isblue = 0;
941 u_char ccr3;
942 u_int regs[4];
944 if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
945 if (cpu == CPU_486) {
947 * These conditions are equivalent to:
948 * - CPU does not support cpuid instruction.
949 * - Cyrix/IBM CPU is detected.
951 isblue = identblue();
952 if (isblue == IDENTBLUE_IBMCPU) {
953 strcpy(cpu_vendor, "IBM");
954 cpu = CPU_BLUE;
955 return;
958 switch (cpu_id & 0xf00) {
959 case 0x600:
961 * Cyrix's datasheet does not describe DIRs.
962 * Therefor, I assume it does not have them
963 * and use the result of the cpuid instruction.
964 * XXX they seem to have it for now at least. -Peter
966 identifycyrix();
967 cpu = CPU_M2;
968 break;
969 default:
970 identifycyrix();
972 * This routine contains a trick.
973 * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now.
975 switch (cyrix_did & 0x00f0) {
976 case 0x00:
977 case 0xf0:
978 cpu = CPU_486DLC;
979 break;
980 case 0x10:
981 cpu = CPU_CY486DX;
982 break;
983 case 0x20:
984 if ((cyrix_did & 0x000f) < 8)
985 cpu = CPU_M1;
986 else
987 cpu = CPU_M1SC;
988 break;
989 case 0x30:
990 cpu = CPU_M1;
991 break;
992 case 0x40:
993 /* MediaGX CPU */
994 cpu = CPU_M1SC;
995 break;
996 default:
997 /* M2 and later CPUs are treated as M2. */
998 cpu = CPU_M2;
1001 * enable cpuid instruction.
1003 ccr3 = read_cyrix_reg(CCR3);
1004 write_cyrix_reg(CCR3, CCR3_MAPEN0);
1005 write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID);
1006 write_cyrix_reg(CCR3, ccr3);
1008 do_cpuid(0, regs);
1009 cpu_high = regs[0]; /* eax */
1010 do_cpuid(1, regs);
1011 cpu_id = regs[0]; /* eax */
1012 cpu_feature = regs[3]; /* edx */
1013 break;
1016 } else if (cpu == CPU_486 && *cpu_vendor == '\0') {
1018 * There are BlueLightning CPUs that do not change
1019 * undefined flags by dividing 5 by 2. In this case,
1020 * the CPU identification routine in locore.s leaves
1021 * cpu_vendor null string and puts CPU_486 into the
1022 * cpu.
1024 isblue = identblue();
1025 if (isblue == IDENTBLUE_IBMCPU) {
1026 strcpy(cpu_vendor, "IBM");
1027 cpu = CPU_BLUE;
1028 return;
1033 static void
1034 print_AMD_assoc(int i)
1036 if (i == 255)
1037 kprintf(", fully associative\n");
1038 else
1039 kprintf(", %d-way associative\n", i);
1043 * #31116 Rev 3.06 section 3.9
1044 * CPUID Fn8000_0006 L2/L3 Cache and L2 TLB Identifiers
1046 static void
1047 print_AMD_L2L3_assoc(int i)
1049 static const char *assoc_str[] = {
1050 [0x0] = "disabled",
1051 [0x1] = "direct mapped",
1052 [0x2] = "2-way associative",
1053 [0x4] = "4-way associative",
1054 [0x6] = "8-way associative",
1055 [0x8] = "16-way associative",
1056 [0xa] = "32-way associative",
1057 [0xb] = "48-way associative",
1058 [0xc] = "64-way associative",
1059 [0xd] = "96-way associative",
1060 [0xe] = "128-way associative",
1061 [0xf] = "fully associative"
1064 i &= 0xf;
1065 if (assoc_str[i] == NULL)
1066 kprintf(", unknown associative\n");
1067 else
1068 kprintf(", %s\n", assoc_str[i]);
1071 static void
1072 print_AMD_info(void)
1074 quad_t amd_whcr;
1076 if (cpu_exthigh >= 0x80000005) {
1077 u_int regs[4];
1079 do_cpuid(0x80000005, regs);
1080 kprintf("Data TLB: %d entries", (regs[1] >> 16) & 0xff);
1081 print_AMD_assoc(regs[1] >> 24);
1082 kprintf("Instruction TLB: %d entries", regs[1] & 0xff);
1083 print_AMD_assoc((regs[1] >> 8) & 0xff);
1084 kprintf("L1 data cache: %d kbytes", regs[2] >> 24);
1085 kprintf(", %d bytes/line", regs[2] & 0xff);
1086 kprintf(", %d lines/tag", (regs[2] >> 8) & 0xff);
1087 print_AMD_assoc((regs[2] >> 16) & 0xff);
1088 kprintf("L1 instruction cache: %d kbytes", regs[3] >> 24);
1089 kprintf(", %d bytes/line", regs[3] & 0xff);
1090 kprintf(", %d lines/tag", (regs[3] >> 8) & 0xff);
1091 print_AMD_assoc((regs[3] >> 16) & 0xff);
1092 if (cpu_exthigh >= 0x80000006) { /* K6-III, or later */
1093 do_cpuid(0x80000006, regs);
1095 * Report right L2 cache size on Duron rev. A0.
1097 if ((cpu_id & 0xFF0) == 0x630)
1098 kprintf("L2 internal cache: 64 kbytes");
1099 else
1100 kprintf("L2 internal cache: %d kbytes",
1101 regs[2] >> 16);
1103 kprintf(", %d bytes/line", regs[2] & 0xff);
1104 kprintf(", %d lines/tag", (regs[2] >> 8) & 0x0f);
1105 print_AMD_L2L3_assoc((regs[2] >> 12) & 0x0f);
1108 * #31116 Rev 3.06 section 2.16.2:
1109 * ... If EDX[31:16] is not zero then the processor
1110 * includes an L3. ...
1112 if ((regs[3] & 0xffff0000) != 0) {
1113 kprintf("L3 shared cache: %d kbytes",
1114 (regs[3] >> 18) * 512);
1115 kprintf(", %d bytes/line", regs[3] & 0xff);
1116 kprintf(", %d lines/tag", (regs[3] >> 8) & 0x0f);
1117 print_AMD_L2L3_assoc((regs[3] >> 12) & 0x0f);
1121 if (((cpu_id & 0xf00) == 0x500)
1122 && (((cpu_id & 0x0f0) > 0x80)
1123 || (((cpu_id & 0x0f0) == 0x80)
1124 && (cpu_id & 0x00f) > 0x07))) {
1125 /* K6-2(new core [Stepping 8-F]), K6-III or later */
1126 amd_whcr = rdmsr(0xc0000082);
1127 if (!(amd_whcr & (0x3ff << 22))) {
1128 kprintf("Write Allocate Disable\n");
1129 } else {
1130 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1131 (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4);
1132 kprintf("Write Allocate 15-16M bytes: %s\n",
1133 (amd_whcr & (1 << 16)) ? "Enable" : "Disable");
1135 } else if (((cpu_id & 0xf00) == 0x500)
1136 && ((cpu_id & 0x0f0) > 0x50)) {
1137 /* K6, K6-2(old core) */
1138 amd_whcr = rdmsr(0xc0000082);
1139 if (!(amd_whcr & (0x7f << 1))) {
1140 kprintf("Write Allocate Disable\n");
1141 } else {
1142 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1143 (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4);
1144 kprintf("Write Allocate 15-16M bytes: %s\n",
1145 (amd_whcr & 0x0001) ? "Enable" : "Disable");
1146 kprintf("Hardware Write Allocate Control: %s\n",
1147 (amd_whcr & 0x0100) ? "Enable" : "Disable");
1152 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1153 static void
1154 print_AMD_features(void)
1156 u_int regs[4];
1159 * Values taken from AMD Processor Recognition
1160 * http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf
1162 do_cpuid(0x80000001, regs);
1163 kprintf("\n AMD Features=0x%b", regs[3] &~ cpu_feature,
1164 "\020" /* in hex */
1165 "\001FPU" /* Integral FPU */
1166 "\002VME" /* Extended VM86 mode support */
1167 "\003DE" /* Debug extensions */
1168 "\004PSE" /* 4MByte page tables */
1169 "\005TSC" /* Timestamp counter */
1170 "\006MSR" /* Machine specific registers */
1171 "\007PAE" /* Physical address extension */
1172 "\010MCE" /* Machine Check support */
1173 "\011CX8" /* CMPEXCH8 instruction */
1174 "\012APIC" /* SMP local APIC */
1175 "\013<b10>"
1176 "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */
1177 "\015MTRR" /* Memory Type Range Registers */
1178 "\016PGE" /* PG_G (global bit) support */
1179 "\017MCA" /* Machine Check Architecture */
1180 "\020ICMOV" /* CMOV instruction */
1181 "\021PAT" /* Page attributes table */
1182 "\022PGE36" /* 36 bit address space support */
1183 "\023RSVD" /* Reserved, unknown */
1184 "\024MP" /* Multiprocessor Capable */
1185 "\025NX" /* No-execute page protection */
1186 "\026<b21>"
1187 "\027AMIE" /* AMD MMX Instruction Extensions */
1188 "\030MMX"
1189 "\031FXSAVE" /* FXSAVE/FXRSTOR */
1190 "\032<b25>"
1191 "\033<b26>"
1192 "\034RDTSCP" /* RDTSCP instruction */
1193 "\035<b28>"
1194 "\036LM" /* Long mode */
1195 "\037DSP" /* AMD 3DNow! Instruction Extensions */
1196 "\0403DNow!"
1199 #endif
1202 * Transmeta Crusoe LongRun Support by Tamotsu Hattori.
1205 #define MSR_TMx86_LONGRUN 0x80868010
1206 #define MSR_TMx86_LONGRUN_FLAGS 0x80868011
1208 #define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f)
1209 #define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
1210 #define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y))
1212 #define LONGRUN_MODE_MINFREQUENCY 0x00
1213 #define LONGRUN_MODE_ECONOMY 0x01
1214 #define LONGRUN_MODE_PERFORMANCE 0x02
1215 #define LONGRUN_MODE_MAXFREQUENCY 0x03
1216 #define LONGRUN_MODE_UNKNOWN 0x04
1217 #define LONGRUN_MODE_MAX 0x04
1219 union msrinfo {
1220 u_int64_t msr;
1221 u_int32_t regs[2];
1224 u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
1225 /* MSR low, MSR high, flags bit0 */
1226 { 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */
1227 { 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */
1228 { 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */
1229 { 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */
1232 static u_int
1233 tmx86_get_longrun_mode(void)
1235 union msrinfo msrinfo;
1236 u_int low, high, flags, mode;
1238 mpintr_lock();
1240 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1241 low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
1242 high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
1243 flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
1245 for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
1246 if (low == longrun_modes[mode][0] &&
1247 high == longrun_modes[mode][1] &&
1248 flags == longrun_modes[mode][2]) {
1249 goto out;
1252 mode = LONGRUN_MODE_UNKNOWN;
1253 out:
1254 mpintr_unlock();
1255 return (mode);
1258 static u_int
1259 tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage)
1261 u_int regs[4];
1263 mpintr_lock();
1265 do_cpuid(0x80860007, regs);
1266 *frequency = regs[0];
1267 *voltage = regs[1];
1268 *percentage = regs[2];
1270 mpintr_unlock();
1271 return (1);
1274 static u_int
1275 tmx86_set_longrun_mode(u_int mode)
1277 union msrinfo msrinfo;
1279 if (mode >= LONGRUN_MODE_UNKNOWN) {
1280 return (0);
1283 mpintr_lock();
1285 /* Write LongRun mode values to Model Specific Register. */
1286 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1287 msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
1288 longrun_modes[mode][0]);
1289 msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
1290 longrun_modes[mode][1]);
1291 wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
1293 /* Write LongRun mode flags to Model Specific Register. */
1294 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
1295 msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
1296 wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
1298 mpintr_unlock();
1299 return (1);
1302 static u_int crusoe_longrun;
1303 static u_int crusoe_frequency;
1304 static u_int crusoe_voltage;
1305 static u_int crusoe_percentage;
1306 static struct sysctl_ctx_list crusoe_sysctl_ctx;
1307 static struct sysctl_oid *crusoe_sysctl_tree;
1309 static int
1310 tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS)
1312 u_int mode;
1313 int error;
1315 crusoe_longrun = tmx86_get_longrun_mode();
1316 mode = crusoe_longrun;
1317 error = sysctl_handle_int(oidp, &mode, 0, req);
1318 if (error || !req->newptr) {
1319 return (error);
1321 if (mode >= LONGRUN_MODE_UNKNOWN) {
1322 error = EINVAL;
1323 return (error);
1325 if (crusoe_longrun != mode) {
1326 crusoe_longrun = mode;
1327 tmx86_set_longrun_mode(crusoe_longrun);
1330 return (error);
1333 static int
1334 tmx86_status_sysctl(SYSCTL_HANDLER_ARGS)
1336 u_int val;
1337 int error;
1339 tmx86_get_longrun_status(&crusoe_frequency,
1340 &crusoe_voltage, &crusoe_percentage);
1341 val = *(u_int *)oidp->oid_arg1;
1342 error = sysctl_handle_int(oidp, &val, 0, req);
1343 return (error);
1346 static void
1347 setup_tmx86_longrun(void)
1349 static int done = 0;
1351 if (done)
1352 return;
1353 done++;
1355 sysctl_ctx_init(&crusoe_sysctl_ctx);
1356 crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx,
1357 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
1358 "crusoe", CTLFLAG_RD, 0,
1359 "Transmeta Crusoe LongRun support");
1360 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1361 OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW,
1362 &crusoe_longrun, 0, tmx86_longrun_sysctl, "I",
1363 "LongRun mode [0-3]");
1364 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1365 OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD,
1366 &crusoe_frequency, 0, tmx86_status_sysctl, "I",
1367 "Current frequency (MHz)");
1368 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1369 OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD,
1370 &crusoe_voltage, 0, tmx86_status_sysctl, "I",
1371 "Current voltage (mV)");
1372 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1373 OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD,
1374 &crusoe_percentage, 0, tmx86_status_sysctl, "I",
1375 "Processing performance (%)");
1378 static void
1379 print_transmeta_info(void)
1381 u_int regs[4], nreg = 0;
1383 do_cpuid(0x80860000, regs);
1384 nreg = regs[0];
1385 if (nreg >= 0x80860001) {
1386 do_cpuid(0x80860001, regs);
1387 kprintf(" Processor revision %u.%u.%u.%u\n",
1388 (regs[1] >> 24) & 0xff,
1389 (regs[1] >> 16) & 0xff,
1390 (regs[1] >> 8) & 0xff,
1391 regs[1] & 0xff);
1393 if (nreg >= 0x80860002) {
1394 do_cpuid(0x80860002, regs);
1395 kprintf(" Code Morphing Software revision %u.%u.%u-%u-%u\n",
1396 (regs[1] >> 24) & 0xff,
1397 (regs[1] >> 16) & 0xff,
1398 (regs[1] >> 8) & 0xff,
1399 regs[1] & 0xff,
1400 regs[2]);
1402 if (nreg >= 0x80860006) {
1403 char info[65];
1404 do_cpuid(0x80860003, (u_int*) &info[0]);
1405 do_cpuid(0x80860004, (u_int*) &info[16]);
1406 do_cpuid(0x80860005, (u_int*) &info[32]);
1407 do_cpuid(0x80860006, (u_int*) &info[48]);
1408 info[64] = 0;
1409 kprintf(" %s\n", info);
1412 crusoe_longrun = tmx86_get_longrun_mode();
1413 tmx86_get_longrun_status(&crusoe_frequency,
1414 &crusoe_voltage, &crusoe_percentage);
1415 kprintf(" LongRun mode: %d <%dMHz %dmV %d%%>\n", crusoe_longrun,
1416 crusoe_frequency, crusoe_voltage, crusoe_percentage);
1419 void
1420 additional_cpu_info(const char *line)
1422 int i;
1424 if ((i = additional_cpu_info_count) < MAX_ADDITIONAL_INFO) {
1425 additional_cpu_info_ary[i] = line;
1426 ++additional_cpu_info_count;
1430 static void
1431 print_via_padlock_info(void)
1433 u_int regs[4];
1435 /* Check for supported models. */
1436 switch (cpu_id & 0xff0) {
1437 case 0x690:
1438 if ((cpu_id & 0xf) < 3)
1439 return;
1440 case 0x6a0:
1441 case 0x6d0:
1442 break;
1443 default:
1444 return;
1447 do_cpuid(0xc0000000, regs);
1448 if (regs[0] >= 0xc0000001)
1449 do_cpuid(0xc0000001, regs);
1450 else
1451 return;
1453 kprintf("\n VIA Padlock Features=0x%b", regs[3],
1454 "\020"
1455 "\003RNG" /* RNG */
1456 "\007AES" /* ACE */
1457 "\011AES-CTR" /* ACE2 */
1458 "\013SHA1,SHA256" /* PHE */
1459 "\015RSA" /* PMM */