identcpu.c revision 18837
1/*- 2 * Copyright (c) 1992 Terrence R. Lambert. 3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp 38 * $Id: identcpu.c,v 1.5 1996/09/06 23:07:02 phk Exp $ 39 */ 40 41#include "opt_temporary.h" /* for I586_OPTIMIZED_B* */ 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/sysproto.h> 46#include <sys/kernel.h> 47#include <sys/sysctl.h> 48 49#include <machine/cpu.h> 50#include <machine/reg.h> 51#include <machine/psl.h> 52#include <machine/clock.h> 53#include <machine/specialreg.h> 54#include <machine/sysarch.h> 55#include <machine/md_var.h> 56 57/* XXX - should be in header file */ 58extern void (*bcopy_vector) __P((const void *from, void *to, size_t len)); 59extern void (*ovbcopy_vector) __P((const void *from, void *to, size_t len)); 60 61void i486_bzero __P((void *buf, size_t len)); 62void i586_bcopy __P((const void *from, void *to, size_t len)); 63void i586_bzero __P((void *buf, size_t len)); 64 65void identifycpu(void); /* XXX should be in different header file */ 66void earlysetcpuclass(void); 67 68int cpu_class = CPUCLASS_386; /* least common denominator */ 69char machine[] = "i386"; 70SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 71 72static char cpu_model[128]; 73SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); 74 75static struct cpu_nameclass i386_cpus[] = { 76 { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */ 77 { "i386SX", CPUCLASS_386 }, /* CPU_386SX */ 78 { "i386DX", CPUCLASS_386 }, /* CPU_386 */ 79 { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ 80 { "i486DX", CPUCLASS_486 }, /* CPU_486 */ 81 { "Pentium", CPUCLASS_586 }, /* CPU_586 */ 82 { "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */ 83 { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */ 84}; 85 86void 87identifycpu(void) 88{ 89 cpu_class = i386_cpus[cpu].cpu_class; 90 printf("CPU: "); 91 strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model); 92 93#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 94 if (!strcmp(cpu_vendor,"GenuineIntel")) { 95 if ((cpu_id & 0xf00) > 3) { 96 cpu_model[0] = '\0'; 97 98 switch (cpu_id & 0x3000) { 99 case 0x1000: 100 strcpy(cpu_model, "Overdrive "); 101 break; 102 case 0x2000: 103 strcpy(cpu_model, "Dual "); 104 break; 105 } 106 107 switch (cpu_id & 0xf00) { 108 case 0x400: 109 strcat(cpu_model, "i486 "); 110 break; 111 case 0x500: 112 strcat(cpu_model, "Pentium"); /* nb no space */ 113 break; 114 case 0x600: 115 strcat(cpu_model, "Pentium Pro"); 116 break; 117 default: 118 strcat(cpu_model, "unknown"); 119 break; 120 } 121 122 switch (cpu_id & 0xff0) { 123 case 0x400: 124 strcat(cpu_model, "DX"); break; 125 case 0x410: 126 strcat(cpu_model, "DX"); break; 127 case 0x420: 128 strcat(cpu_model, "SX"); break; 129 case 0x430: 130 strcat(cpu_model, "DX2"); break; 131 case 0x440: 132 strcat(cpu_model, "SL"); break; 133 case 0x450: 134 strcat(cpu_model, "SX2"); break; 135 case 0x470: 136 strcat(cpu_model, "DX2 Write-Back Enhanced"); 137 break; 138 case 0x480: 139 strcat(cpu_model, "DX4"); break; 140 break; 141 } 142 } 143 } else if (!strcmp(cpu_vendor,"AuthenticAMD")) { 144 cpu_model[0] = '\0'; 145 strcpy(cpu_model, "AMD "); 146 switch (cpu_id & 0xF0) { 147 case 0xE0: 148 strcat(cpu_model, "Am5x86 Write-Through"); 149 break; 150 case 0xF0: 151 strcat(cpu_model, "Am5x86 Write-Back"); 152 break; 153 default: 154 strcat(cpu_model, "Unknown"); 155 break; 156 } 157 } 158#endif 159 printf("%s (", cpu_model); 160 switch(cpu_class) { 161 case CPUCLASS_286: 162 printf("286"); 163 break; 164#if defined(I386_CPU) 165 case CPUCLASS_386: 166 printf("386"); 167 break; 168#endif 169#if defined(I486_CPU) 170 case CPUCLASS_486: 171 printf("486"); 172 bzero = i486_bzero; 173 break; 174#endif 175#if defined(I586_CPU) 176 case CPUCLASS_586: 177 printf("%d.%02d-MHz ", 178 (i586_ctr_freq + 4999) / 1000000, 179 ((i586_ctr_freq + 4999) / 10000) % 100); 180 printf("586"); 181#ifdef I586_OPTIMIZED_BCOPY 182 bcopy_vector = i586_bcopy; 183 ovbcopy_vector = i586_bcopy; 184#endif 185#ifdef I586_OPTIMIZED_BZERO 186 bzero = i586_bzero; 187#endif 188 break; 189#endif 190#if defined(I686_CPU) 191 case CPUCLASS_686: 192 printf("%d.%02d-MHz ", 193 (i586_ctr_freq + 4999) / 1000000, 194 ((i586_ctr_freq + 4999) / 10000) % 100); 195 printf("686"); 196 break; 197#endif 198 default: 199 printf("unknown"); /* will panic below... */ 200 } 201 printf("-class CPU)\n"); 202#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 203 if(*cpu_vendor) 204 printf(" Origin = \"%s\"",cpu_vendor); 205 if(cpu_id) 206 printf(" Id = 0x%lx",cpu_id); 207 208 if (!strcmp(cpu_vendor, "GenuineIntel")) { 209 printf(" Stepping=%ld", cpu_id & 0xf); 210 if (cpu_high > 0) { 211 /* 212 * Here we should probably set up flags indicating 213 * whether or not various features are available. 214 * The interesting ones are probably VME, PSE, PAE, 215 * and PGE. The code already assumes without bothering 216 * to check that all CPUs >= Pentium have a TSC and 217 * MSRs. 218 */ 219 printf("\n Features=0x%b", cpu_feature, 220 "\020" 221 "\001FPU" 222 "\002VME" 223 "\003DE" 224 "\004PSE" 225 "\005TSC" 226 "\006MSR" 227 "\007PAE" 228 "\010MCE" 229 "\011CX8" 230 "\012APIC" 231 "\013<b10>" 232 "\014<b11>" 233 "\015MTRR" 234 "\016PGE" 235 "\017MCA" 236 "\020CMOV" 237 ); 238 } 239 } 240 /* Avoid ugly blank lines: only print newline when we have to. */ 241 if (*cpu_vendor || cpu_id) 242 printf("\n"); 243#endif 244#ifdef I686_CPU 245 /* 246 * XXX - Do PPro CPUID level=2 stuff here? 247 */ 248#endif 249 250 /* 251 * Now that we have told the user what they have, 252 * let them know if that machine type isn't configured. 253 */ 254 switch (cpu_class) { 255 case CPUCLASS_286: /* a 286 should not make it this far, anyway */ 256#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU) 257#error This kernel is not configured for one of the supported CPUs 258#endif 259#if !defined(I386_CPU) 260 case CPUCLASS_386: 261#endif 262#if !defined(I486_CPU) 263 case CPUCLASS_486: 264#endif 265#if !defined(I586_CPU) 266 case CPUCLASS_586: 267#endif 268#if !defined(I686_CPU) 269 case CPUCLASS_686: 270#endif 271 panic("CPU class not configured"); 272 default: 273 break; 274 } 275} 276 277/* 278 * This routine is called specifically to set up cpu_class before 279 * startrtclock() uses it. Probably this should be rearranged so that 280 * startrtclock() doesn't need to run until after identifycpu() has been 281 * called. Another alternative formulation would be for this routine 282 * to do all the identification work, and make identifycpu() into a 283 * printing-only routine. 284 */ 285void 286earlysetcpuclass(void) 287{ 288 cpu_class = i386_cpus[cpu].cpu_class; 289} 290