VIA CPU support: Detect and enable CPU features (RNG, ACE etc.).
[dragonfly.git] / sys / platform / pc32 / i386 / identcpu.c
blob45d05310735ce3d5b17a546f1338268320a23e06
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 print_via_padlock_info(void);
84 static void setup_tmx86_longrun(void);
85 static void print_via_padlock_info(void);
87 int cpu_class = CPUCLASS_386;
88 u_int cpu_exthigh; /* Highest arg to extended CPUID */
89 u_int cyrix_did; /* Device ID of Cyrix CPU */
90 char machine[] = MACHINE;
91 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
92 machine, 0, "Machine class");
94 static char cpu_model[128];
95 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD,
96 cpu_model, 0, "Machine model");
98 static char cpu_brand[48];
100 #define MAX_ADDITIONAL_INFO 16
102 static const char *additional_cpu_info_ary[MAX_ADDITIONAL_INFO];
103 static u_int additional_cpu_info_count;
105 #define MAX_BRAND_INDEX 23
108 * Brand ID's according to Intel document AP-485, number 241618-31, published
109 * September 2006, page 42.
111 static const char *cpu_brandtable[MAX_BRAND_INDEX + 1] = {
112 NULL, /* No brand */
113 "Intel Celeron",
114 "Intel Pentium III",
115 "Intel Pentium III Xeon",
116 "Intel Pentium III",
117 NULL, /* Unspecified */
118 "Mobile Intel Pentium III-M",
119 "Mobile Intel Celeron",
120 "Intel Pentium 4",
121 "Intel Pentium 4",
122 "Intel Celeron",
123 "Intel Xeon",
124 "Intel Xeon MP",
125 NULL, /* Unspecified */
126 "Mobile Intel Pentium 4-M",
127 "Mobile Intel Celeron",
128 NULL, /* Unspecified */
129 "Mobile Genuine Intel",
130 "Intel Celeron M",
131 "Mobile Intel Celeron",
132 "Intel Celeron",
133 "Mobile Genuine Intel",
134 "Intel Pentium M",
135 "Mobile Intel Celeron"
138 static struct cpu_nameclass i386_cpus[] = {
139 { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */
140 { "i386SX", CPUCLASS_386 }, /* CPU_386SX */
141 { "i386DX", CPUCLASS_386 }, /* CPU_386 */
142 { "i486SX", CPUCLASS_486 }, /* CPU_486SX */
143 { "i486DX", CPUCLASS_486 }, /* CPU_486 */
144 { "Pentium", CPUCLASS_586 }, /* CPU_586 */
145 { "Cyrix 486", CPUCLASS_486 }, /* CPU_486DLC */
146 { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */
147 { "Cyrix 5x86", CPUCLASS_486 }, /* CPU_M1SC */
148 { "Cyrix 6x86", CPUCLASS_486 }, /* CPU_M1 */
149 { "Blue Lightning", CPUCLASS_486 }, /* CPU_BLUE */
150 { "Cyrix 6x86MX", CPUCLASS_686 }, /* CPU_M2 */
151 { "NexGen 586", CPUCLASS_386 }, /* CPU_NX586 (XXX) */
152 { "Cyrix 486S/DX", CPUCLASS_486 }, /* CPU_CY486DX */
153 { "Pentium II", CPUCLASS_686 }, /* CPU_PII */
154 { "Pentium III", CPUCLASS_686 }, /* CPU_PIII */
155 { "Pentium 4", CPUCLASS_686 }, /* CPU_P4 */
158 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
159 int has_f00f_bug = 0; /* Initialized so that it can be patched. */
160 #endif
162 void
163 printcpuinfo(void)
165 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
166 u_int regs[4], i;
167 #endif
168 char *brand;
170 cpu_class = i386_cpus[cpu].cpu_class;
171 kprintf("CPU: ");
172 strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof (cpu_model));
174 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
175 /* Check for extended CPUID information and a processor name. */
176 if (cpu_high > 0 &&
177 (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
178 strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
179 strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
180 strcmp(cpu_vendor, "TransmetaCPU") == 0)) {
181 do_cpuid(0x80000000, regs);
182 if (regs[0] >= 0x80000000) {
183 cpu_exthigh = regs[0];
184 if (cpu_exthigh >= 0x80000004) {
185 brand = cpu_brand;
186 for (i = 0x80000002; i < 0x80000005; i++) {
187 do_cpuid(i, regs);
188 memcpy(brand, regs, sizeof(regs));
189 brand += sizeof(regs);
195 if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
196 if ((cpu_id & 0xf00) > 0x300) {
197 u_int brand_index;
199 cpu_model[0] = '\0';
201 switch (cpu_id & 0x3000) {
202 case 0x1000:
203 strcpy(cpu_model, "Overdrive ");
204 break;
205 case 0x2000:
206 strcpy(cpu_model, "Dual ");
207 break;
210 switch (cpu_id & 0xf00) {
211 case 0x400:
212 strcat(cpu_model, "i486 ");
213 /* Check the particular flavor of 486 */
214 switch (cpu_id & 0xf0) {
215 case 0x00:
216 case 0x10:
217 strcat(cpu_model, "DX");
218 break;
219 case 0x20:
220 strcat(cpu_model, "SX");
221 break;
222 case 0x30:
223 strcat(cpu_model, "DX2");
224 break;
225 case 0x40:
226 strcat(cpu_model, "SL");
227 break;
228 case 0x50:
229 strcat(cpu_model, "SX2");
230 break;
231 case 0x70:
232 strcat(cpu_model,
233 "DX2 Write-Back Enhanced");
234 break;
235 case 0x80:
236 strcat(cpu_model, "DX4");
237 break;
239 break;
240 case 0x500:
241 /* Check the particular flavor of 586 */
242 strcat(cpu_model, "Pentium");
243 switch (cpu_id & 0xf0) {
244 case 0x00:
245 strcat(cpu_model, " A-step");
246 break;
247 case 0x10:
248 strcat(cpu_model, "/P5");
249 break;
250 case 0x20:
251 strcat(cpu_model, "/P54C");
252 break;
253 case 0x30:
254 strcat(cpu_model, "/P54T Overdrive");
255 break;
256 case 0x40:
257 strcat(cpu_model, "/P55C");
258 break;
259 case 0x70:
260 strcat(cpu_model, "/P54C");
261 break;
262 case 0x80:
263 strcat(cpu_model, "/P55C (quarter-micron)");
264 break;
265 default:
266 /* nothing */
267 break;
269 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
271 * XXX - If/when Intel fixes the bug, this
272 * should also check the version of the
273 * CPU, not just that it's a Pentium.
275 has_f00f_bug = 1;
276 #endif
277 break;
278 case 0x600:
279 /* Check the particular flavor of 686 */
280 switch (cpu_id & 0xf0) {
281 case 0x00:
282 strcat(cpu_model, "Pentium Pro A-step");
283 break;
284 case 0x10:
285 strcat(cpu_model, "Pentium Pro");
286 break;
287 case 0x30:
288 case 0x50:
289 case 0x60:
290 strcat(cpu_model,
291 "Pentium II/Pentium II Xeon/Celeron");
292 cpu = CPU_PII;
293 break;
294 case 0x70:
295 case 0x80:
296 case 0xa0:
297 case 0xb0:
298 strcat(cpu_model,
299 "Pentium III/Pentium III Xeon/Celeron");
300 cpu = CPU_PIII;
301 break;
302 default:
303 strcat(cpu_model, "Unknown 80686");
304 break;
306 break;
307 case 0xf00:
308 strcat(cpu_model, "Pentium 4");
309 cpu = CPU_P4;
310 break;
311 default:
312 strcat(cpu_model, "unknown");
313 break;
317 * If we didn't get a brand name from the extended
318 * CPUID, try to look it up in the brand table.
320 if (cpu_high > 0 && *cpu_brand == '\0') {
321 brand_index = cpu_procinfo & CPUID_BRAND_INDEX;
322 if (brand_index <= MAX_BRAND_INDEX &&
323 cpu_brandtable[brand_index] != NULL)
324 strcpy(cpu_brand,
325 cpu_brandtable[brand_index]);
328 } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
330 * Values taken from AMD Processor Recognition
331 * http://www.amd.com/K6/k6docs/pdf/20734g.pdf
332 * (also describes ``Features'' encodings.
334 strcpy(cpu_model, "AMD ");
335 switch (cpu_id & 0xFF0) {
336 case 0x410:
337 strcat(cpu_model, "Standard Am486DX");
338 break;
339 case 0x430:
340 strcat(cpu_model, "Enhanced Am486DX2 Write-Through");
341 break;
342 case 0x470:
343 strcat(cpu_model, "Enhanced Am486DX2 Write-Back");
344 break;
345 case 0x480:
346 strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Through");
347 break;
348 case 0x490:
349 strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Back");
350 break;
351 case 0x4E0:
352 strcat(cpu_model, "Am5x86 Write-Through");
353 break;
354 case 0x4F0:
355 strcat(cpu_model, "Am5x86 Write-Back");
356 break;
357 case 0x500:
358 strcat(cpu_model, "K5 model 0");
359 tsc_is_broken = 1;
360 break;
361 case 0x510:
362 strcat(cpu_model, "K5 model 1");
363 break;
364 case 0x520:
365 strcat(cpu_model, "K5 PR166 (model 2)");
366 break;
367 case 0x530:
368 strcat(cpu_model, "K5 PR200 (model 3)");
369 break;
370 case 0x560:
371 strcat(cpu_model, "K6");
372 break;
373 case 0x570:
374 strcat(cpu_model, "K6 266 (model 1)");
375 break;
376 case 0x580:
377 strcat(cpu_model, "K6-2");
378 break;
379 case 0x590:
380 strcat(cpu_model, "K6-III");
381 break;
382 default:
383 strcat(cpu_model, "Unknown");
384 break;
386 #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
387 if ((cpu_id & 0xf00) == 0x500) {
388 if (((cpu_id & 0x0f0) > 0)
389 && ((cpu_id & 0x0f0) < 0x60)
390 && ((cpu_id & 0x00f) > 3))
391 enable_K5_wt_alloc();
392 else if (((cpu_id & 0x0f0) > 0x80)
393 || (((cpu_id & 0x0f0) == 0x80)
394 && (cpu_id & 0x00f) > 0x07))
395 enable_K6_2_wt_alloc();
396 else if ((cpu_id & 0x0f0) > 0x50)
397 enable_K6_wt_alloc();
399 #endif
400 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
401 strcpy(cpu_model, "Cyrix ");
402 switch (cpu_id & 0xff0) {
403 case 0x440:
404 strcat(cpu_model, "MediaGX");
405 break;
406 case 0x520:
407 strcat(cpu_model, "6x86");
408 break;
409 case 0x540:
410 cpu_class = CPUCLASS_586;
411 strcat(cpu_model, "GXm");
412 break;
413 case 0x600:
414 strcat(cpu_model, "6x86MX");
415 break;
416 default:
418 * Even though CPU supports the cpuid
419 * instruction, it can be disabled.
420 * Therefore, this routine supports all Cyrix
421 * CPUs.
423 switch (cyrix_did & 0xf0) {
424 case 0x00:
425 switch (cyrix_did & 0x0f) {
426 case 0x00:
427 strcat(cpu_model, "486SLC");
428 break;
429 case 0x01:
430 strcat(cpu_model, "486DLC");
431 break;
432 case 0x02:
433 strcat(cpu_model, "486SLC2");
434 break;
435 case 0x03:
436 strcat(cpu_model, "486DLC2");
437 break;
438 case 0x04:
439 strcat(cpu_model, "486SRx");
440 break;
441 case 0x05:
442 strcat(cpu_model, "486DRx");
443 break;
444 case 0x06:
445 strcat(cpu_model, "486SRx2");
446 break;
447 case 0x07:
448 strcat(cpu_model, "486DRx2");
449 break;
450 case 0x08:
451 strcat(cpu_model, "486SRu");
452 break;
453 case 0x09:
454 strcat(cpu_model, "486DRu");
455 break;
456 case 0x0a:
457 strcat(cpu_model, "486SRu2");
458 break;
459 case 0x0b:
460 strcat(cpu_model, "486DRu2");
461 break;
462 default:
463 strcat(cpu_model, "Unknown");
464 break;
466 break;
467 case 0x10:
468 switch (cyrix_did & 0x0f) {
469 case 0x00:
470 strcat(cpu_model, "486S");
471 break;
472 case 0x01:
473 strcat(cpu_model, "486S2");
474 break;
475 case 0x02:
476 strcat(cpu_model, "486Se");
477 break;
478 case 0x03:
479 strcat(cpu_model, "486S2e");
480 break;
481 case 0x0a:
482 strcat(cpu_model, "486DX");
483 break;
484 case 0x0b:
485 strcat(cpu_model, "486DX2");
486 break;
487 case 0x0f:
488 strcat(cpu_model, "486DX4");
489 break;
490 default:
491 strcat(cpu_model, "Unknown");
492 break;
494 break;
495 case 0x20:
496 if ((cyrix_did & 0x0f) < 8)
497 strcat(cpu_model, "6x86"); /* Where did you get it? */
498 else
499 strcat(cpu_model, "5x86");
500 break;
501 case 0x30:
502 strcat(cpu_model, "6x86");
503 break;
504 case 0x40:
505 if ((cyrix_did & 0xf000) == 0x3000) {
506 cpu_class = CPUCLASS_586;
507 strcat(cpu_model, "GXm");
508 } else
509 strcat(cpu_model, "MediaGX");
510 break;
511 case 0x50:
512 strcat(cpu_model, "6x86MX");
513 break;
514 case 0xf0:
515 switch (cyrix_did & 0x0f) {
516 case 0x0d:
517 strcat(cpu_model, "Overdrive CPU");
518 break;
519 case 0x0e:
520 strcpy(cpu_model, "Texas Instruments 486SXL");
521 break;
522 case 0x0f:
523 strcat(cpu_model, "486SLC/DLC");
524 break;
525 default:
526 strcat(cpu_model, "Unknown");
527 break;
529 break;
530 default:
531 strcat(cpu_model, "Unknown");
532 break;
534 break;
536 } else if (strcmp(cpu_vendor, "RiseRiseRise") == 0) {
537 strcpy(cpu_model, "Rise ");
538 switch (cpu_id & 0xff0) {
539 case 0x500:
540 strcat(cpu_model, "mP6");
541 break;
542 default:
543 strcat(cpu_model, "Unknown");
545 } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) {
546 switch (cpu_id & 0xff0) {
547 case 0x540:
548 strcpy(cpu_model, "IDT WinChip C6");
549 tsc_is_broken = 1;
550 break;
551 case 0x580:
552 strcpy(cpu_model, "IDT WinChip 2");
553 break;
554 case 0x660:
555 strcpy(cpu_model, "VIA C3 Samuel");
556 break;
557 case 0x670:
558 if (cpu_id & 0x8)
559 strcpy(cpu_model, "VIA C3 Ezra");
560 else
561 strcpy(cpu_model, "VIA C3 Samuel 2");
562 break;
563 case 0x680:
564 strcpy(cpu_model, "VIA C3 Ezra-T");
565 break;
566 case 0x690:
567 strcpy(cpu_model, "VIA C3 Nehemiah");
568 break;
569 case 0x6a0:
570 case 0x6d0:
571 strcpy(cpu_model, "VIA C7 Esther");
572 break;
573 case 0x6f0:
574 strcpy(cpu_model, "VIA Nano");
575 break;
576 default:
577 strcpy(cpu_model, "VIA/IDT Unknown");
579 } else if (strcmp(cpu_vendor, "IBM") == 0) {
580 strcpy(cpu_model, "Blue Lightning CPU");
584 * Replace cpu_model with cpu_brand minus leading spaces if
585 * we have one.
587 brand = cpu_brand;
588 while (*brand == ' ')
589 ++brand;
590 if (*brand != '\0')
591 strcpy(cpu_model, brand);
593 #endif
595 kprintf("%s (", cpu_model);
596 switch(cpu_class) {
597 case CPUCLASS_286:
598 kprintf("286");
599 break;
600 case CPUCLASS_386:
601 kprintf("386");
602 break;
603 #if defined(I486_CPU)
604 case CPUCLASS_486:
605 kprintf("486");
606 /* bzero = i486_bzero; */
607 break;
608 #endif
609 #if defined(I586_CPU)
610 case CPUCLASS_586:
611 kprintf("%lld.%02lld-MHz ",
612 (tsc_frequency + 4999LL) / 1000000LL,
613 ((tsc_frequency + 4999LL) / 10000LL) % 100LL);
614 kprintf("586");
615 break;
616 #endif
617 #if defined(I686_CPU)
618 case CPUCLASS_686:
619 kprintf("%lld.%02lld-MHz ",
620 (tsc_frequency + 4999LL) / 1000000LL,
621 ((tsc_frequency + 4999LL) / 10000LL) % 100LL);
622 kprintf("686");
623 break;
624 #endif
625 default:
626 kprintf("Unknown"); /* will panic below... */
628 kprintf("-class CPU)\n");
629 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
630 if(*cpu_vendor)
631 kprintf(" Origin = \"%s\"",cpu_vendor);
632 if(cpu_id)
633 kprintf(" Id = 0x%x", cpu_id);
635 if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
636 strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
637 strcmp(cpu_vendor, "RiseRiseRise") == 0 ||
638 strcmp(cpu_vendor, "CentaurHauls") == 0 ||
639 ((strcmp(cpu_vendor, "CyrixInstead") == 0) &&
640 ((cpu_id & 0xf00) > 0x500))) {
641 kprintf(" Stepping = %u", cpu_id & 0xf);
642 if (strcmp(cpu_vendor, "CyrixInstead") == 0)
643 kprintf(" DIR=0x%04x", cyrix_did);
644 if (cpu_high > 0) {
646 * Here we should probably set up flags indicating
647 * whether or not various features are available.
648 * The interesting ones are probably VME, PSE, PAE,
649 * and PGE. The code already assumes without bothering
650 * to check that all CPUs >= Pentium have a TSC and
651 * MSRs.
653 kprintf("\n Features=0x%b", cpu_feature,
654 "\020"
655 "\001FPU" /* Integral FPU */
656 "\002VME" /* Extended VM86 mode support */
657 "\003DE" /* Debugging Extensions (CR4.DE) */
658 "\004PSE" /* 4MByte page tables */
659 "\005TSC" /* Timestamp counter */
660 "\006MSR" /* Machine specific registers */
661 "\007PAE" /* Physical address extension */
662 "\010MCE" /* Machine Check support */
663 "\011CX8" /* CMPEXCH8 instruction */
664 "\012APIC" /* SMP local APIC */
665 "\013oldMTRR" /* Previous implementation of MTRR */
666 "\014SEP" /* Fast System Call */
667 "\015MTRR" /* Memory Type Range Registers */
668 "\016PGE" /* PG_G (global bit) support */
669 "\017MCA" /* Machine Check Architecture */
670 "\020CMOV" /* CMOV instruction */
671 "\021PAT" /* Page attributes table */
672 "\022PSE36" /* 36 bit address space support */
673 "\023PN" /* Processor Serial number */
674 "\024CLFLUSH" /* Has the CLFLUSH instruction */
675 "\025<b20>"
676 "\026DTS" /* Debug Trace Store */
677 "\027ACPI" /* ACPI support */
678 "\030MMX" /* MMX instructions */
679 "\031FXSR" /* FXSAVE/FXRSTOR */
680 "\032SSE" /* Streaming SIMD Extensions */
681 "\033SSE2" /* Streaming SIMD Extensions #2 */
682 "\034SS" /* Self snoop */
683 "\035HTT" /* Hyperthreading (see EBX bit 16-23) */
684 "\036TM" /* Thermal Monitor clock slowdown */
685 "\037IA64" /* CPU can execute IA64 instructions */
686 "\040PBE" /* Pending Break Enable */
689 if (cpu_feature2 != 0) {
690 kprintf("\n Features2=0x%b", cpu_feature2,
691 "\020"
692 "\001SSE3" /* SSE3 */
693 "\002<b1>"
694 "\003DTES64" /* 64-bit Debug Trace */
695 "\004MON" /* MONITOR/MWAIT Instructions */
696 "\005DS_CPL" /* CPL Qualified Debug Store */
697 "\006VMX" /* Virtual Machine Extensions */
698 "\007SMX" /* Safer Mode Extensions */
699 "\010EST" /* Enhanced SpeedStep */
700 "\011TM2" /* Thermal Monitor 2 */
701 "\012SSSE3" /* SSSE3 */
702 "\013CNXT-ID" /* L1 context ID available */
703 "\014<b11>"
704 "\015<b12>"
705 "\016CX16" /* CMPXCHG16B Instruction */
706 "\017xTPR" /* Send Task Priority Messages*/
707 "\020PDCM" /* Perf/Debug Capability MSR */
708 "\021<b16>"
709 "\022<b17>"
710 "\023DCA" /* Direct Cache Access */
711 "\024SSE4.1"
712 "\025SSE4.2"
713 "\026x2APIC" /* xAPIC Extensions */
714 "\027MOVBE" /* MOVBE instruction */
715 "\030POPCNT"
716 "\031<b24>"
717 "\032<b25>"
718 "\033XSAVE"
719 "\034OSXSAVE"
720 "\035<b28>"
721 "\036<b29>"
722 "\037<b30>"
723 "\040<b31>"
726 if (strcmp(cpu_vendor, "CentaurHauls") == 0)
727 print_via_padlock_info();
729 if (strcmp(cpu_vendor, "CentaurHauls") == 0)
730 print_via_padlock_info();
733 * If this CPU supports hyperthreading then mention
734 * the number of logical CPU's it contains.
736 if (cpu_feature & CPUID_HTT &&
737 (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1)
738 kprintf("\n Hyperthreading: %d logical CPUs",
739 (cpu_procinfo & CPUID_HTT_CORES) >> 16);
741 if (strcmp(cpu_vendor, "AuthenticAMD") == 0 &&
742 cpu_exthigh >= 0x80000001)
743 print_AMD_features();
744 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
745 kprintf(" DIR=0x%04x", cyrix_did);
746 kprintf(" Stepping=%u", (cyrix_did & 0xf000) >> 12);
747 kprintf(" Revision=%u", (cyrix_did & 0x0f00) >> 8);
748 #ifndef CYRIX_CACHE_REALLY_WORKS
749 if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700)
750 kprintf("\n CPU cache: write-through mode");
751 #endif
753 /* Avoid ugly blank lines: only print newline when we have to. */
754 if (*cpu_vendor || cpu_id)
755 kprintf("\n");
757 #endif
758 if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
759 strcmp(cpu_vendor, "TransmetaCPU") == 0) {
760 setup_tmx86_longrun();
763 for (i = 0; i < additional_cpu_info_count; ++i) {
764 kprintf(" %s\n", additional_cpu_info_ary[i]);
767 if (!bootverbose)
768 return;
770 if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
771 print_AMD_info();
772 else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
773 strcmp(cpu_vendor, "TransmetaCPU") == 0)
774 print_transmeta_info();
776 #ifdef I686_CPU
778 * XXX - Do PPro CPUID level=2 stuff here?
780 * No, but maybe in a print_Intel_info() function called from here.
782 #endif
785 void
786 panicifcpuunsupported(void)
789 #if !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
790 #error This kernel is not configured for one of the supported CPUs
791 #endif
793 * Now that we have told the user what they have,
794 * let them know if that machine type isn't configured.
796 switch (cpu_class) {
798 * A 286 and 386 should not make it this far, anyway.
800 case CPUCLASS_286:
801 case CPUCLASS_386:
802 #if !defined(I486_CPU)
803 case CPUCLASS_486:
804 #endif
805 #if !defined(I586_CPU)
806 case CPUCLASS_586:
807 #endif
808 #if !defined(I686_CPU)
809 case CPUCLASS_686:
810 #endif
811 panic("CPU class not configured");
812 default:
813 break;
818 static volatile u_int trap_by_rdmsr;
821 * Special exception 6 handler.
822 * The rdmsr instruction generates invalid opcodes fault on 486-class
823 * Cyrix CPU. Stacked eip register points the rdmsr instruction in the
824 * function identblue() when this handler is called. Stacked eip should
825 * be advanced.
827 inthand_t bluetrap6;
829 __asm(
830 " .text \n"
831 " .p2align 2,0x90 \n"
832 " .type " __XSTRING(CNAME(bluetrap6)) ",@function \n"
833 __XSTRING(CNAME(bluetrap6)) ": \n"
834 " ss \n"
835 " movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
836 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
837 " iret \n"
841 * Special exception 13 handler.
842 * Accessing non-existent MSR generates general protection fault.
844 inthand_t bluetrap13;
846 __asm(
847 " .text \n"
848 " .p2align 2,0x90 \n"
849 " .type " __XSTRING(CNAME(bluetrap13)) ",@function \n"
850 __XSTRING(CNAME(bluetrap13)) ": \n"
851 " ss \n"
852 " movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
853 " popl %eax # discard errorcode. \n"
854 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
855 " iret \n"
859 * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not
860 * support cpuid instruction. This function should be called after
861 * loading interrupt descriptor table register.
863 * I don't like this method that handles fault, but I couldn't get
864 * information for any other methods. Does blue giant know?
866 static int
867 identblue(void)
870 trap_by_rdmsr = 0;
873 * Cyrix 486-class CPU does not support rdmsr instruction.
874 * The rdmsr instruction generates invalid opcode fault, and exception
875 * will be trapped by bluetrap6() on Cyrix 486-class CPU. The
876 * bluetrap6() set the magic number to trap_by_rdmsr.
878 setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
881 * Certain BIOS disables cpuid instruction of Cyrix 6x86MX CPU.
882 * In this case, rdmsr generates general protection fault, and
883 * exception will be trapped by bluetrap13().
885 setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
887 rdmsr(0x1002); /* Cyrix CPU generates fault. */
889 if (trap_by_rdmsr == 0xa8c1d)
890 return IDENTBLUE_CYRIX486;
891 else if (trap_by_rdmsr == 0xa89c4)
892 return IDENTBLUE_CYRIXM2;
893 return IDENTBLUE_IBMCPU;
898 * identifycyrix() set lower 16 bits of cyrix_did as follows:
900 * F E D C B A 9 8 7 6 5 4 3 2 1 0
901 * +-------+-------+---------------+
902 * | SID | RID | Device ID |
903 * | (DIR 1) | (DIR 0) |
904 * +-------+-------+---------------+
906 static void
907 identifycyrix(void)
909 int ccr2_test = 0, dir_test = 0;
910 u_char ccr2, ccr3;
912 mpintr_lock();
914 ccr2 = read_cyrix_reg(CCR2);
915 write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW);
916 read_cyrix_reg(CCR2);
917 if (read_cyrix_reg(CCR2) != ccr2)
918 ccr2_test = 1;
919 write_cyrix_reg(CCR2, ccr2);
921 ccr3 = read_cyrix_reg(CCR3);
922 write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3);
923 read_cyrix_reg(CCR3);
924 if (read_cyrix_reg(CCR3) != ccr3)
925 dir_test = 1; /* CPU supports DIRs. */
926 write_cyrix_reg(CCR3, ccr3);
928 if (dir_test) {
929 /* Device ID registers are available. */
930 cyrix_did = read_cyrix_reg(DIR1) << 8;
931 cyrix_did += read_cyrix_reg(DIR0);
932 } else if (ccr2_test)
933 cyrix_did = 0x0010; /* 486S A-step */
934 else
935 cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */
937 mpintr_unlock();
941 * Final stage of CPU identification. -- Should I check TI?
943 void
944 finishidentcpu(void)
946 int isblue = 0;
947 u_char ccr3;
948 u_int regs[4];
950 if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
951 if (cpu == CPU_486) {
953 * These conditions are equivalent to:
954 * - CPU does not support cpuid instruction.
955 * - Cyrix/IBM CPU is detected.
957 isblue = identblue();
958 if (isblue == IDENTBLUE_IBMCPU) {
959 strcpy(cpu_vendor, "IBM");
960 cpu = CPU_BLUE;
961 return;
964 switch (cpu_id & 0xf00) {
965 case 0x600:
967 * Cyrix's datasheet does not describe DIRs.
968 * Therefor, I assume it does not have them
969 * and use the result of the cpuid instruction.
970 * XXX they seem to have it for now at least. -Peter
972 identifycyrix();
973 cpu = CPU_M2;
974 break;
975 default:
976 identifycyrix();
978 * This routine contains a trick.
979 * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now.
981 switch (cyrix_did & 0x00f0) {
982 case 0x00:
983 case 0xf0:
984 cpu = CPU_486DLC;
985 break;
986 case 0x10:
987 cpu = CPU_CY486DX;
988 break;
989 case 0x20:
990 if ((cyrix_did & 0x000f) < 8)
991 cpu = CPU_M1;
992 else
993 cpu = CPU_M1SC;
994 break;
995 case 0x30:
996 cpu = CPU_M1;
997 break;
998 case 0x40:
999 /* MediaGX CPU */
1000 cpu = CPU_M1SC;
1001 break;
1002 default:
1003 /* M2 and later CPUs are treated as M2. */
1004 cpu = CPU_M2;
1007 * enable cpuid instruction.
1009 ccr3 = read_cyrix_reg(CCR3);
1010 write_cyrix_reg(CCR3, CCR3_MAPEN0);
1011 write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID);
1012 write_cyrix_reg(CCR3, ccr3);
1014 do_cpuid(0, regs);
1015 cpu_high = regs[0]; /* eax */
1016 do_cpuid(1, regs);
1017 cpu_id = regs[0]; /* eax */
1018 cpu_feature = regs[3]; /* edx */
1019 break;
1022 } else if (cpu == CPU_486 && *cpu_vendor == '\0') {
1024 * There are BlueLightning CPUs that do not change
1025 * undefined flags by dividing 5 by 2. In this case,
1026 * the CPU identification routine in locore.s leaves
1027 * cpu_vendor null string and puts CPU_486 into the
1028 * cpu.
1030 isblue = identblue();
1031 if (isblue == IDENTBLUE_IBMCPU) {
1032 strcpy(cpu_vendor, "IBM");
1033 cpu = CPU_BLUE;
1034 return;
1039 static void
1040 print_AMD_assoc(int i)
1042 if (i == 255)
1043 kprintf(", fully associative\n");
1044 else
1045 kprintf(", %d-way associative\n", i);
1049 * #31116 Rev 3.06 section 3.9
1050 * CPUID Fn8000_0006 L2/L3 Cache and L2 TLB Identifiers
1052 static void
1053 print_AMD_L2L3_assoc(int i)
1055 static const char *assoc_str[] = {
1056 [0x0] = "disabled",
1057 [0x1] = "direct mapped",
1058 [0x2] = "2-way associative",
1059 [0x4] = "4-way associative",
1060 [0x6] = "8-way associative",
1061 [0x8] = "16-way associative",
1062 [0xa] = "32-way associative",
1063 [0xb] = "48-way associative",
1064 [0xc] = "64-way associative",
1065 [0xd] = "96-way associative",
1066 [0xe] = "128-way associative",
1067 [0xf] = "fully associative"
1070 i &= 0xf;
1071 if (assoc_str[i] == NULL)
1072 kprintf(", unknown associative\n");
1073 else
1074 kprintf(", %s\n", assoc_str[i]);
1077 static void
1078 print_AMD_info(void)
1080 quad_t amd_whcr;
1082 if (cpu_exthigh >= 0x80000005) {
1083 u_int regs[4];
1085 do_cpuid(0x80000005, regs);
1086 kprintf("Data TLB: %d entries", (regs[1] >> 16) & 0xff);
1087 print_AMD_assoc(regs[1] >> 24);
1088 kprintf("Instruction TLB: %d entries", regs[1] & 0xff);
1089 print_AMD_assoc((regs[1] >> 8) & 0xff);
1090 kprintf("L1 data cache: %d kbytes", regs[2] >> 24);
1091 kprintf(", %d bytes/line", regs[2] & 0xff);
1092 kprintf(", %d lines/tag", (regs[2] >> 8) & 0xff);
1093 print_AMD_assoc((regs[2] >> 16) & 0xff);
1094 kprintf("L1 instruction cache: %d kbytes", regs[3] >> 24);
1095 kprintf(", %d bytes/line", regs[3] & 0xff);
1096 kprintf(", %d lines/tag", (regs[3] >> 8) & 0xff);
1097 print_AMD_assoc((regs[3] >> 16) & 0xff);
1098 if (cpu_exthigh >= 0x80000006) { /* K6-III, or later */
1099 do_cpuid(0x80000006, regs);
1101 * Report right L2 cache size on Duron rev. A0.
1103 if ((cpu_id & 0xFF0) == 0x630)
1104 kprintf("L2 internal cache: 64 kbytes");
1105 else
1106 kprintf("L2 internal cache: %d kbytes",
1107 regs[2] >> 16);
1109 kprintf(", %d bytes/line", regs[2] & 0xff);
1110 kprintf(", %d lines/tag", (regs[2] >> 8) & 0x0f);
1111 print_AMD_L2L3_assoc((regs[2] >> 12) & 0x0f);
1114 * #31116 Rev 3.06 section 2.16.2:
1115 * ... If EDX[31:16] is not zero then the processor
1116 * includes an L3. ...
1118 if ((regs[3] & 0xffff0000) != 0) {
1119 kprintf("L3 shared cache: %d kbytes",
1120 (regs[3] >> 18) * 512);
1121 kprintf(", %d bytes/line", regs[3] & 0xff);
1122 kprintf(", %d lines/tag", (regs[3] >> 8) & 0x0f);
1123 print_AMD_L2L3_assoc((regs[3] >> 12) & 0x0f);
1127 if (((cpu_id & 0xf00) == 0x500)
1128 && (((cpu_id & 0x0f0) > 0x80)
1129 || (((cpu_id & 0x0f0) == 0x80)
1130 && (cpu_id & 0x00f) > 0x07))) {
1131 /* K6-2(new core [Stepping 8-F]), K6-III or later */
1132 amd_whcr = rdmsr(0xc0000082);
1133 if (!(amd_whcr & (0x3ff << 22))) {
1134 kprintf("Write Allocate Disable\n");
1135 } else {
1136 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1137 (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4);
1138 kprintf("Write Allocate 15-16M bytes: %s\n",
1139 (amd_whcr & (1 << 16)) ? "Enable" : "Disable");
1141 } else if (((cpu_id & 0xf00) == 0x500)
1142 && ((cpu_id & 0x0f0) > 0x50)) {
1143 /* K6, K6-2(old core) */
1144 amd_whcr = rdmsr(0xc0000082);
1145 if (!(amd_whcr & (0x7f << 1))) {
1146 kprintf("Write Allocate Disable\n");
1147 } else {
1148 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1149 (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4);
1150 kprintf("Write Allocate 15-16M bytes: %s\n",
1151 (amd_whcr & 0x0001) ? "Enable" : "Disable");
1152 kprintf("Hardware Write Allocate Control: %s\n",
1153 (amd_whcr & 0x0100) ? "Enable" : "Disable");
1158 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1159 static void
1160 print_AMD_features(void)
1162 u_int regs[4];
1165 * Values taken from AMD Processor Recognition
1166 * http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf
1168 do_cpuid(0x80000001, regs);
1169 kprintf("\n AMD Features=0x%b", regs[3] &~ cpu_feature,
1170 "\020" /* in hex */
1171 "\001FPU" /* Integral FPU */
1172 "\002VME" /* Extended VM86 mode support */
1173 "\003DE" /* Debug extensions */
1174 "\004PSE" /* 4MByte page tables */
1175 "\005TSC" /* Timestamp counter */
1176 "\006MSR" /* Machine specific registers */
1177 "\007PAE" /* Physical address extension */
1178 "\010MCE" /* Machine Check support */
1179 "\011CX8" /* CMPEXCH8 instruction */
1180 "\012APIC" /* SMP local APIC */
1181 "\013<b10>"
1182 "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */
1183 "\015MTRR" /* Memory Type Range Registers */
1184 "\016PGE" /* PG_G (global bit) support */
1185 "\017MCA" /* Machine Check Architecture */
1186 "\020ICMOV" /* CMOV instruction */
1187 "\021PAT" /* Page attributes table */
1188 "\022PGE36" /* 36 bit address space support */
1189 "\023RSVD" /* Reserved, unknown */
1190 "\024MP" /* Multiprocessor Capable */
1191 "\025NX" /* No-execute page protection */
1192 "\026<b21>"
1193 "\027AMIE" /* AMD MMX Instruction Extensions */
1194 "\030MMX"
1195 "\031FXSAVE" /* FXSAVE/FXRSTOR */
1196 "\032<b25>"
1197 "\033<b26>"
1198 "\034RDTSCP" /* RDTSCP instruction */
1199 "\035<b28>"
1200 "\036LM" /* Long mode */
1201 "\037DSP" /* AMD 3DNow! Instruction Extensions */
1202 "\0403DNow!"
1205 #endif
1208 * Transmeta Crusoe LongRun Support by Tamotsu Hattori.
1211 #define MSR_TMx86_LONGRUN 0x80868010
1212 #define MSR_TMx86_LONGRUN_FLAGS 0x80868011
1214 #define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f)
1215 #define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
1216 #define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y))
1218 #define LONGRUN_MODE_MINFREQUENCY 0x00
1219 #define LONGRUN_MODE_ECONOMY 0x01
1220 #define LONGRUN_MODE_PERFORMANCE 0x02
1221 #define LONGRUN_MODE_MAXFREQUENCY 0x03
1222 #define LONGRUN_MODE_UNKNOWN 0x04
1223 #define LONGRUN_MODE_MAX 0x04
1225 union msrinfo {
1226 u_int64_t msr;
1227 u_int32_t regs[2];
1230 u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
1231 /* MSR low, MSR high, flags bit0 */
1232 { 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */
1233 { 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */
1234 { 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */
1235 { 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */
1238 static u_int
1239 tmx86_get_longrun_mode(void)
1241 union msrinfo msrinfo;
1242 u_int low, high, flags, mode;
1244 mpintr_lock();
1246 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1247 low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
1248 high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
1249 flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
1251 for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
1252 if (low == longrun_modes[mode][0] &&
1253 high == longrun_modes[mode][1] &&
1254 flags == longrun_modes[mode][2]) {
1255 goto out;
1258 mode = LONGRUN_MODE_UNKNOWN;
1259 out:
1260 mpintr_unlock();
1261 return (mode);
1264 static u_int
1265 tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage)
1267 u_int regs[4];
1269 mpintr_lock();
1271 do_cpuid(0x80860007, regs);
1272 *frequency = regs[0];
1273 *voltage = regs[1];
1274 *percentage = regs[2];
1276 mpintr_unlock();
1277 return (1);
1280 static u_int
1281 tmx86_set_longrun_mode(u_int mode)
1283 union msrinfo msrinfo;
1285 if (mode >= LONGRUN_MODE_UNKNOWN) {
1286 return (0);
1289 mpintr_lock();
1291 /* Write LongRun mode values to Model Specific Register. */
1292 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1293 msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
1294 longrun_modes[mode][0]);
1295 msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
1296 longrun_modes[mode][1]);
1297 wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
1299 /* Write LongRun mode flags to Model Specific Register. */
1300 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
1301 msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
1302 wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
1304 mpintr_unlock();
1305 return (1);
1308 static u_int crusoe_longrun;
1309 static u_int crusoe_frequency;
1310 static u_int crusoe_voltage;
1311 static u_int crusoe_percentage;
1312 static struct sysctl_ctx_list crusoe_sysctl_ctx;
1313 static struct sysctl_oid *crusoe_sysctl_tree;
1315 static int
1316 tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS)
1318 u_int mode;
1319 int error;
1321 crusoe_longrun = tmx86_get_longrun_mode();
1322 mode = crusoe_longrun;
1323 error = sysctl_handle_int(oidp, &mode, 0, req);
1324 if (error || !req->newptr) {
1325 return (error);
1327 if (mode >= LONGRUN_MODE_UNKNOWN) {
1328 error = EINVAL;
1329 return (error);
1331 if (crusoe_longrun != mode) {
1332 crusoe_longrun = mode;
1333 tmx86_set_longrun_mode(crusoe_longrun);
1336 return (error);
1339 static int
1340 tmx86_status_sysctl(SYSCTL_HANDLER_ARGS)
1342 u_int val;
1343 int error;
1345 tmx86_get_longrun_status(&crusoe_frequency,
1346 &crusoe_voltage, &crusoe_percentage);
1347 val = *(u_int *)oidp->oid_arg1;
1348 error = sysctl_handle_int(oidp, &val, 0, req);
1349 return (error);
1352 static void
1353 setup_tmx86_longrun(void)
1355 static int done = 0;
1357 if (done)
1358 return;
1359 done++;
1361 sysctl_ctx_init(&crusoe_sysctl_ctx);
1362 crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx,
1363 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
1364 "crusoe", CTLFLAG_RD, 0,
1365 "Transmeta Crusoe LongRun support");
1366 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1367 OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW,
1368 &crusoe_longrun, 0, tmx86_longrun_sysctl, "I",
1369 "LongRun mode [0-3]");
1370 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1371 OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD,
1372 &crusoe_frequency, 0, tmx86_status_sysctl, "I",
1373 "Current frequency (MHz)");
1374 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1375 OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD,
1376 &crusoe_voltage, 0, tmx86_status_sysctl, "I",
1377 "Current voltage (mV)");
1378 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1379 OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD,
1380 &crusoe_percentage, 0, tmx86_status_sysctl, "I",
1381 "Processing performance (%)");
1384 static void
1385 print_transmeta_info(void)
1387 u_int regs[4], nreg = 0;
1389 do_cpuid(0x80860000, regs);
1390 nreg = regs[0];
1391 if (nreg >= 0x80860001) {
1392 do_cpuid(0x80860001, regs);
1393 kprintf(" Processor revision %u.%u.%u.%u\n",
1394 (regs[1] >> 24) & 0xff,
1395 (regs[1] >> 16) & 0xff,
1396 (regs[1] >> 8) & 0xff,
1397 regs[1] & 0xff);
1399 if (nreg >= 0x80860002) {
1400 do_cpuid(0x80860002, regs);
1401 kprintf(" Code Morphing Software revision %u.%u.%u-%u-%u\n",
1402 (regs[1] >> 24) & 0xff,
1403 (regs[1] >> 16) & 0xff,
1404 (regs[1] >> 8) & 0xff,
1405 regs[1] & 0xff,
1406 regs[2]);
1408 if (nreg >= 0x80860006) {
1409 char info[65];
1410 do_cpuid(0x80860003, (u_int*) &info[0]);
1411 do_cpuid(0x80860004, (u_int*) &info[16]);
1412 do_cpuid(0x80860005, (u_int*) &info[32]);
1413 do_cpuid(0x80860006, (u_int*) &info[48]);
1414 info[64] = 0;
1415 kprintf(" %s\n", info);
1418 crusoe_longrun = tmx86_get_longrun_mode();
1419 tmx86_get_longrun_status(&crusoe_frequency,
1420 &crusoe_voltage, &crusoe_percentage);
1421 kprintf(" LongRun mode: %d <%dMHz %dmV %d%%>\n", crusoe_longrun,
1422 crusoe_frequency, crusoe_voltage, crusoe_percentage);
1425 static void
1426 print_via_padlock_info(void)
1428 u_int regs[4];
1430 /* Check for supported models. */
1431 switch (cpu_id & 0xff0) {
1432 case 0x690:
1433 if ((cpu_id & 0xf) < 3)
1434 return;
1435 case 0x6a0:
1436 case 0x6d0:
1437 case 0x6f0:
1438 break;
1439 default:
1440 return;
1443 do_cpuid(0xc0000000, regs);
1444 if (regs[0] >= 0xc0000001)
1445 do_cpuid(0xc0000001, regs);
1446 else
1447 return;
1449 kprintf("\n VIA Padlock Features=0x%b", regs[3],
1450 "\020"
1451 "\003RNG" /* RNG */
1452 "\007AES" /* ACE */
1453 "\011AES-CTR" /* ACE2 */
1454 "\013SHA1,SHA256" /* PHE */
1455 "\015RSA" /* PMM */
1459 void
1460 additional_cpu_info(const char *line)
1462 int i;
1464 if ((i = additional_cpu_info_count) < MAX_ADDITIONAL_INFO) {
1465 additional_cpu_info_ary[i] = line;
1466 ++additional_cpu_info_count;
1470 static void
1471 print_via_padlock_info(void)
1473 u_int regs[4];
1475 /* Check for supported models. */
1476 switch (cpu_id & 0xff0) {
1477 case 0x690:
1478 if ((cpu_id & 0xf) < 3)
1479 return;
1480 case 0x6a0:
1481 case 0x6d0:
1482 case 0x6f0:
1483 break;
1484 default:
1485 return;
1488 do_cpuid(0xc0000000, regs);
1489 if (regs[0] >= 0xc0000001)
1490 do_cpuid(0xc0000001, regs);
1491 else
1492 return;
1494 kprintf("\n VIA Padlock Features=0x%b", regs[3],
1495 "\020"
1496 "\003RNG" /* RNG */
1497 "\007AES" /* ACE */
1498 "\011AES-CTR" /* ACE2 */
1499 "\013SHA1,SHA256" /* PHE */
1500 "\015RSA" /* PMM */