]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/identcpu.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / sys / i386 / i386 / identcpu.c
1 /*-
2  * Copyright (c) 1992 Terrence R. Lambert.
3  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
4  * Copyright (c) 1997 KATO Takenori.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * William Jolitz.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *      from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
39  */
40
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 #include "opt_cpu.h"
45
46 #include <sys/param.h>
47 #include <sys/bus.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/sysctl.h>
51 #include <sys/power.h>
52
53 #include <machine/asmacros.h>
54 #include <machine/clock.h>
55 #include <machine/cputypes.h>
56 #include <machine/intr_machdep.h>
57 #include <machine/md_var.h>
58 #include <machine/segments.h>
59 #include <machine/specialreg.h>
60
61 #define IDENTBLUE_CYRIX486      0
62 #define IDENTBLUE_IBMCPU        1
63 #define IDENTBLUE_CYRIXM2       2
64
65 /* XXX - should be in header file: */
66 void printcpuinfo(void);
67 void finishidentcpu(void);
68 void earlysetcpuclass(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);
75
76 static void identifycyrix(void);
77 static void print_AMD_info(void);
78 static void print_AMD_assoc(int i);
79 static void print_transmeta_info(void);
80 static void print_via_padlock_info(void);
81
82 int     cpu_class;
83 u_int   cpu_exthigh;            /* Highest arg to extended CPUID */
84 u_int   cyrix_did;              /* Device ID of Cyrix CPU */
85 char machine[] = "i386";
86 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, 
87     machine, 0, "Machine class");
88
89 static char cpu_model[128];
90 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, 
91     cpu_model, 0, "Machine model");
92
93 static int hw_clockrate;
94 SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 
95     &hw_clockrate, 0, "CPU instruction clock rate");
96
97 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
98 static char cpu_brand[48];
99
100 #define MAX_BRAND_INDEX 8
101
102 static const char *cpu_brandtable[MAX_BRAND_INDEX + 1] = {
103         NULL,                   /* No brand */
104         "Intel Celeron",
105         "Intel Pentium III",
106         "Intel Pentium III Xeon",
107         NULL,
108         NULL,
109         NULL,
110         NULL,
111         "Intel Pentium 4"
112 };
113 #endif
114
115 static struct {
116         char    *cpu_name;
117         int     cpu_class;
118 } i386_cpus[] = {
119         { "Intel 80286",        CPUCLASS_286 },         /* CPU_286   */
120         { "i386SX",             CPUCLASS_386 },         /* CPU_386SX */
121         { "i386DX",             CPUCLASS_386 },         /* CPU_386   */
122         { "i486SX",             CPUCLASS_486 },         /* CPU_486SX */
123         { "i486DX",             CPUCLASS_486 },         /* CPU_486   */
124         { "Pentium",            CPUCLASS_586 },         /* CPU_586   */
125         { "Cyrix 486",          CPUCLASS_486 },         /* CPU_486DLC */
126         { "Pentium Pro",        CPUCLASS_686 },         /* CPU_686 */
127         { "Cyrix 5x86",         CPUCLASS_486 },         /* CPU_M1SC */
128         { "Cyrix 6x86",         CPUCLASS_486 },         /* CPU_M1 */
129         { "Blue Lightning",     CPUCLASS_486 },         /* CPU_BLUE */
130         { "Cyrix 6x86MX",       CPUCLASS_686 },         /* CPU_M2 */
131         { "NexGen 586",         CPUCLASS_386 },         /* CPU_NX586 (XXX) */
132         { "Cyrix 486S/DX",      CPUCLASS_486 },         /* CPU_CY486DX */
133         { "Pentium II",         CPUCLASS_686 },         /* CPU_PII */
134         { "Pentium III",        CPUCLASS_686 },         /* CPU_PIII */
135         { "Pentium 4",          CPUCLASS_686 },         /* CPU_P4 */
136 };
137
138 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
139 int has_f00f_bug = 0;           /* Initialized so that it can be patched. */
140 #endif
141
142 void
143 printcpuinfo(void)
144 {
145 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
146         u_int regs[4], i;
147         char *brand;
148 #endif
149
150         cpu_class = i386_cpus[cpu].cpu_class;
151         printf("CPU: ");
152         strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof (cpu_model));
153
154 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
155         /* Check for extended CPUID information and a processor name. */
156         if (cpu_high > 0 &&
157             (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
158             strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
159             strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
160             strcmp(cpu_vendor, "TransmetaCPU") == 0 ||
161             strcmp(cpu_vendor, "CentaurHauls") == 0 ||
162             strcmp(cpu_vendor, "Geode by NSC") == 0)) {
163                 do_cpuid(0x80000000, regs);
164                 if (regs[0] >= 0x80000000) {
165                         cpu_exthigh = regs[0];
166                         if (cpu_exthigh >= 0x80000004) {
167                                 brand = cpu_brand;
168                                 for (i = 0x80000002; i < 0x80000005; i++) {
169                                         do_cpuid(i, regs);
170                                         memcpy(brand, regs, sizeof(regs));
171                                         brand += sizeof(regs);
172                                 }
173                         }
174                 }
175         }
176
177         /* Detect AMD features (PTE no-execute bit, 3dnow, 64 bit mode etc) */
178         if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
179             strcmp(cpu_vendor, "AuthenticAMD") == 0) {
180                 if (cpu_exthigh >= 0x80000001) {
181                         do_cpuid(0x80000001, regs);
182                         amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff);
183                         amd_feature2 = regs[2];
184                 }
185                 if (cpu_exthigh >= 0x80000008) {
186                         do_cpuid(0x80000008, regs);
187                         cpu_procinfo2 = regs[2];
188                 }
189         }
190
191         if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
192                 if ((cpu_id & 0xf00) > 0x300) {
193                         u_int brand_index;
194
195                         cpu_model[0] = '\0';
196
197                         switch (cpu_id & 0x3000) {
198                         case 0x1000:
199                                 strcpy(cpu_model, "Overdrive ");
200                                 break;
201                         case 0x2000:
202                                 strcpy(cpu_model, "Dual ");
203                                 break;
204                         }
205
206                         switch (cpu_id & 0xf00) {
207                         case 0x400:
208                                 strcat(cpu_model, "i486 ");
209                                 /* Check the particular flavor of 486 */
210                                 switch (cpu_id & 0xf0) {
211                                 case 0x00:
212                                 case 0x10:
213                                         strcat(cpu_model, "DX");
214                                         break;
215                                 case 0x20:
216                                         strcat(cpu_model, "SX");
217                                         break;
218                                 case 0x30:
219                                         strcat(cpu_model, "DX2");
220                                         break;
221                                 case 0x40:
222                                         strcat(cpu_model, "SL");
223                                         break;
224                                 case 0x50:
225                                         strcat(cpu_model, "SX2");
226                                         break;
227                                 case 0x70:
228                                         strcat(cpu_model,
229                                             "DX2 Write-Back Enhanced");
230                                         break;
231                                 case 0x80:
232                                         strcat(cpu_model, "DX4");
233                                         break;
234                                 }
235                                 break;
236                         case 0x500:
237                                 /* Check the particular flavor of 586 */
238                                 strcat(cpu_model, "Pentium");
239                                 switch (cpu_id & 0xf0) {
240                                 case 0x00:
241                                         strcat(cpu_model, " A-step");
242                                         break;
243                                 case 0x10:
244                                         strcat(cpu_model, "/P5");
245                                         break;
246                                 case 0x20:
247                                         strcat(cpu_model, "/P54C");
248                                         break;
249                                 case 0x30:
250                                         strcat(cpu_model, "/P54T Overdrive");
251                                         break;
252                                 case 0x40:
253                                         strcat(cpu_model, "/P55C");
254                                         break;
255                                 case 0x70:
256                                         strcat(cpu_model, "/P54C");
257                                         break;
258                                 case 0x80:
259                                         strcat(cpu_model, "/P55C (quarter-micron)");
260                                         break;
261                                 default:
262                                         /* nothing */
263                                         break;
264                                 }
265 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
266                                 /*
267                                  * XXX - If/when Intel fixes the bug, this
268                                  * should also check the version of the
269                                  * CPU, not just that it's a Pentium.
270                                  */
271                                 has_f00f_bug = 1;
272 #endif
273                                 break;
274                         case 0x600:
275                                 /* Check the particular flavor of 686 */
276                                 switch (cpu_id & 0xf0) {
277                                 case 0x00:
278                                         strcat(cpu_model, "Pentium Pro A-step");
279                                         break;
280                                 case 0x10:
281                                         strcat(cpu_model, "Pentium Pro");
282                                         break;
283                                 case 0x30:
284                                 case 0x50:
285                                 case 0x60:
286                                         strcat(cpu_model,
287                                 "Pentium II/Pentium II Xeon/Celeron");
288                                         cpu = CPU_PII;
289                                         break;
290                                 case 0x70:
291                                 case 0x80:
292                                 case 0xa0:
293                                 case 0xb0:
294                                         strcat(cpu_model,
295                                         "Pentium III/Pentium III Xeon/Celeron");
296                                         cpu = CPU_PIII;
297                                         break;
298                                 default:
299                                         strcat(cpu_model, "Unknown 80686");
300                                         break;
301                                 }
302                                 break;
303                         case 0xf00:
304                                 strcat(cpu_model, "Pentium 4");
305                                 cpu = CPU_P4;
306                                 break;
307                         default:
308                                 strcat(cpu_model, "unknown");
309                                 break;
310                         }
311
312                         /*
313                          * If we didn't get a brand name from the extended
314                          * CPUID, try to look it up in the brand table.
315                          */
316                         if (cpu_high > 0 && *cpu_brand == '\0') {
317                                 brand_index = cpu_procinfo & CPUID_BRAND_INDEX;
318                                 if (brand_index <= MAX_BRAND_INDEX &&
319                                     cpu_brandtable[brand_index] != NULL)
320                                         strcpy(cpu_brand,
321                                             cpu_brandtable[brand_index]);
322                         }
323                 }
324         } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
325                 /*
326                  * Values taken from AMD Processor Recognition
327                  * http://www.amd.com/K6/k6docs/pdf/20734g.pdf
328                  * (also describes ``Features'' encodings.
329                  */
330                 strcpy(cpu_model, "AMD ");
331                 switch (cpu_id & 0xFF0) {
332                 case 0x410:
333                         strcat(cpu_model, "Standard Am486DX");
334                         break;
335                 case 0x430:
336                         strcat(cpu_model, "Enhanced Am486DX2 Write-Through");
337                         break;
338                 case 0x470:
339                         strcat(cpu_model, "Enhanced Am486DX2 Write-Back");
340                         break;
341                 case 0x480:
342                         strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Through");
343                         break;
344                 case 0x490:
345                         strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Back");
346                         break;
347                 case 0x4E0:
348                         strcat(cpu_model, "Am5x86 Write-Through");
349                         break;
350                 case 0x4F0:
351                         strcat(cpu_model, "Am5x86 Write-Back");
352                         break;
353                 case 0x500:
354                         strcat(cpu_model, "K5 model 0");
355                         tsc_is_broken = 1;
356                         break;
357                 case 0x510:
358                         strcat(cpu_model, "K5 model 1");
359                         break;
360                 case 0x520:
361                         strcat(cpu_model, "K5 PR166 (model 2)");
362                         break;
363                 case 0x530:
364                         strcat(cpu_model, "K5 PR200 (model 3)");
365                         break;
366                 case 0x560:
367                         strcat(cpu_model, "K6");
368                         break;
369                 case 0x570:
370                         strcat(cpu_model, "K6 266 (model 1)");
371                         break;
372                 case 0x580:
373                         strcat(cpu_model, "K6-2");
374                         break;
375                 case 0x590:
376                         strcat(cpu_model, "K6-III");
377                         break;
378                 default:
379                         strcat(cpu_model, "Unknown");
380                         break;
381                 }
382 #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
383                 if ((cpu_id & 0xf00) == 0x500) {
384                         if (((cpu_id & 0x0f0) > 0)
385                             && ((cpu_id & 0x0f0) < 0x60)
386                             && ((cpu_id & 0x00f) > 3))
387                                 enable_K5_wt_alloc();
388                         else if (((cpu_id & 0x0f0) > 0x80)
389                                  || (((cpu_id & 0x0f0) == 0x80)
390                                      && (cpu_id & 0x00f) > 0x07))
391                                 enable_K6_2_wt_alloc();
392                         else if ((cpu_id & 0x0f0) > 0x50)
393                                 enable_K6_wt_alloc();
394                 }
395 #endif
396         } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
397                 strcpy(cpu_model, "Cyrix ");
398                 switch (cpu_id & 0xff0) {
399                 case 0x440:
400                         strcat(cpu_model, "MediaGX");
401                         break;
402                 case 0x520:
403                         strcat(cpu_model, "6x86");
404                         break;
405                 case 0x540:
406                         cpu_class = CPUCLASS_586;
407                         strcat(cpu_model, "GXm");
408                         break;
409                 case 0x600:
410                         strcat(cpu_model, "6x86MX");
411                         break;
412                 default:
413                         /*
414                          * Even though CPU supports the cpuid
415                          * instruction, it can be disabled.
416                          * Therefore, this routine supports all Cyrix
417                          * CPUs.
418                          */
419                         switch (cyrix_did & 0xf0) {
420                         case 0x00:
421                                 switch (cyrix_did & 0x0f) {
422                                 case 0x00:
423                                         strcat(cpu_model, "486SLC");
424                                         break;
425                                 case 0x01:
426                                         strcat(cpu_model, "486DLC");
427                                         break;
428                                 case 0x02:
429                                         strcat(cpu_model, "486SLC2");
430                                         break;
431                                 case 0x03:
432                                         strcat(cpu_model, "486DLC2");
433                                         break;
434                                 case 0x04:
435                                         strcat(cpu_model, "486SRx");
436                                         break;
437                                 case 0x05:
438                                         strcat(cpu_model, "486DRx");
439                                         break;
440                                 case 0x06:
441                                         strcat(cpu_model, "486SRx2");
442                                         break;
443                                 case 0x07:
444                                         strcat(cpu_model, "486DRx2");
445                                         break;
446                                 case 0x08:
447                                         strcat(cpu_model, "486SRu");
448                                         break;
449                                 case 0x09:
450                                         strcat(cpu_model, "486DRu");
451                                         break;
452                                 case 0x0a:
453                                         strcat(cpu_model, "486SRu2");
454                                         break;
455                                 case 0x0b:
456                                         strcat(cpu_model, "486DRu2");
457                                         break;
458                                 default:
459                                         strcat(cpu_model, "Unknown");
460                                         break;
461                                 }
462                                 break;
463                         case 0x10:
464                                 switch (cyrix_did & 0x0f) {
465                                 case 0x00:
466                                         strcat(cpu_model, "486S");
467                                         break;
468                                 case 0x01:
469                                         strcat(cpu_model, "486S2");
470                                         break;
471                                 case 0x02:
472                                         strcat(cpu_model, "486Se");
473                                         break;
474                                 case 0x03:
475                                         strcat(cpu_model, "486S2e");
476                                         break;
477                                 case 0x0a:
478                                         strcat(cpu_model, "486DX");
479                                         break;
480                                 case 0x0b:
481                                         strcat(cpu_model, "486DX2");
482                                         break;
483                                 case 0x0f:
484                                         strcat(cpu_model, "486DX4");
485                                         break;
486                                 default:
487                                         strcat(cpu_model, "Unknown");
488                                         break;
489                                 }
490                                 break;
491                         case 0x20:
492                                 if ((cyrix_did & 0x0f) < 8)
493                                         strcat(cpu_model, "6x86");      /* Where did you get it? */
494                                 else
495                                         strcat(cpu_model, "5x86");
496                                 break;
497                         case 0x30:
498                                 strcat(cpu_model, "6x86");
499                                 break;
500                         case 0x40:
501                                 if ((cyrix_did & 0xf000) == 0x3000) {
502                                         cpu_class = CPUCLASS_586;
503                                         strcat(cpu_model, "GXm");
504                                 } else
505                                         strcat(cpu_model, "MediaGX");
506                                 break;
507                         case 0x50:
508                                 strcat(cpu_model, "6x86MX");
509                                 break;
510                         case 0xf0:
511                                 switch (cyrix_did & 0x0f) {
512                                 case 0x0d:
513                                         strcat(cpu_model, "Overdrive CPU");
514                                         break;
515                                 case 0x0e:
516                                         strcpy(cpu_model, "Texas Instruments 486SXL");
517                                         break;
518                                 case 0x0f:
519                                         strcat(cpu_model, "486SLC/DLC");
520                                         break;
521                                 default:
522                                         strcat(cpu_model, "Unknown");
523                                         break;
524                                 }
525                                 break;
526                         default:
527                                 strcat(cpu_model, "Unknown");
528                                 break;
529                         }
530                         break;
531                 }
532         } else if (strcmp(cpu_vendor, "RiseRiseRise") == 0) {
533                 strcpy(cpu_model, "Rise ");
534                 switch (cpu_id & 0xff0) {
535                 case 0x500:
536                         strcat(cpu_model, "mP6");
537                         break;
538                 default:
539                         strcat(cpu_model, "Unknown");
540                 }
541         } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) {
542                 switch (cpu_id & 0xff0) {
543                 case 0x540:
544                         strcpy(cpu_model, "IDT WinChip C6");
545                         tsc_is_broken = 1;
546                         break;
547                 case 0x580:
548                         strcpy(cpu_model, "IDT WinChip 2");
549                         break;
550                 case 0x660:
551                         strcpy(cpu_model, "VIA C3 Samuel");
552                         break;
553                 case 0x670:
554                         if (cpu_id & 0x8)
555                                 strcpy(cpu_model, "VIA C3 Ezra");
556                         else
557                                 strcpy(cpu_model, "VIA C3 Samuel 2");
558                         break;
559                 case 0x680:
560                         strcpy(cpu_model, "VIA C3 Ezra-T");
561                         break;
562                 case 0x690:
563                         strcpy(cpu_model, "VIA C3 Nehemiah");
564                         break;
565                 case 0x6a0:
566                 case 0x6d0:
567                         strcpy(cpu_model, "VIA C7 Esther");
568                         break;
569                 default:
570                         strcpy(cpu_model, "VIA/IDT Unknown");
571                 }
572         } else if (strcmp(cpu_vendor, "IBM") == 0) {
573                 strcpy(cpu_model, "Blue Lightning CPU");
574         } else if (strcmp(cpu_vendor, "Geode by NSC") == 0) {
575                 switch (cpu_id & 0xfff) {
576                 case 0x540:
577                         strcpy(cpu_model, "Geode SC1100");
578                         cpu = CPU_GEODE1100;
579                         tsc_is_broken = 1;
580                         break;
581                 default:
582                         strcpy(cpu_model, "Geode/NSC unknown");
583                         break;
584                 }
585         }
586
587         /*
588          * Replace cpu_model with cpu_brand minus leading spaces if
589          * we have one.
590          */
591         brand = cpu_brand;
592         while (*brand == ' ')
593                 ++brand;
594         if (*brand != '\0')
595                 strcpy(cpu_model, brand);
596
597 #endif
598
599         printf("%s (", cpu_model);
600         switch(cpu_class) {
601         case CPUCLASS_286:
602                 printf("286");
603                 break;
604         case CPUCLASS_386:
605                 printf("386");
606                 break;
607 #if defined(I486_CPU)
608         case CPUCLASS_486:
609                 printf("486");
610                 bzero_vector = i486_bzero;
611                 break;
612 #endif
613 #if defined(I586_CPU)
614         case CPUCLASS_586:
615                 hw_clockrate = (tsc_freq + 5000) / 1000000;
616                 printf("%jd.%02d-MHz ",
617                        (intmax_t)(tsc_freq + 4999) / 1000000,
618                        (u_int)((tsc_freq + 4999) / 10000) % 100);
619                 printf("586");
620                 break;
621 #endif
622 #if defined(I686_CPU)
623         case CPUCLASS_686:
624                 hw_clockrate = (tsc_freq + 5000) / 1000000;
625                 printf("%jd.%02d-MHz ",
626                        (intmax_t)(tsc_freq + 4999) / 1000000,
627                        (u_int)((tsc_freq + 4999) / 10000) % 100);
628                 printf("686");
629                 break;
630 #endif
631         default:
632                 printf("Unknown");      /* will panic below... */
633         }
634         printf("-class CPU)\n");
635 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
636         if(*cpu_vendor)
637                 printf("  Origin = \"%s\"",cpu_vendor);
638         if(cpu_id)
639                 printf("  Id = 0x%x", cpu_id);
640
641         if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
642             strcmp(cpu_vendor, "AuthenticAMD") == 0 ||
643             strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
644             strcmp(cpu_vendor, "TransmetaCPU") == 0 ||
645             strcmp(cpu_vendor, "RiseRiseRise") == 0 ||
646             strcmp(cpu_vendor, "CentaurHauls") == 0 ||
647             strcmp(cpu_vendor, "Geode by NSC") == 0 ||
648                 ((strcmp(cpu_vendor, "CyrixInstead") == 0) &&
649                  ((cpu_id & 0xf00) > 0x500))) {
650                 printf("  Stepping = %u", cpu_id & 0xf);
651                 if (strcmp(cpu_vendor, "CyrixInstead") == 0)
652                         printf("  DIR=0x%04x", cyrix_did);
653                 if (cpu_high > 0) {
654                         u_int cmp = 1, htt = 1;
655
656                         /*
657                          * Here we should probably set up flags indicating
658                          * whether or not various features are available.
659                          * The interesting ones are probably VME, PSE, PAE,
660                          * and PGE.  The code already assumes without bothering
661                          * to check that all CPUs >= Pentium have a TSC and
662                          * MSRs.
663                          */
664                         printf("\n  Features=0x%b", cpu_feature,
665                         "\020"
666                         "\001FPU"       /* Integral FPU */
667                         "\002VME"       /* Extended VM86 mode support */
668                         "\003DE"        /* Debugging Extensions (CR4.DE) */
669                         "\004PSE"       /* 4MByte page tables */
670                         "\005TSC"       /* Timestamp counter */
671                         "\006MSR"       /* Machine specific registers */
672                         "\007PAE"       /* Physical address extension */
673                         "\010MCE"       /* Machine Check support */
674                         "\011CX8"       /* CMPEXCH8 instruction */
675                         "\012APIC"      /* SMP local APIC */
676                         "\013oldMTRR"   /* Previous implementation of MTRR */
677                         "\014SEP"       /* Fast System Call */
678                         "\015MTRR"      /* Memory Type Range Registers */
679                         "\016PGE"       /* PG_G (global bit) support */
680                         "\017MCA"       /* Machine Check Architecture */
681                         "\020CMOV"      /* CMOV instruction */
682                         "\021PAT"       /* Page attributes table */
683                         "\022PSE36"     /* 36 bit address space support */
684                         "\023PN"        /* Processor Serial number */
685                         "\024CLFLUSH"   /* Has the CLFLUSH instruction */
686                         "\025<b20>"
687                         "\026DTS"       /* Debug Trace Store */
688                         "\027ACPI"      /* ACPI support */
689                         "\030MMX"       /* MMX instructions */
690                         "\031FXSR"      /* FXSAVE/FXRSTOR */
691                         "\032SSE"       /* Streaming SIMD Extensions */
692                         "\033SSE2"      /* Streaming SIMD Extensions #2 */
693                         "\034SS"        /* Self snoop */
694                         "\035HTT"       /* Hyperthreading (see EBX bit 16-23) */
695                         "\036TM"        /* Thermal Monitor clock slowdown */
696                         "\037IA64"      /* CPU can execute IA64 instructions */
697                         "\040PBE"       /* Pending Break Enable */
698                         );
699
700                         if (cpu_feature2 != 0) {
701                                 printf("\n  Features2=0x%b", cpu_feature2,
702                                 "\020"
703                                 "\001SSE3"      /* SSE3 */
704                                 "\002<b1>"
705                                 "\003RSVD2"     /* "Reserved" bit 2 */
706                                 "\004MON"       /* MONITOR/MWAIT Instructions */
707                                 "\005DS_CPL"    /* CPL Qualified Debug Store */
708                                 "\006VMX"       /* Virtual Machine Extensions */
709                                 "\007SMX"       /* Safer Mode Extensions */
710                                 "\010EST"       /* Enhanced SpeedStep */
711                                 "\011TM2"       /* Thermal Monitor 2 */
712                                 "\012SSSE3"     /* SSSE3 */
713                                 "\013CNXT-ID"   /* L1 context ID available */
714                                 "\014<b11>"
715                                 "\015<b12>"
716                                 "\016CX16"      /* CMPXCHG16B Instruction */
717                                 "\017xTPR"      /* Send Task Priority Messages*/
718                                 "\020PDCM"      /* Perf/Debug Capability MSR */
719                                 "\021<b16>"
720                                 "\022<b17>"
721                                 "\023DCA"       /* Direct Cache Access */
722                                 "\024<b19>"
723                                 "\025<b20>"
724                                 "\026<b21>"
725                                 "\027<b22>"
726                                 "\030<b23>"
727                                 "\031<b24>"
728                                 "\032<b25>"
729                                 "\033<b26>"
730                                 "\034<b27>"
731                                 "\035<b28>"
732                                 "\036<b29>"
733                                 "\037<b30>"
734                                 "\040<b31>"
735                                 );
736                         }
737
738                         /*
739                          * AMD64 Architecture Programmer's Manual Volume 3:
740                          * General-Purpose and System Instructions
741                          * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf
742                          *
743                          * IA-32 Intel Architecture Software Developer's Manual,
744                          * Volume 2A: Instruction Set Reference, A-M
745                          * ftp://download.intel.com/design/Pentium4/manuals/25366617.pdf
746                          */
747                         if (amd_feature != 0) {
748                                 printf("\n  AMD Features=0x%b", amd_feature,
749                                 "\020"          /* in hex */
750                                 "\001<s0>"      /* Same */
751                                 "\002<s1>"      /* Same */
752                                 "\003<s2>"      /* Same */
753                                 "\004<s3>"      /* Same */
754                                 "\005<s4>"      /* Same */
755                                 "\006<s5>"      /* Same */
756                                 "\007<s6>"      /* Same */
757                                 "\010<s7>"      /* Same */
758                                 "\011<s8>"      /* Same */
759                                 "\012<s9>"      /* Same */
760                                 "\013<b10>"     /* Undefined */
761                                 "\014SYSCALL"   /* Have SYSCALL/SYSRET */
762                                 "\015<s12>"     /* Same */
763                                 "\016<s13>"     /* Same */
764                                 "\017<s14>"     /* Same */
765                                 "\020<s15>"     /* Same */
766                                 "\021<s16>"     /* Same */
767                                 "\022<s17>"     /* Same */
768                                 "\023<b18>"     /* Reserved, unknown */
769                                 "\024MP"        /* Multiprocessor Capable */
770                                 "\025NX"        /* Has EFER.NXE, NX */
771                                 "\026<b21>"     /* Undefined */
772                                 "\027MMX+"      /* AMD MMX Extensions */
773                                 "\030<s23>"     /* Same */
774                                 "\031<s24>"     /* Same */
775                                 "\032FFXSR"     /* Fast FXSAVE/FXRSTOR */
776                                 "\033<b26>"     /* Undefined */
777                                 "\034RDTSCP"    /* RDTSCP */
778                                 "\035<b28>"     /* Undefined */
779                                 "\036LM"        /* 64 bit long mode */
780                                 "\0373DNow!+"   /* AMD 3DNow! Extensions */
781                                 "\0403DNow!"    /* AMD 3DNow! */
782                                 );
783                         }
784
785                         if (amd_feature2 != 0) {
786                                 printf("\n  AMD Features2=0x%b", amd_feature2,
787                                 "\020"
788                                 "\001LAHF"      /* LAHF/SAHF in long mode */
789                                 "\002CMP"       /* CMP legacy */
790                                 "\003SVM"       /* Secure Virtual Mode */
791                                 "\004ExtAPIC"   /* Extended APIC register */
792                                 "\005CR8"       /* CR8 in legacy mode */
793                                 "\006<b5>"
794                                 "\007<b6>"
795                                 "\010<b7>"
796                                 "\011Prefetch"  /* 3DNow! Prefetch/PrefetchW */
797                                 "\012<b9>"
798                                 "\013<b10>"
799                                 "\014<b11>"
800                                 "\015<b12>"
801                                 "\016<b13>"
802                                 "\017<b14>"
803                                 "\020<b15>"
804                                 "\021<b16>"
805                                 "\022<b17>"
806                                 "\023<b18>"
807                                 "\024<b19>"
808                                 "\025<b20>"
809                                 "\026<b21>"
810                                 "\027<b22>"
811                                 "\030<b23>"
812                                 "\031<b24>"
813                                 "\032<b25>"
814                                 "\033<b26>"
815                                 "\034<b27>"
816                                 "\035<b28>"
817                                 "\036<b29>"
818                                 "\037<b30>"
819                                 "\040<b31>"
820                                 );
821                         }
822
823                         if (cpu_feature & CPUID_HTT && strcmp(cpu_vendor,
824                             "AuthenticAMD") == 0)
825                                 cpu_feature &= ~CPUID_HTT;
826
827                         /*
828                          * If this CPU supports HTT or CMP then mention the
829                          * number of physical/logical cores it contains.
830                          */
831                         if (cpu_feature & CPUID_HTT)
832                                 htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
833                         if (strcmp(cpu_vendor, "AuthenticAMD") == 0 &&
834                             (amd_feature2 & AMDID2_CMP))
835                                 cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
836                         else if (strcmp(cpu_vendor, "GenuineIntel") == 0 &&
837                             (cpu_high >= 4)) {
838                                 cpuid_count(4, 0, regs);
839                                 cmp = ((regs[0] & 0xfc000000) >> 26) + 1;
840                         }
841                         if (cmp > 1)
842                                 printf("\n  Cores per package: %d", cmp);
843                         if ((htt / cmp) > 1)
844                                 printf("\n  Logical CPUs per core: %d",
845                                     htt / cmp);
846                 }
847         } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
848                 printf("  DIR=0x%04x", cyrix_did);
849                 printf("  Stepping=%u", (cyrix_did & 0xf000) >> 12);
850                 printf("  Revision=%u", (cyrix_did & 0x0f00) >> 8);
851 #ifndef CYRIX_CACHE_REALLY_WORKS
852                 if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700)
853                         printf("\n  CPU cache: write-through mode");
854 #endif
855         }
856         if (strcmp(cpu_vendor, "CentaurHauls") == 0)
857                 print_via_padlock_info();
858
859         /* Avoid ugly blank lines: only print newline when we have to. */
860         if (*cpu_vendor || cpu_id)
861                 printf("\n");
862
863 #endif
864
865         if (!bootverbose)
866                 return;
867
868         if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
869                 print_AMD_info();
870         else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 ||
871                  strcmp(cpu_vendor, "TransmetaCPU") == 0)
872                 print_transmeta_info();
873
874 #ifdef I686_CPU
875         /*
876          * XXX - Do PPro CPUID level=2 stuff here?
877          *
878          * No, but maybe in a print_Intel_info() function called from here.
879          */
880 #endif
881 }
882
883 void
884 panicifcpuunsupported(void)
885 {
886
887 #if !defined(lint)
888 #if !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
889 #error This kernel is not configured for one of the supported CPUs
890 #endif
891 #else /* lint */
892 #endif /* lint */
893         /*
894          * Now that we have told the user what they have,
895          * let them know if that machine type isn't configured.
896          */
897         switch (cpu_class) {
898         case CPUCLASS_286:      /* a 286 should not make it this far, anyway */
899         case CPUCLASS_386:
900 #if !defined(I486_CPU)
901         case CPUCLASS_486:
902 #endif
903 #if !defined(I586_CPU)
904         case CPUCLASS_586:
905 #endif
906 #if !defined(I686_CPU)
907         case CPUCLASS_686:
908 #endif
909                 panic("CPU class not configured");
910         default:
911                 break;
912         }
913 }
914
915
916 static  volatile u_int trap_by_rdmsr;
917
918 /*
919  * Special exception 6 handler.
920  * The rdmsr instruction generates invalid opcodes fault on 486-class
921  * Cyrix CPU.  Stacked eip register points the rdmsr instruction in the
922  * function identblue() when this handler is called.  Stacked eip should
923  * be advanced.
924  */
925 inthand_t       bluetrap6;
926 #ifdef __GNUCLIKE_ASM
927 __asm
928 ("                                                                      \n\
929         .text                                                           \n\
930         .p2align 2,0x90                                                 \n\
931         .type   " __XSTRING(CNAME(bluetrap6)) ",@function               \n\
932 " __XSTRING(CNAME(bluetrap6)) ":                                        \n\
933         ss                                                              \n\
934         movl    $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) "            \n\
935         addl    $2, (%esp)      /* rdmsr is a 2-byte instruction */     \n\
936         iret                                                            \n\
937 ");
938 #endif
939
940 /*
941  * Special exception 13 handler.
942  * Accessing non-existent MSR generates general protection fault.
943  */
944 inthand_t       bluetrap13;
945 #ifdef __GNUCLIKE_ASM
946 __asm
947 ("                                                                      \n\
948         .text                                                           \n\
949         .p2align 2,0x90                                                 \n\
950         .type   " __XSTRING(CNAME(bluetrap13)) ",@function              \n\
951 " __XSTRING(CNAME(bluetrap13)) ":                                       \n\
952         ss                                                              \n\
953         movl    $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) "            \n\
954         popl    %eax            /* discard error code */                \n\
955         addl    $2, (%esp)      /* rdmsr is a 2-byte instruction */     \n\
956         iret                                                            \n\
957 ");
958 #endif
959
960 /*
961  * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not
962  * support cpuid instruction.  This function should be called after
963  * loading interrupt descriptor table register.
964  *
965  * I don't like this method that handles fault, but I couldn't get
966  * information for any other methods.  Does blue giant know?
967  */
968 static int
969 identblue(void)
970 {
971
972         trap_by_rdmsr = 0;
973
974         /*
975          * Cyrix 486-class CPU does not support rdmsr instruction.
976          * The rdmsr instruction generates invalid opcode fault, and exception
977          * will be trapped by bluetrap6() on Cyrix 486-class CPU.  The
978          * bluetrap6() set the magic number to trap_by_rdmsr.
979          */
980         setidt(IDT_UD, bluetrap6, SDT_SYS386TGT, SEL_KPL,
981             GSEL(GCODE_SEL, SEL_KPL));
982
983         /*
984          * Certain BIOS disables cpuid instruction of Cyrix 6x86MX CPU.
985          * In this case, rdmsr generates general protection fault, and
986          * exception will be trapped by bluetrap13().
987          */
988         setidt(IDT_GP, bluetrap13, SDT_SYS386TGT, SEL_KPL,
989             GSEL(GCODE_SEL, SEL_KPL));
990
991         rdmsr(0x1002);          /* Cyrix CPU generates fault. */
992
993         if (trap_by_rdmsr == 0xa8c1d)
994                 return IDENTBLUE_CYRIX486;
995         else if (trap_by_rdmsr == 0xa89c4)
996                 return IDENTBLUE_CYRIXM2;
997         return IDENTBLUE_IBMCPU;
998 }
999
1000
1001 /*
1002  * identifycyrix() set lower 16 bits of cyrix_did as follows:
1003  *
1004  *  F E D C B A 9 8 7 6 5 4 3 2 1 0
1005  * +-------+-------+---------------+
1006  * |  SID  |  RID  |   Device ID   |
1007  * |    (DIR 1)    |    (DIR 0)    |
1008  * +-------+-------+---------------+
1009  */
1010 static void
1011 identifycyrix(void)
1012 {
1013         u_int   eflags;
1014         int     ccr2_test = 0, dir_test = 0;
1015         u_char  ccr2, ccr3;
1016
1017         eflags = read_eflags();
1018         disable_intr();
1019
1020         ccr2 = read_cyrix_reg(CCR2);
1021         write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW);
1022         read_cyrix_reg(CCR2);
1023         if (read_cyrix_reg(CCR2) != ccr2)
1024                 ccr2_test = 1;
1025         write_cyrix_reg(CCR2, ccr2);
1026
1027         ccr3 = read_cyrix_reg(CCR3);
1028         write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3);
1029         read_cyrix_reg(CCR3);
1030         if (read_cyrix_reg(CCR3) != ccr3)
1031                 dir_test = 1;                                   /* CPU supports DIRs. */
1032         write_cyrix_reg(CCR3, ccr3);
1033
1034         if (dir_test) {
1035                 /* Device ID registers are available. */
1036                 cyrix_did = read_cyrix_reg(DIR1) << 8;
1037                 cyrix_did += read_cyrix_reg(DIR0);
1038         } else if (ccr2_test)
1039                 cyrix_did = 0x0010;             /* 486S A-step */
1040         else
1041                 cyrix_did = 0x00ff;             /* Old 486SLC/DLC and TI486SXLC/SXL */
1042
1043         write_eflags(eflags);
1044 }
1045
1046 /*
1047  * Final stage of CPU identification. -- Should I check TI?
1048  */
1049 void
1050 finishidentcpu(void)
1051 {
1052         int     isblue = 0;
1053         u_char  ccr3;
1054         u_int   regs[4];
1055
1056         if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
1057                 if (cpu == CPU_486) {
1058                         /*
1059                          * These conditions are equivalent to:
1060                          *     - CPU does not support cpuid instruction.
1061                          *     - Cyrix/IBM CPU is detected.
1062                          */
1063                         isblue = identblue();
1064                         if (isblue == IDENTBLUE_IBMCPU) {
1065                                 strcpy(cpu_vendor, "IBM");
1066                                 cpu = CPU_BLUE;
1067                                 return;
1068                         }
1069                 }
1070                 switch (cpu_id & 0xf00) {
1071                 case 0x600:
1072                         /*
1073                          * Cyrix's datasheet does not describe DIRs.
1074                          * Therefor, I assume it does not have them
1075                          * and use the result of the cpuid instruction.
1076                          * XXX they seem to have it for now at least. -Peter
1077                          */
1078                         identifycyrix();
1079                         cpu = CPU_M2;
1080                         break;
1081                 default:
1082                         identifycyrix();
1083                         /*
1084                          * This routine contains a trick.
1085                          * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now.
1086                          */
1087                         switch (cyrix_did & 0x00f0) {
1088                         case 0x00:
1089                         case 0xf0:
1090                                 cpu = CPU_486DLC;
1091                                 break;
1092                         case 0x10:
1093                                 cpu = CPU_CY486DX;
1094                                 break;
1095                         case 0x20:
1096                                 if ((cyrix_did & 0x000f) < 8)
1097                                         cpu = CPU_M1;
1098                                 else
1099                                         cpu = CPU_M1SC;
1100                                 break;
1101                         case 0x30:
1102                                 cpu = CPU_M1;
1103                                 break;
1104                         case 0x40:
1105                                 /* MediaGX CPU */
1106                                 cpu = CPU_M1SC;
1107                                 break;
1108                         default:
1109                                 /* M2 and later CPUs are treated as M2. */
1110                                 cpu = CPU_M2;
1111
1112                                 /*
1113                                  * enable cpuid instruction.
1114                                  */
1115                                 ccr3 = read_cyrix_reg(CCR3);
1116                                 write_cyrix_reg(CCR3, CCR3_MAPEN0);
1117                                 write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID);
1118                                 write_cyrix_reg(CCR3, ccr3);
1119
1120                                 do_cpuid(0, regs);
1121                                 cpu_high = regs[0];     /* eax */
1122                                 do_cpuid(1, regs);
1123                                 cpu_id = regs[0];       /* eax */
1124                                 cpu_feature = regs[3];  /* edx */
1125                                 break;
1126                         }
1127                 }
1128         } else if (cpu == CPU_486 && *cpu_vendor == '\0') {
1129                 /*
1130                  * There are BlueLightning CPUs that do not change
1131                  * undefined flags by dividing 5 by 2.  In this case,
1132                  * the CPU identification routine in locore.s leaves
1133                  * cpu_vendor null string and puts CPU_486 into the
1134                  * cpu.
1135                  */
1136                 isblue = identblue();
1137                 if (isblue == IDENTBLUE_IBMCPU) {
1138                         strcpy(cpu_vendor, "IBM");
1139                         cpu = CPU_BLUE;
1140                         return;
1141                 }
1142         }
1143 }
1144
1145 static void
1146 print_AMD_assoc(int i)
1147 {
1148         if (i == 255)
1149                 printf(", fully associative\n");
1150         else
1151                 printf(", %d-way associative\n", i);
1152 }
1153
1154 static void
1155 print_AMD_info(void)
1156 {
1157         quad_t amd_whcr;
1158
1159         if (cpu_exthigh >= 0x80000005) {
1160                 u_int regs[4];
1161
1162                 do_cpuid(0x80000005, regs);
1163                 printf("Data TLB: %d entries", (regs[1] >> 16) & 0xff);
1164                 print_AMD_assoc(regs[1] >> 24);
1165                 printf("Instruction TLB: %d entries", regs[1] & 0xff);
1166                 print_AMD_assoc((regs[1] >> 8) & 0xff);
1167                 printf("L1 data cache: %d kbytes", regs[2] >> 24);
1168                 printf(", %d bytes/line", regs[2] & 0xff);
1169                 printf(", %d lines/tag", (regs[2] >> 8) & 0xff);
1170                 print_AMD_assoc((regs[2] >> 16) & 0xff);
1171                 printf("L1 instruction cache: %d kbytes", regs[3] >> 24);
1172                 printf(", %d bytes/line", regs[3] & 0xff);
1173                 printf(", %d lines/tag", (regs[3] >> 8) & 0xff);
1174                 print_AMD_assoc((regs[3] >> 16) & 0xff);
1175                 if (cpu_exthigh >= 0x80000006) {        /* K6-III only */
1176                         do_cpuid(0x80000006, regs);
1177                         printf("L2 internal cache: %d kbytes", regs[2] >> 16);
1178                         printf(", %d bytes/line", regs[2] & 0xff);
1179                         printf(", %d lines/tag", (regs[2] >> 8) & 0x0f);
1180                         print_AMD_assoc((regs[2] >> 12) & 0x0f);        
1181                 }
1182         }
1183         if (((cpu_id & 0xf00) == 0x500)
1184             && (((cpu_id & 0x0f0) > 0x80)
1185                 || (((cpu_id & 0x0f0) == 0x80)
1186                     && (cpu_id & 0x00f) > 0x07))) {
1187                 /* K6-2(new core [Stepping 8-F]), K6-III or later */
1188                 amd_whcr = rdmsr(0xc0000082);
1189                 if (!(amd_whcr & (0x3ff << 22))) {
1190                         printf("Write Allocate Disable\n");
1191                 } else {
1192                         printf("Write Allocate Enable Limit: %dM bytes\n",
1193                             (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4);
1194                         printf("Write Allocate 15-16M bytes: %s\n",
1195                             (amd_whcr & (1 << 16)) ? "Enable" : "Disable");
1196                 }
1197         } else if (((cpu_id & 0xf00) == 0x500)
1198                    && ((cpu_id & 0x0f0) > 0x50)) {
1199                 /* K6, K6-2(old core) */
1200                 amd_whcr = rdmsr(0xc0000082);
1201                 if (!(amd_whcr & (0x7f << 1))) {
1202                         printf("Write Allocate Disable\n");
1203                 } else {
1204                         printf("Write Allocate Enable Limit: %dM bytes\n",
1205                             (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4);
1206                         printf("Write Allocate 15-16M bytes: %s\n",
1207                             (amd_whcr & 0x0001) ? "Enable" : "Disable");
1208                         printf("Hardware Write Allocate Control: %s\n",
1209                             (amd_whcr & 0x0100) ? "Enable" : "Disable");
1210                 }
1211         }
1212 }
1213
1214 static void
1215 print_transmeta_info(void)
1216 {
1217         u_int regs[4], nreg = 0;
1218
1219         do_cpuid(0x80860000, regs);
1220         nreg = regs[0];
1221         if (nreg >= 0x80860001) {
1222                 do_cpuid(0x80860001, regs);
1223                 printf("  Processor revision %u.%u.%u.%u\n",
1224                        (regs[1] >> 24) & 0xff,
1225                        (regs[1] >> 16) & 0xff,
1226                        (regs[1] >> 8) & 0xff,
1227                        regs[1] & 0xff);
1228         }
1229         if (nreg >= 0x80860002) {
1230                 do_cpuid(0x80860002, regs);
1231                 printf("  Code Morphing Software revision %u.%u.%u-%u-%u\n",
1232                        (regs[1] >> 24) & 0xff,
1233                        (regs[1] >> 16) & 0xff,
1234                        (regs[1] >> 8) & 0xff,
1235                        regs[1] & 0xff,
1236                        regs[2]);
1237         }
1238         if (nreg >= 0x80860006) {
1239                 char info[65];
1240                 do_cpuid(0x80860003, (u_int*) &info[0]);
1241                 do_cpuid(0x80860004, (u_int*) &info[16]);
1242                 do_cpuid(0x80860005, (u_int*) &info[32]);
1243                 do_cpuid(0x80860006, (u_int*) &info[48]);
1244                 info[64] = 0;
1245                 printf("  %s\n", info);
1246         }
1247 }
1248
1249 static void
1250 print_via_padlock_info(void)
1251 {
1252         u_int regs[4];
1253
1254         /* Check for supported models. */
1255         switch (cpu_id & 0xff0) {
1256         case 0x690:
1257                 if ((cpu_id & 0xf) < 3)
1258                         return;
1259         case 0x6a0:
1260         case 0x6d0:
1261                 break;
1262         default:
1263                 return;
1264         }
1265         
1266         do_cpuid(0xc0000000, regs);
1267         if (regs[0] >= 0xc0000001)
1268                 do_cpuid(0xc0000001, regs);
1269         else
1270                 return;
1271
1272         printf("\n  VIA Padlock Features=0x%b", regs[3],
1273         "\020"
1274         "\003RNG"               /* RNG */
1275         "\007AES"               /* ACE */
1276         "\011AES-CTR"           /* ACE2 */
1277         "\013SHA1,SHA256"       /* PHE */
1278         "\015RSA"               /* PMM */
1279         );
1280 }