i386/identcpu.c: Add VIA Nano support
[dragonfly.git] / sys / platform / pc32 / i386 / identcpu.c
blob4120c4c5c14f46e315c23dea796ad39218e36ac7
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 case 0x6f0:
573 strcpy(cpu_model, "VIA Nano");
574 break;
575 default:
576 strcpy(cpu_model, "VIA/IDT Unknown");
578 } else if (strcmp(cpu_vendor, "IBM") == 0) {
579 strcpy(cpu_model, "Blue Lightning CPU");
583 * Replace cpu_model with cpu_brand minus leading spaces if
584 * we have one.
586 brand = cpu_brand;
587 while (*brand == ' ')
588 ++brand;
589 if (*brand != '\0')
590 strcpy(cpu_model, brand);
592 #endif
594 kprintf("%s (", cpu_model);
595 switch(cpu_class) {
596 case CPUCLASS_286:
597 kprintf("286");
598 break;
599 case CPUCLASS_386:
600 kprintf("386");
601 break;
602 #if defined(I486_CPU)
603 case CPUCLASS_486:
604 kprintf("486");
605 /* bzero = i486_bzero; */
606 break;
607 #endif
608 #if defined(I586_CPU)
609 case CPUCLASS_586:
610 kprintf("%lld.%02lld-MHz ",
611 (tsc_frequency + 4999LL) / 1000000LL,
612 ((tsc_frequency + 4999LL) / 10000LL) % 100LL);
613 kprintf("586");
614 break;
615 #endif
616 #if defined(I686_CPU)
617 case CPUCLASS_686:
618 kprintf("%lld.%02lld-MHz ",
619 (tsc_frequency + 4999LL) / 1000000LL,
620 ((tsc_frequency + 4999LL) / 10000LL) % 100LL);
621 kprintf("686");
622 break;
623 #endif
624 default:
625 kprintf("Unknown"); /* will panic below... */
627 kprintf("-class CPU)\n");
628 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
629 if(*cpu_vendor)
630 kprintf(" Origin = \"%s\"",cpu_vendor);
631 if(cpu_id)
632 kprintf(" Id = 0x%x", cpu_id);
634 if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
635 strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
636 strcmp(cpu_vendor, "RiseRiseRise") == 0 ||
637 strcmp(cpu_vendor, "CentaurHauls") == 0 ||
638 ((strcmp(cpu_vendor, "CyrixInstead") == 0) &&
639 ((cpu_id & 0xf00) > 0x500))) {
640 kprintf(" Stepping = %u", cpu_id & 0xf);
641 if (strcmp(cpu_vendor, "CyrixInstead") == 0)
642 kprintf(" DIR=0x%04x", cyrix_did);
643 if (cpu_high > 0) {
645 * Here we should probably set up flags indicating
646 * whether or not various features are available.
647 * The interesting ones are probably VME, PSE, PAE,
648 * and PGE. The code already assumes without bothering
649 * to check that all CPUs >= Pentium have a TSC and
650 * MSRs.
652 kprintf("\n Features=0x%b", cpu_feature,
653 "\020"
654 "\001FPU" /* Integral FPU */
655 "\002VME" /* Extended VM86 mode support */
656 "\003DE" /* Debugging Extensions (CR4.DE) */
657 "\004PSE" /* 4MByte page tables */
658 "\005TSC" /* Timestamp counter */
659 "\006MSR" /* Machine specific registers */
660 "\007PAE" /* Physical address extension */
661 "\010MCE" /* Machine Check support */
662 "\011CX8" /* CMPEXCH8 instruction */
663 "\012APIC" /* SMP local APIC */
664 "\013oldMTRR" /* Previous implementation of MTRR */
665 "\014SEP" /* Fast System Call */
666 "\015MTRR" /* Memory Type Range Registers */
667 "\016PGE" /* PG_G (global bit) support */
668 "\017MCA" /* Machine Check Architecture */
669 "\020CMOV" /* CMOV instruction */
670 "\021PAT" /* Page attributes table */
671 "\022PSE36" /* 36 bit address space support */
672 "\023PN" /* Processor Serial number */
673 "\024CLFLUSH" /* Has the CLFLUSH instruction */
674 "\025<b20>"
675 "\026DTS" /* Debug Trace Store */
676 "\027ACPI" /* ACPI support */
677 "\030MMX" /* MMX instructions */
678 "\031FXSR" /* FXSAVE/FXRSTOR */
679 "\032SSE" /* Streaming SIMD Extensions */
680 "\033SSE2" /* Streaming SIMD Extensions #2 */
681 "\034SS" /* Self snoop */
682 "\035HTT" /* Hyperthreading (see EBX bit 16-23) */
683 "\036TM" /* Thermal Monitor clock slowdown */
684 "\037IA64" /* CPU can execute IA64 instructions */
685 "\040PBE" /* Pending Break Enable */
688 if (cpu_feature2 != 0) {
689 kprintf("\n Features2=0x%b", cpu_feature2,
690 "\020"
691 "\001SSE3" /* SSE3 */
692 "\002<b1>"
693 "\003DTES64" /* 64-bit Debug Trace */
694 "\004MON" /* MONITOR/MWAIT Instructions */
695 "\005DS_CPL" /* CPL Qualified Debug Store */
696 "\006VMX" /* Virtual Machine Extensions */
697 "\007SMX" /* Safer Mode Extensions */
698 "\010EST" /* Enhanced SpeedStep */
699 "\011TM2" /* Thermal Monitor 2 */
700 "\012SSSE3" /* SSSE3 */
701 "\013CNXT-ID" /* L1 context ID available */
702 "\014<b11>"
703 "\015<b12>"
704 "\016CX16" /* CMPXCHG16B Instruction */
705 "\017xTPR" /* Send Task Priority Messages*/
706 "\020PDCM" /* Perf/Debug Capability MSR */
707 "\021<b16>"
708 "\022<b17>"
709 "\023DCA" /* Direct Cache Access */
710 "\024SSE4.1"
711 "\025SSE4.2"
712 "\026x2APIC" /* xAPIC Extensions */
713 "\027MOVBE" /* MOVBE instruction */
714 "\030POPCNT"
715 "\031<b24>"
716 "\032<b25>"
717 "\033XSAVE"
718 "\034OSXSAVE"
719 "\035<b28>"
720 "\036<b29>"
721 "\037<b30>"
722 "\040<b31>"
725 if (strcmp(cpu_vendor, "CentaurHauls") == 0)
726 print_via_padlock_info();
729 * If this CPU supports hyperthreading then mention
730 * the number of logical CPU's it contains.
732 if (cpu_feature & CPUID_HTT &&
733 (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1)
734 kprintf("\n Hyperthreading: %d logical CPUs",
735 (cpu_procinfo & CPUID_HTT_CORES) >> 16);
737 if (strcmp(cpu_vendor, "AuthenticAMD") == 0 &&
738 cpu_exthigh >= 0x80000001)
739 print_AMD_features();
740 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
741 kprintf(" DIR=0x%04x", cyrix_did);
742 kprintf(" Stepping=%u", (cyrix_did & 0xf000) >> 12);
743 kprintf(" Revision=%u", (cyrix_did & 0x0f00) >> 8);
744 #ifndef CYRIX_CACHE_REALLY_WORKS
745 if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700)
746 kprintf("\n CPU cache: write-through mode");
747 #endif
749 /* Avoid ugly blank lines: only print newline when we have to. */
750 if (*cpu_vendor || cpu_id)
751 kprintf("\n");
753 #endif
754 if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
755 strcmp(cpu_vendor, "TransmetaCPU") == 0) {
756 setup_tmx86_longrun();
759 for (i = 0; i < additional_cpu_info_count; ++i) {
760 kprintf(" %s\n", additional_cpu_info_ary[i]);
763 if (!bootverbose)
764 return;
766 if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
767 print_AMD_info();
768 else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
769 strcmp(cpu_vendor, "TransmetaCPU") == 0)
770 print_transmeta_info();
772 #ifdef I686_CPU
774 * XXX - Do PPro CPUID level=2 stuff here?
776 * No, but maybe in a print_Intel_info() function called from here.
778 #endif
781 void
782 panicifcpuunsupported(void)
785 #if !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
786 #error This kernel is not configured for one of the supported CPUs
787 #endif
789 * Now that we have told the user what they have,
790 * let them know if that machine type isn't configured.
792 switch (cpu_class) {
794 * A 286 and 386 should not make it this far, anyway.
796 case CPUCLASS_286:
797 case CPUCLASS_386:
798 #if !defined(I486_CPU)
799 case CPUCLASS_486:
800 #endif
801 #if !defined(I586_CPU)
802 case CPUCLASS_586:
803 #endif
804 #if !defined(I686_CPU)
805 case CPUCLASS_686:
806 #endif
807 panic("CPU class not configured");
808 default:
809 break;
814 static volatile u_int trap_by_rdmsr;
817 * Special exception 6 handler.
818 * The rdmsr instruction generates invalid opcodes fault on 486-class
819 * Cyrix CPU. Stacked eip register points the rdmsr instruction in the
820 * function identblue() when this handler is called. Stacked eip should
821 * be advanced.
823 inthand_t bluetrap6;
825 __asm(
826 " .text \n"
827 " .p2align 2,0x90 \n"
828 " .type " __XSTRING(CNAME(bluetrap6)) ",@function \n"
829 __XSTRING(CNAME(bluetrap6)) ": \n"
830 " ss \n"
831 " movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
832 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
833 " iret \n"
837 * Special exception 13 handler.
838 * Accessing non-existent MSR generates general protection fault.
840 inthand_t bluetrap13;
842 __asm(
843 " .text \n"
844 " .p2align 2,0x90 \n"
845 " .type " __XSTRING(CNAME(bluetrap13)) ",@function \n"
846 __XSTRING(CNAME(bluetrap13)) ": \n"
847 " ss \n"
848 " movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
849 " popl %eax # discard errorcode. \n"
850 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
851 " iret \n"
855 * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not
856 * support cpuid instruction. This function should be called after
857 * loading interrupt descriptor table register.
859 * I don't like this method that handles fault, but I couldn't get
860 * information for any other methods. Does blue giant know?
862 static int
863 identblue(void)
866 trap_by_rdmsr = 0;
869 * Cyrix 486-class CPU does not support rdmsr instruction.
870 * The rdmsr instruction generates invalid opcode fault, and exception
871 * will be trapped by bluetrap6() on Cyrix 486-class CPU. The
872 * bluetrap6() set the magic number to trap_by_rdmsr.
874 setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
877 * Certain BIOS disables cpuid instruction of Cyrix 6x86MX CPU.
878 * In this case, rdmsr generates general protection fault, and
879 * exception will be trapped by bluetrap13().
881 setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
883 rdmsr(0x1002); /* Cyrix CPU generates fault. */
885 if (trap_by_rdmsr == 0xa8c1d)
886 return IDENTBLUE_CYRIX486;
887 else if (trap_by_rdmsr == 0xa89c4)
888 return IDENTBLUE_CYRIXM2;
889 return IDENTBLUE_IBMCPU;
894 * identifycyrix() set lower 16 bits of cyrix_did as follows:
896 * F E D C B A 9 8 7 6 5 4 3 2 1 0
897 * +-------+-------+---------------+
898 * | SID | RID | Device ID |
899 * | (DIR 1) | (DIR 0) |
900 * +-------+-------+---------------+
902 static void
903 identifycyrix(void)
905 int ccr2_test = 0, dir_test = 0;
906 u_char ccr2, ccr3;
908 mpintr_lock();
910 ccr2 = read_cyrix_reg(CCR2);
911 write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW);
912 read_cyrix_reg(CCR2);
913 if (read_cyrix_reg(CCR2) != ccr2)
914 ccr2_test = 1;
915 write_cyrix_reg(CCR2, ccr2);
917 ccr3 = read_cyrix_reg(CCR3);
918 write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3);
919 read_cyrix_reg(CCR3);
920 if (read_cyrix_reg(CCR3) != ccr3)
921 dir_test = 1; /* CPU supports DIRs. */
922 write_cyrix_reg(CCR3, ccr3);
924 if (dir_test) {
925 /* Device ID registers are available. */
926 cyrix_did = read_cyrix_reg(DIR1) << 8;
927 cyrix_did += read_cyrix_reg(DIR0);
928 } else if (ccr2_test)
929 cyrix_did = 0x0010; /* 486S A-step */
930 else
931 cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */
933 mpintr_unlock();
937 * Final stage of CPU identification. -- Should I check TI?
939 void
940 finishidentcpu(void)
942 int isblue = 0;
943 u_char ccr3;
944 u_int regs[4];
946 if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
947 if (cpu == CPU_486) {
949 * These conditions are equivalent to:
950 * - CPU does not support cpuid instruction.
951 * - Cyrix/IBM CPU is detected.
953 isblue = identblue();
954 if (isblue == IDENTBLUE_IBMCPU) {
955 strcpy(cpu_vendor, "IBM");
956 cpu = CPU_BLUE;
957 return;
960 switch (cpu_id & 0xf00) {
961 case 0x600:
963 * Cyrix's datasheet does not describe DIRs.
964 * Therefor, I assume it does not have them
965 * and use the result of the cpuid instruction.
966 * XXX they seem to have it for now at least. -Peter
968 identifycyrix();
969 cpu = CPU_M2;
970 break;
971 default:
972 identifycyrix();
974 * This routine contains a trick.
975 * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now.
977 switch (cyrix_did & 0x00f0) {
978 case 0x00:
979 case 0xf0:
980 cpu = CPU_486DLC;
981 break;
982 case 0x10:
983 cpu = CPU_CY486DX;
984 break;
985 case 0x20:
986 if ((cyrix_did & 0x000f) < 8)
987 cpu = CPU_M1;
988 else
989 cpu = CPU_M1SC;
990 break;
991 case 0x30:
992 cpu = CPU_M1;
993 break;
994 case 0x40:
995 /* MediaGX CPU */
996 cpu = CPU_M1SC;
997 break;
998 default:
999 /* M2 and later CPUs are treated as M2. */
1000 cpu = CPU_M2;
1003 * enable cpuid instruction.
1005 ccr3 = read_cyrix_reg(CCR3);
1006 write_cyrix_reg(CCR3, CCR3_MAPEN0);
1007 write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID);
1008 write_cyrix_reg(CCR3, ccr3);
1010 do_cpuid(0, regs);
1011 cpu_high = regs[0]; /* eax */
1012 do_cpuid(1, regs);
1013 cpu_id = regs[0]; /* eax */
1014 cpu_feature = regs[3]; /* edx */
1015 break;
1018 } else if (cpu == CPU_486 && *cpu_vendor == '\0') {
1020 * There are BlueLightning CPUs that do not change
1021 * undefined flags by dividing 5 by 2. In this case,
1022 * the CPU identification routine in locore.s leaves
1023 * cpu_vendor null string and puts CPU_486 into the
1024 * cpu.
1026 isblue = identblue();
1027 if (isblue == IDENTBLUE_IBMCPU) {
1028 strcpy(cpu_vendor, "IBM");
1029 cpu = CPU_BLUE;
1030 return;
1035 static void
1036 print_AMD_assoc(int i)
1038 if (i == 255)
1039 kprintf(", fully associative\n");
1040 else
1041 kprintf(", %d-way associative\n", i);
1045 * #31116 Rev 3.06 section 3.9
1046 * CPUID Fn8000_0006 L2/L3 Cache and L2 TLB Identifiers
1048 static void
1049 print_AMD_L2L3_assoc(int i)
1051 static const char *assoc_str[] = {
1052 [0x0] = "disabled",
1053 [0x1] = "direct mapped",
1054 [0x2] = "2-way associative",
1055 [0x4] = "4-way associative",
1056 [0x6] = "8-way associative",
1057 [0x8] = "16-way associative",
1058 [0xa] = "32-way associative",
1059 [0xb] = "48-way associative",
1060 [0xc] = "64-way associative",
1061 [0xd] = "96-way associative",
1062 [0xe] = "128-way associative",
1063 [0xf] = "fully associative"
1066 i &= 0xf;
1067 if (assoc_str[i] == NULL)
1068 kprintf(", unknown associative\n");
1069 else
1070 kprintf(", %s\n", assoc_str[i]);
1073 static void
1074 print_AMD_info(void)
1076 quad_t amd_whcr;
1078 if (cpu_exthigh >= 0x80000005) {
1079 u_int regs[4];
1081 do_cpuid(0x80000005, regs);
1082 kprintf("Data TLB: %d entries", (regs[1] >> 16) & 0xff);
1083 print_AMD_assoc(regs[1] >> 24);
1084 kprintf("Instruction TLB: %d entries", regs[1] & 0xff);
1085 print_AMD_assoc((regs[1] >> 8) & 0xff);
1086 kprintf("L1 data cache: %d kbytes", regs[2] >> 24);
1087 kprintf(", %d bytes/line", regs[2] & 0xff);
1088 kprintf(", %d lines/tag", (regs[2] >> 8) & 0xff);
1089 print_AMD_assoc((regs[2] >> 16) & 0xff);
1090 kprintf("L1 instruction cache: %d kbytes", regs[3] >> 24);
1091 kprintf(", %d bytes/line", regs[3] & 0xff);
1092 kprintf(", %d lines/tag", (regs[3] >> 8) & 0xff);
1093 print_AMD_assoc((regs[3] >> 16) & 0xff);
1094 if (cpu_exthigh >= 0x80000006) { /* K6-III, or later */
1095 do_cpuid(0x80000006, regs);
1097 * Report right L2 cache size on Duron rev. A0.
1099 if ((cpu_id & 0xFF0) == 0x630)
1100 kprintf("L2 internal cache: 64 kbytes");
1101 else
1102 kprintf("L2 internal cache: %d kbytes",
1103 regs[2] >> 16);
1105 kprintf(", %d bytes/line", regs[2] & 0xff);
1106 kprintf(", %d lines/tag", (regs[2] >> 8) & 0x0f);
1107 print_AMD_L2L3_assoc((regs[2] >> 12) & 0x0f);
1110 * #31116 Rev 3.06 section 2.16.2:
1111 * ... If EDX[31:16] is not zero then the processor
1112 * includes an L3. ...
1114 if ((regs[3] & 0xffff0000) != 0) {
1115 kprintf("L3 shared cache: %d kbytes",
1116 (regs[3] >> 18) * 512);
1117 kprintf(", %d bytes/line", regs[3] & 0xff);
1118 kprintf(", %d lines/tag", (regs[3] >> 8) & 0x0f);
1119 print_AMD_L2L3_assoc((regs[3] >> 12) & 0x0f);
1123 if (((cpu_id & 0xf00) == 0x500)
1124 && (((cpu_id & 0x0f0) > 0x80)
1125 || (((cpu_id & 0x0f0) == 0x80)
1126 && (cpu_id & 0x00f) > 0x07))) {
1127 /* K6-2(new core [Stepping 8-F]), K6-III or later */
1128 amd_whcr = rdmsr(0xc0000082);
1129 if (!(amd_whcr & (0x3ff << 22))) {
1130 kprintf("Write Allocate Disable\n");
1131 } else {
1132 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1133 (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4);
1134 kprintf("Write Allocate 15-16M bytes: %s\n",
1135 (amd_whcr & (1 << 16)) ? "Enable" : "Disable");
1137 } else if (((cpu_id & 0xf00) == 0x500)
1138 && ((cpu_id & 0x0f0) > 0x50)) {
1139 /* K6, K6-2(old core) */
1140 amd_whcr = rdmsr(0xc0000082);
1141 if (!(amd_whcr & (0x7f << 1))) {
1142 kprintf("Write Allocate Disable\n");
1143 } else {
1144 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1145 (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4);
1146 kprintf("Write Allocate 15-16M bytes: %s\n",
1147 (amd_whcr & 0x0001) ? "Enable" : "Disable");
1148 kprintf("Hardware Write Allocate Control: %s\n",
1149 (amd_whcr & 0x0100) ? "Enable" : "Disable");
1154 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1155 static void
1156 print_AMD_features(void)
1158 u_int regs[4];
1161 * Values taken from AMD Processor Recognition
1162 * http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf
1164 do_cpuid(0x80000001, regs);
1165 kprintf("\n AMD Features=0x%b", regs[3] &~ cpu_feature,
1166 "\020" /* in hex */
1167 "\001FPU" /* Integral FPU */
1168 "\002VME" /* Extended VM86 mode support */
1169 "\003DE" /* Debug extensions */
1170 "\004PSE" /* 4MByte page tables */
1171 "\005TSC" /* Timestamp counter */
1172 "\006MSR" /* Machine specific registers */
1173 "\007PAE" /* Physical address extension */
1174 "\010MCE" /* Machine Check support */
1175 "\011CX8" /* CMPEXCH8 instruction */
1176 "\012APIC" /* SMP local APIC */
1177 "\013<b10>"
1178 "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */
1179 "\015MTRR" /* Memory Type Range Registers */
1180 "\016PGE" /* PG_G (global bit) support */
1181 "\017MCA" /* Machine Check Architecture */
1182 "\020ICMOV" /* CMOV instruction */
1183 "\021PAT" /* Page attributes table */
1184 "\022PGE36" /* 36 bit address space support */
1185 "\023RSVD" /* Reserved, unknown */
1186 "\024MP" /* Multiprocessor Capable */
1187 "\025NX" /* No-execute page protection */
1188 "\026<b21>"
1189 "\027AMIE" /* AMD MMX Instruction Extensions */
1190 "\030MMX"
1191 "\031FXSAVE" /* FXSAVE/FXRSTOR */
1192 "\032<b25>"
1193 "\033<b26>"
1194 "\034RDTSCP" /* RDTSCP instruction */
1195 "\035<b28>"
1196 "\036LM" /* Long mode */
1197 "\037DSP" /* AMD 3DNow! Instruction Extensions */
1198 "\0403DNow!"
1201 #endif
1204 * Transmeta Crusoe LongRun Support by Tamotsu Hattori.
1207 #define MSR_TMx86_LONGRUN 0x80868010
1208 #define MSR_TMx86_LONGRUN_FLAGS 0x80868011
1210 #define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f)
1211 #define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
1212 #define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y))
1214 #define LONGRUN_MODE_MINFREQUENCY 0x00
1215 #define LONGRUN_MODE_ECONOMY 0x01
1216 #define LONGRUN_MODE_PERFORMANCE 0x02
1217 #define LONGRUN_MODE_MAXFREQUENCY 0x03
1218 #define LONGRUN_MODE_UNKNOWN 0x04
1219 #define LONGRUN_MODE_MAX 0x04
1221 union msrinfo {
1222 u_int64_t msr;
1223 u_int32_t regs[2];
1226 u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
1227 /* MSR low, MSR high, flags bit0 */
1228 { 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */
1229 { 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */
1230 { 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */
1231 { 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */
1234 static u_int
1235 tmx86_get_longrun_mode(void)
1237 union msrinfo msrinfo;
1238 u_int low, high, flags, mode;
1240 mpintr_lock();
1242 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1243 low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
1244 high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
1245 flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
1247 for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
1248 if (low == longrun_modes[mode][0] &&
1249 high == longrun_modes[mode][1] &&
1250 flags == longrun_modes[mode][2]) {
1251 goto out;
1254 mode = LONGRUN_MODE_UNKNOWN;
1255 out:
1256 mpintr_unlock();
1257 return (mode);
1260 static u_int
1261 tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage)
1263 u_int regs[4];
1265 mpintr_lock();
1267 do_cpuid(0x80860007, regs);
1268 *frequency = regs[0];
1269 *voltage = regs[1];
1270 *percentage = regs[2];
1272 mpintr_unlock();
1273 return (1);
1276 static u_int
1277 tmx86_set_longrun_mode(u_int mode)
1279 union msrinfo msrinfo;
1281 if (mode >= LONGRUN_MODE_UNKNOWN) {
1282 return (0);
1285 mpintr_lock();
1287 /* Write LongRun mode values to Model Specific Register. */
1288 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1289 msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
1290 longrun_modes[mode][0]);
1291 msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
1292 longrun_modes[mode][1]);
1293 wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
1295 /* Write LongRun mode flags to Model Specific Register. */
1296 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
1297 msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
1298 wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
1300 mpintr_unlock();
1301 return (1);
1304 static u_int crusoe_longrun;
1305 static u_int crusoe_frequency;
1306 static u_int crusoe_voltage;
1307 static u_int crusoe_percentage;
1308 static struct sysctl_ctx_list crusoe_sysctl_ctx;
1309 static struct sysctl_oid *crusoe_sysctl_tree;
1311 static int
1312 tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS)
1314 u_int mode;
1315 int error;
1317 crusoe_longrun = tmx86_get_longrun_mode();
1318 mode = crusoe_longrun;
1319 error = sysctl_handle_int(oidp, &mode, 0, req);
1320 if (error || !req->newptr) {
1321 return (error);
1323 if (mode >= LONGRUN_MODE_UNKNOWN) {
1324 error = EINVAL;
1325 return (error);
1327 if (crusoe_longrun != mode) {
1328 crusoe_longrun = mode;
1329 tmx86_set_longrun_mode(crusoe_longrun);
1332 return (error);
1335 static int
1336 tmx86_status_sysctl(SYSCTL_HANDLER_ARGS)
1338 u_int val;
1339 int error;
1341 tmx86_get_longrun_status(&crusoe_frequency,
1342 &crusoe_voltage, &crusoe_percentage);
1343 val = *(u_int *)oidp->oid_arg1;
1344 error = sysctl_handle_int(oidp, &val, 0, req);
1345 return (error);
1348 static void
1349 setup_tmx86_longrun(void)
1351 static int done = 0;
1353 if (done)
1354 return;
1355 done++;
1357 sysctl_ctx_init(&crusoe_sysctl_ctx);
1358 crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx,
1359 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
1360 "crusoe", CTLFLAG_RD, 0,
1361 "Transmeta Crusoe LongRun support");
1362 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1363 OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW,
1364 &crusoe_longrun, 0, tmx86_longrun_sysctl, "I",
1365 "LongRun mode [0-3]");
1366 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1367 OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD,
1368 &crusoe_frequency, 0, tmx86_status_sysctl, "I",
1369 "Current frequency (MHz)");
1370 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1371 OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD,
1372 &crusoe_voltage, 0, tmx86_status_sysctl, "I",
1373 "Current voltage (mV)");
1374 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1375 OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD,
1376 &crusoe_percentage, 0, tmx86_status_sysctl, "I",
1377 "Processing performance (%)");
1380 static void
1381 print_transmeta_info(void)
1383 u_int regs[4], nreg = 0;
1385 do_cpuid(0x80860000, regs);
1386 nreg = regs[0];
1387 if (nreg >= 0x80860001) {
1388 do_cpuid(0x80860001, regs);
1389 kprintf(" Processor revision %u.%u.%u.%u\n",
1390 (regs[1] >> 24) & 0xff,
1391 (regs[1] >> 16) & 0xff,
1392 (regs[1] >> 8) & 0xff,
1393 regs[1] & 0xff);
1395 if (nreg >= 0x80860002) {
1396 do_cpuid(0x80860002, regs);
1397 kprintf(" Code Morphing Software revision %u.%u.%u-%u-%u\n",
1398 (regs[1] >> 24) & 0xff,
1399 (regs[1] >> 16) & 0xff,
1400 (regs[1] >> 8) & 0xff,
1401 regs[1] & 0xff,
1402 regs[2]);
1404 if (nreg >= 0x80860006) {
1405 char info[65];
1406 do_cpuid(0x80860003, (u_int*) &info[0]);
1407 do_cpuid(0x80860004, (u_int*) &info[16]);
1408 do_cpuid(0x80860005, (u_int*) &info[32]);
1409 do_cpuid(0x80860006, (u_int*) &info[48]);
1410 info[64] = 0;
1411 kprintf(" %s\n", info);
1414 crusoe_longrun = tmx86_get_longrun_mode();
1415 tmx86_get_longrun_status(&crusoe_frequency,
1416 &crusoe_voltage, &crusoe_percentage);
1417 kprintf(" LongRun mode: %d <%dMHz %dmV %d%%>\n", crusoe_longrun,
1418 crusoe_frequency, crusoe_voltage, crusoe_percentage);
1421 void
1422 additional_cpu_info(const char *line)
1424 int i;
1426 if ((i = additional_cpu_info_count) < MAX_ADDITIONAL_INFO) {
1427 additional_cpu_info_ary[i] = line;
1428 ++additional_cpu_info_count;
1432 static void
1433 print_via_padlock_info(void)
1435 u_int regs[4];
1437 /* Check for supported models. */
1438 switch (cpu_id & 0xff0) {
1439 case 0x690:
1440 if ((cpu_id & 0xf) < 3)
1441 return;
1442 case 0x6a0:
1443 case 0x6d0:
1444 case 0x6f0:
1445 break;
1446 default:
1447 return;
1450 do_cpuid(0xc0000000, regs);
1451 if (regs[0] >= 0xc0000001)
1452 do_cpuid(0xc0000001, regs);
1453 else
1454 return;
1456 kprintf("\n VIA Padlock Features=0x%b", regs[3],
1457 "\020"
1458 "\003RNG" /* RNG */
1459 "\007AES" /* ACE */
1460 "\011AES-CTR" /* ACE2 */
1461 "\013SHA1,SHA256" /* PHE */
1462 "\015RSA" /* PMM */