opencrypto - Finish porting
[dragonfly.git] / sys / platform / pc32 / i386 / identcpu.c
blob93b6d8941158c9d94aa5c9375b8094ebed838e28
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>"
726 if (strcmp(cpu_vendor, "CentaurHauls") == 0)
727 print_via_padlock_info();
730 * If this CPU supports hyperthreading then mention
731 * the number of logical CPU's it contains.
733 if (cpu_feature & CPUID_HTT &&
734 (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1)
735 kprintf("\n Hyperthreading: %d logical CPUs",
736 (cpu_procinfo & CPUID_HTT_CORES) >> 16);
738 if (strcmp(cpu_vendor, "AuthenticAMD") == 0 &&
739 cpu_exthigh >= 0x80000001)
740 print_AMD_features();
741 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
742 kprintf(" DIR=0x%04x", cyrix_did);
743 kprintf(" Stepping=%u", (cyrix_did & 0xf000) >> 12);
744 kprintf(" Revision=%u", (cyrix_did & 0x0f00) >> 8);
745 #ifndef CYRIX_CACHE_REALLY_WORKS
746 if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700)
747 kprintf("\n CPU cache: write-through mode");
748 #endif
750 /* Avoid ugly blank lines: only print newline when we have to. */
751 if (*cpu_vendor || cpu_id)
752 kprintf("\n");
754 #endif
755 if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
756 strcmp(cpu_vendor, "TransmetaCPU") == 0) {
757 setup_tmx86_longrun();
760 for (i = 0; i < additional_cpu_info_count; ++i) {
761 kprintf(" %s\n", additional_cpu_info_ary[i]);
764 if (!bootverbose)
765 return;
767 if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
768 print_AMD_info();
769 else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
770 strcmp(cpu_vendor, "TransmetaCPU") == 0)
771 print_transmeta_info();
773 #ifdef I686_CPU
775 * XXX - Do PPro CPUID level=2 stuff here?
777 * No, but maybe in a print_Intel_info() function called from here.
779 #endif
782 void
783 panicifcpuunsupported(void)
786 #if !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
787 #error This kernel is not configured for one of the supported CPUs
788 #endif
790 * Now that we have told the user what they have,
791 * let them know if that machine type isn't configured.
793 switch (cpu_class) {
795 * A 286 and 386 should not make it this far, anyway.
797 case CPUCLASS_286:
798 case CPUCLASS_386:
799 #if !defined(I486_CPU)
800 case CPUCLASS_486:
801 #endif
802 #if !defined(I586_CPU)
803 case CPUCLASS_586:
804 #endif
805 #if !defined(I686_CPU)
806 case CPUCLASS_686:
807 #endif
808 panic("CPU class not configured");
809 default:
810 break;
815 static volatile u_int trap_by_rdmsr;
818 * Special exception 6 handler.
819 * The rdmsr instruction generates invalid opcodes fault on 486-class
820 * Cyrix CPU. Stacked eip register points the rdmsr instruction in the
821 * function identblue() when this handler is called. Stacked eip should
822 * be advanced.
824 inthand_t bluetrap6;
826 __asm(
827 " .text \n"
828 " .p2align 2,0x90 \n"
829 " .type " __XSTRING(CNAME(bluetrap6)) ",@function \n"
830 __XSTRING(CNAME(bluetrap6)) ": \n"
831 " ss \n"
832 " movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
833 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
834 " iret \n"
838 * Special exception 13 handler.
839 * Accessing non-existent MSR generates general protection fault.
841 inthand_t bluetrap13;
843 __asm(
844 " .text \n"
845 " .p2align 2,0x90 \n"
846 " .type " __XSTRING(CNAME(bluetrap13)) ",@function \n"
847 __XSTRING(CNAME(bluetrap13)) ": \n"
848 " ss \n"
849 " movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " \n"
850 " popl %eax # discard errorcode. \n"
851 " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n"
852 " iret \n"
856 * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not
857 * support cpuid instruction. This function should be called after
858 * loading interrupt descriptor table register.
860 * I don't like this method that handles fault, but I couldn't get
861 * information for any other methods. Does blue giant know?
863 static int
864 identblue(void)
867 trap_by_rdmsr = 0;
870 * Cyrix 486-class CPU does not support rdmsr instruction.
871 * The rdmsr instruction generates invalid opcode fault, and exception
872 * will be trapped by bluetrap6() on Cyrix 486-class CPU. The
873 * bluetrap6() set the magic number to trap_by_rdmsr.
875 setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
878 * Certain BIOS disables cpuid instruction of Cyrix 6x86MX CPU.
879 * In this case, rdmsr generates general protection fault, and
880 * exception will be trapped by bluetrap13().
882 setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
884 rdmsr(0x1002); /* Cyrix CPU generates fault. */
886 if (trap_by_rdmsr == 0xa8c1d)
887 return IDENTBLUE_CYRIX486;
888 else if (trap_by_rdmsr == 0xa89c4)
889 return IDENTBLUE_CYRIXM2;
890 return IDENTBLUE_IBMCPU;
895 * identifycyrix() set lower 16 bits of cyrix_did as follows:
897 * F E D C B A 9 8 7 6 5 4 3 2 1 0
898 * +-------+-------+---------------+
899 * | SID | RID | Device ID |
900 * | (DIR 1) | (DIR 0) |
901 * +-------+-------+---------------+
903 static void
904 identifycyrix(void)
906 int ccr2_test = 0, dir_test = 0;
907 u_char ccr2, ccr3;
909 mpintr_lock();
911 ccr2 = read_cyrix_reg(CCR2);
912 write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW);
913 read_cyrix_reg(CCR2);
914 if (read_cyrix_reg(CCR2) != ccr2)
915 ccr2_test = 1;
916 write_cyrix_reg(CCR2, ccr2);
918 ccr3 = read_cyrix_reg(CCR3);
919 write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3);
920 read_cyrix_reg(CCR3);
921 if (read_cyrix_reg(CCR3) != ccr3)
922 dir_test = 1; /* CPU supports DIRs. */
923 write_cyrix_reg(CCR3, ccr3);
925 if (dir_test) {
926 /* Device ID registers are available. */
927 cyrix_did = read_cyrix_reg(DIR1) << 8;
928 cyrix_did += read_cyrix_reg(DIR0);
929 } else if (ccr2_test)
930 cyrix_did = 0x0010; /* 486S A-step */
931 else
932 cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */
934 mpintr_unlock();
938 * Final stage of CPU identification. -- Should I check TI?
940 void
941 finishidentcpu(void)
943 int isblue = 0;
944 u_char ccr3;
945 u_int regs[4];
947 if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
948 if (cpu == CPU_486) {
950 * These conditions are equivalent to:
951 * - CPU does not support cpuid instruction.
952 * - Cyrix/IBM CPU is detected.
954 isblue = identblue();
955 if (isblue == IDENTBLUE_IBMCPU) {
956 strcpy(cpu_vendor, "IBM");
957 cpu = CPU_BLUE;
958 return;
961 switch (cpu_id & 0xf00) {
962 case 0x600:
964 * Cyrix's datasheet does not describe DIRs.
965 * Therefor, I assume it does not have them
966 * and use the result of the cpuid instruction.
967 * XXX they seem to have it for now at least. -Peter
969 identifycyrix();
970 cpu = CPU_M2;
971 break;
972 default:
973 identifycyrix();
975 * This routine contains a trick.
976 * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now.
978 switch (cyrix_did & 0x00f0) {
979 case 0x00:
980 case 0xf0:
981 cpu = CPU_486DLC;
982 break;
983 case 0x10:
984 cpu = CPU_CY486DX;
985 break;
986 case 0x20:
987 if ((cyrix_did & 0x000f) < 8)
988 cpu = CPU_M1;
989 else
990 cpu = CPU_M1SC;
991 break;
992 case 0x30:
993 cpu = CPU_M1;
994 break;
995 case 0x40:
996 /* MediaGX CPU */
997 cpu = CPU_M1SC;
998 break;
999 default:
1000 /* M2 and later CPUs are treated as M2. */
1001 cpu = CPU_M2;
1004 * enable cpuid instruction.
1006 ccr3 = read_cyrix_reg(CCR3);
1007 write_cyrix_reg(CCR3, CCR3_MAPEN0);
1008 write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID);
1009 write_cyrix_reg(CCR3, ccr3);
1011 do_cpuid(0, regs);
1012 cpu_high = regs[0]; /* eax */
1013 do_cpuid(1, regs);
1014 cpu_id = regs[0]; /* eax */
1015 cpu_feature = regs[3]; /* edx */
1016 break;
1019 } else if (cpu == CPU_486 && *cpu_vendor == '\0') {
1021 * There are BlueLightning CPUs that do not change
1022 * undefined flags by dividing 5 by 2. In this case,
1023 * the CPU identification routine in locore.s leaves
1024 * cpu_vendor null string and puts CPU_486 into the
1025 * cpu.
1027 isblue = identblue();
1028 if (isblue == IDENTBLUE_IBMCPU) {
1029 strcpy(cpu_vendor, "IBM");
1030 cpu = CPU_BLUE;
1031 return;
1036 static void
1037 print_AMD_assoc(int i)
1039 if (i == 255)
1040 kprintf(", fully associative\n");
1041 else
1042 kprintf(", %d-way associative\n", i);
1046 * #31116 Rev 3.06 section 3.9
1047 * CPUID Fn8000_0006 L2/L3 Cache and L2 TLB Identifiers
1049 static void
1050 print_AMD_L2L3_assoc(int i)
1052 static const char *assoc_str[] = {
1053 [0x0] = "disabled",
1054 [0x1] = "direct mapped",
1055 [0x2] = "2-way associative",
1056 [0x4] = "4-way associative",
1057 [0x6] = "8-way associative",
1058 [0x8] = "16-way associative",
1059 [0xa] = "32-way associative",
1060 [0xb] = "48-way associative",
1061 [0xc] = "64-way associative",
1062 [0xd] = "96-way associative",
1063 [0xe] = "128-way associative",
1064 [0xf] = "fully associative"
1067 i &= 0xf;
1068 if (assoc_str[i] == NULL)
1069 kprintf(", unknown associative\n");
1070 else
1071 kprintf(", %s\n", assoc_str[i]);
1074 static void
1075 print_AMD_info(void)
1077 quad_t amd_whcr;
1079 if (cpu_exthigh >= 0x80000005) {
1080 u_int regs[4];
1082 do_cpuid(0x80000005, regs);
1083 kprintf("Data TLB: %d entries", (regs[1] >> 16) & 0xff);
1084 print_AMD_assoc(regs[1] >> 24);
1085 kprintf("Instruction TLB: %d entries", regs[1] & 0xff);
1086 print_AMD_assoc((regs[1] >> 8) & 0xff);
1087 kprintf("L1 data cache: %d kbytes", regs[2] >> 24);
1088 kprintf(", %d bytes/line", regs[2] & 0xff);
1089 kprintf(", %d lines/tag", (regs[2] >> 8) & 0xff);
1090 print_AMD_assoc((regs[2] >> 16) & 0xff);
1091 kprintf("L1 instruction cache: %d kbytes", regs[3] >> 24);
1092 kprintf(", %d bytes/line", regs[3] & 0xff);
1093 kprintf(", %d lines/tag", (regs[3] >> 8) & 0xff);
1094 print_AMD_assoc((regs[3] >> 16) & 0xff);
1095 if (cpu_exthigh >= 0x80000006) { /* K6-III, or later */
1096 do_cpuid(0x80000006, regs);
1098 * Report right L2 cache size on Duron rev. A0.
1100 if ((cpu_id & 0xFF0) == 0x630)
1101 kprintf("L2 internal cache: 64 kbytes");
1102 else
1103 kprintf("L2 internal cache: %d kbytes",
1104 regs[2] >> 16);
1106 kprintf(", %d bytes/line", regs[2] & 0xff);
1107 kprintf(", %d lines/tag", (regs[2] >> 8) & 0x0f);
1108 print_AMD_L2L3_assoc((regs[2] >> 12) & 0x0f);
1111 * #31116 Rev 3.06 section 2.16.2:
1112 * ... If EDX[31:16] is not zero then the processor
1113 * includes an L3. ...
1115 if ((regs[3] & 0xffff0000) != 0) {
1116 kprintf("L3 shared cache: %d kbytes",
1117 (regs[3] >> 18) * 512);
1118 kprintf(", %d bytes/line", regs[3] & 0xff);
1119 kprintf(", %d lines/tag", (regs[3] >> 8) & 0x0f);
1120 print_AMD_L2L3_assoc((regs[3] >> 12) & 0x0f);
1124 if (((cpu_id & 0xf00) == 0x500)
1125 && (((cpu_id & 0x0f0) > 0x80)
1126 || (((cpu_id & 0x0f0) == 0x80)
1127 && (cpu_id & 0x00f) > 0x07))) {
1128 /* K6-2(new core [Stepping 8-F]), K6-III or later */
1129 amd_whcr = rdmsr(0xc0000082);
1130 if (!(amd_whcr & (0x3ff << 22))) {
1131 kprintf("Write Allocate Disable\n");
1132 } else {
1133 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1134 (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4);
1135 kprintf("Write Allocate 15-16M bytes: %s\n",
1136 (amd_whcr & (1 << 16)) ? "Enable" : "Disable");
1138 } else if (((cpu_id & 0xf00) == 0x500)
1139 && ((cpu_id & 0x0f0) > 0x50)) {
1140 /* K6, K6-2(old core) */
1141 amd_whcr = rdmsr(0xc0000082);
1142 if (!(amd_whcr & (0x7f << 1))) {
1143 kprintf("Write Allocate Disable\n");
1144 } else {
1145 kprintf("Write Allocate Enable Limit: %dM bytes\n",
1146 (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4);
1147 kprintf("Write Allocate 15-16M bytes: %s\n",
1148 (amd_whcr & 0x0001) ? "Enable" : "Disable");
1149 kprintf("Hardware Write Allocate Control: %s\n",
1150 (amd_whcr & 0x0100) ? "Enable" : "Disable");
1155 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1156 static void
1157 print_AMD_features(void)
1159 u_int regs[4];
1162 * Values taken from AMD Processor Recognition
1163 * http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf
1165 do_cpuid(0x80000001, regs);
1166 kprintf("\n AMD Features=0x%b", regs[3] &~ cpu_feature,
1167 "\020" /* in hex */
1168 "\001FPU" /* Integral FPU */
1169 "\002VME" /* Extended VM86 mode support */
1170 "\003DE" /* Debug extensions */
1171 "\004PSE" /* 4MByte page tables */
1172 "\005TSC" /* Timestamp counter */
1173 "\006MSR" /* Machine specific registers */
1174 "\007PAE" /* Physical address extension */
1175 "\010MCE" /* Machine Check support */
1176 "\011CX8" /* CMPEXCH8 instruction */
1177 "\012APIC" /* SMP local APIC */
1178 "\013<b10>"
1179 "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */
1180 "\015MTRR" /* Memory Type Range Registers */
1181 "\016PGE" /* PG_G (global bit) support */
1182 "\017MCA" /* Machine Check Architecture */
1183 "\020ICMOV" /* CMOV instruction */
1184 "\021PAT" /* Page attributes table */
1185 "\022PGE36" /* 36 bit address space support */
1186 "\023RSVD" /* Reserved, unknown */
1187 "\024MP" /* Multiprocessor Capable */
1188 "\025NX" /* No-execute page protection */
1189 "\026<b21>"
1190 "\027AMIE" /* AMD MMX Instruction Extensions */
1191 "\030MMX"
1192 "\031FXSAVE" /* FXSAVE/FXRSTOR */
1193 "\032<b25>"
1194 "\033<b26>"
1195 "\034RDTSCP" /* RDTSCP instruction */
1196 "\035<b28>"
1197 "\036LM" /* Long mode */
1198 "\037DSP" /* AMD 3DNow! Instruction Extensions */
1199 "\0403DNow!"
1202 #endif
1205 * Transmeta Crusoe LongRun Support by Tamotsu Hattori.
1208 #define MSR_TMx86_LONGRUN 0x80868010
1209 #define MSR_TMx86_LONGRUN_FLAGS 0x80868011
1211 #define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f)
1212 #define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80)
1213 #define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y))
1215 #define LONGRUN_MODE_MINFREQUENCY 0x00
1216 #define LONGRUN_MODE_ECONOMY 0x01
1217 #define LONGRUN_MODE_PERFORMANCE 0x02
1218 #define LONGRUN_MODE_MAXFREQUENCY 0x03
1219 #define LONGRUN_MODE_UNKNOWN 0x04
1220 #define LONGRUN_MODE_MAX 0x04
1222 union msrinfo {
1223 u_int64_t msr;
1224 u_int32_t regs[2];
1227 u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
1228 /* MSR low, MSR high, flags bit0 */
1229 { 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */
1230 { 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */
1231 { 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */
1232 { 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */
1235 static u_int
1236 tmx86_get_longrun_mode(void)
1238 union msrinfo msrinfo;
1239 u_int low, high, flags, mode;
1241 mpintr_lock();
1243 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1244 low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
1245 high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
1246 flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
1248 for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
1249 if (low == longrun_modes[mode][0] &&
1250 high == longrun_modes[mode][1] &&
1251 flags == longrun_modes[mode][2]) {
1252 goto out;
1255 mode = LONGRUN_MODE_UNKNOWN;
1256 out:
1257 mpintr_unlock();
1258 return (mode);
1261 static u_int
1262 tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage)
1264 u_int regs[4];
1266 mpintr_lock();
1268 do_cpuid(0x80860007, regs);
1269 *frequency = regs[0];
1270 *voltage = regs[1];
1271 *percentage = regs[2];
1273 mpintr_unlock();
1274 return (1);
1277 static u_int
1278 tmx86_set_longrun_mode(u_int mode)
1280 union msrinfo msrinfo;
1282 if (mode >= LONGRUN_MODE_UNKNOWN) {
1283 return (0);
1286 mpintr_lock();
1288 /* Write LongRun mode values to Model Specific Register. */
1289 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
1290 msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
1291 longrun_modes[mode][0]);
1292 msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
1293 longrun_modes[mode][1]);
1294 wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
1296 /* Write LongRun mode flags to Model Specific Register. */
1297 msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
1298 msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
1299 wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
1301 mpintr_unlock();
1302 return (1);
1305 static u_int crusoe_longrun;
1306 static u_int crusoe_frequency;
1307 static u_int crusoe_voltage;
1308 static u_int crusoe_percentage;
1309 static struct sysctl_ctx_list crusoe_sysctl_ctx;
1310 static struct sysctl_oid *crusoe_sysctl_tree;
1312 static int
1313 tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS)
1315 u_int mode;
1316 int error;
1318 crusoe_longrun = tmx86_get_longrun_mode();
1319 mode = crusoe_longrun;
1320 error = sysctl_handle_int(oidp, &mode, 0, req);
1321 if (error || !req->newptr) {
1322 return (error);
1324 if (mode >= LONGRUN_MODE_UNKNOWN) {
1325 error = EINVAL;
1326 return (error);
1328 if (crusoe_longrun != mode) {
1329 crusoe_longrun = mode;
1330 tmx86_set_longrun_mode(crusoe_longrun);
1333 return (error);
1336 static int
1337 tmx86_status_sysctl(SYSCTL_HANDLER_ARGS)
1339 u_int val;
1340 int error;
1342 tmx86_get_longrun_status(&crusoe_frequency,
1343 &crusoe_voltage, &crusoe_percentage);
1344 val = *(u_int *)oidp->oid_arg1;
1345 error = sysctl_handle_int(oidp, &val, 0, req);
1346 return (error);
1349 static void
1350 setup_tmx86_longrun(void)
1352 static int done = 0;
1354 if (done)
1355 return;
1356 done++;
1358 sysctl_ctx_init(&crusoe_sysctl_ctx);
1359 crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx,
1360 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
1361 "crusoe", CTLFLAG_RD, 0,
1362 "Transmeta Crusoe LongRun support");
1363 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1364 OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW,
1365 &crusoe_longrun, 0, tmx86_longrun_sysctl, "I",
1366 "LongRun mode [0-3]");
1367 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1368 OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD,
1369 &crusoe_frequency, 0, tmx86_status_sysctl, "I",
1370 "Current frequency (MHz)");
1371 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1372 OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD,
1373 &crusoe_voltage, 0, tmx86_status_sysctl, "I",
1374 "Current voltage (mV)");
1375 SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree),
1376 OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD,
1377 &crusoe_percentage, 0, tmx86_status_sysctl, "I",
1378 "Processing performance (%)");
1381 static void
1382 print_transmeta_info(void)
1384 u_int regs[4], nreg = 0;
1386 do_cpuid(0x80860000, regs);
1387 nreg = regs[0];
1388 if (nreg >= 0x80860001) {
1389 do_cpuid(0x80860001, regs);
1390 kprintf(" Processor revision %u.%u.%u.%u\n",
1391 (regs[1] >> 24) & 0xff,
1392 (regs[1] >> 16) & 0xff,
1393 (regs[1] >> 8) & 0xff,
1394 regs[1] & 0xff);
1396 if (nreg >= 0x80860002) {
1397 do_cpuid(0x80860002, regs);
1398 kprintf(" Code Morphing Software revision %u.%u.%u-%u-%u\n",
1399 (regs[1] >> 24) & 0xff,
1400 (regs[1] >> 16) & 0xff,
1401 (regs[1] >> 8) & 0xff,
1402 regs[1] & 0xff,
1403 regs[2]);
1405 if (nreg >= 0x80860006) {
1406 char info[65];
1407 do_cpuid(0x80860003, (u_int*) &info[0]);
1408 do_cpuid(0x80860004, (u_int*) &info[16]);
1409 do_cpuid(0x80860005, (u_int*) &info[32]);
1410 do_cpuid(0x80860006, (u_int*) &info[48]);
1411 info[64] = 0;
1412 kprintf(" %s\n", info);
1415 crusoe_longrun = tmx86_get_longrun_mode();
1416 tmx86_get_longrun_status(&crusoe_frequency,
1417 &crusoe_voltage, &crusoe_percentage);
1418 kprintf(" LongRun mode: %d <%dMHz %dmV %d%%>\n", crusoe_longrun,
1419 crusoe_frequency, crusoe_voltage, crusoe_percentage);
1422 static void
1423 print_via_padlock_info(void)
1425 u_int regs[4];
1427 /* Check for supported models. */
1428 switch (cpu_id & 0xff0) {
1429 case 0x690:
1430 if ((cpu_id & 0xf) < 3)
1431 return;
1432 case 0x6a0:
1433 case 0x6d0:
1434 case 0x6f0:
1435 break;
1436 default:
1437 return;
1440 do_cpuid(0xc0000000, regs);
1441 if (regs[0] >= 0xc0000001)
1442 do_cpuid(0xc0000001, regs);
1443 else
1444 return;
1446 kprintf("\n VIA Padlock Features=0x%b", regs[3],
1447 "\020"
1448 "\003RNG" /* RNG */
1449 "\007AES" /* ACE */
1450 "\011AES-CTR" /* ACE2 */
1451 "\013SHA1,SHA256" /* PHE */
1452 "\015RSA" /* PMM */
1456 void
1457 additional_cpu_info(const char *line)
1459 int i;
1461 if ((i = additional_cpu_info_count) < MAX_ADDITIONAL_INFO) {
1462 additional_cpu_info_ary[i] = line;
1463 ++additional_cpu_info_count;