diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1999-03-08 23:47:27 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1999-03-08 23:47:27 +0000 |
commit | 4d5babe9a53a5ba8e34500bef93832521e116ba6 (patch) | |
tree | b166b51a1410c9cd064f29d5504332b7d65b26c0 /sys/arch/i386 | |
parent | 2492f35aa95abb2800f1632d1049bbc8c334c96f (diff) |
Add support for CPUID level 2. This is used to determine the L2 cache size
on Intel processors; print out the correct CPU name and cache size at boot.
Also clean up the feature flags, including PPro errata.
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/i386/locore.s | 27 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 134 | ||||
-rw-r--r-- | sys/arch/i386/include/cpu.h | 6 | ||||
-rw-r--r-- | sys/arch/i386/include/specialreg.h | 16 |
4 files changed, 149 insertions, 34 deletions
diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s index 2b0ac84ba1b..78ff759f110 100644 --- a/sys/arch/i386/i386/locore.s +++ b/sys/arch/i386/i386/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.47 1999/02/26 04:34:31 art Exp $ */ +/* $OpenBSD: locore.s,v 1.48 1999/03/08 23:47:26 downsj Exp $ */ /* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */ /*- @@ -141,16 +141,21 @@ .data .globl _cpu,_cpu_id,_cpu_vendor,_cpuid_level,_cpu_feature + .globl _cpu_cache_eax,_cpu_cache_ebx,_cpu_cache_ecx,_cpu_cache_edx .globl _cold,_cnvmem,_extmem,_esym .globl _boothowto,_bootdev,_atdevbase .globl _proc0paddr,_curpcb,_PTDpaddr,_dynamic_gdt .globl _bootapiver, _bootargc, _bootargv _cpu: .long 0 # are we 386, 386sx, 486, 586 or 686 -_cpu_id: .long 0 # saved from `cpuid' instruction +_cpu_id: .long 0 # saved from 'cpuid' instruction _cpu_feature: .long 0 # feature flags from 'cpuid' instruction _cpuid_level: .long -1 # max. level accepted by 'cpuid' instruction -_cpu_vendor: .space 16 # vendor string returned by `cpuid' instruction +_cpu_cache_eax: .long 0 +_cpu_cache_ebx: .long 0 +_cpu_cache_ecx: .long 0 +_cpu_cache_edx: .long 0 +_cpu_vendor: .space 16 # vendor string returned by 'cpuid' instruction _cold: .long 1 # cold till we are not _esym: .long 0 # ptr to end of syms _cnvmem: .long 0 # conventional memory size @@ -376,6 +381,22 @@ try586: /* Use the `cpuid' instruction. */ movl %eax,RELOC(_cpu_id) # store cpu_id and features movl %edx,RELOC(_cpu_feature) + movl $RELOC(_cpuid_level),%eax + cmp $2,%eax + jl 2f + + movl $2,%eax + cpuid +/* + cmp $1,%al + jne 2f +*/ + + movl %eax,RELOC(_cpu_cache_eax) + movl %ebx,RELOC(_cpu_cache_ebx) + movl %ecx,RELOC(_cpu_cache_ecx) + movl %edx,RELOC(_cpu_cache_edx) + 2: /* * Finished with old stack; load new %esp now instead of later so we diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index d5f41799ee4..cd77b846d0d 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.102 1999/02/26 04:41:13 art Exp $ */ +/* $OpenBSD: machdep.c,v 1.103 1999/03/08 23:47:26 downsj Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -251,8 +251,10 @@ int allowaperture = 0; #endif #endif -void cyrix6x86_cpu_setup __P((const char *, int)); -void intel586_cpu_setup __P((const char *, int)); +void cyrix6x86_cpu_setup __P((const char *, int, int)); +void intel586_cpu_setup __P((const char *, int, int)); +void intel686_cpu_setup __P((const char *, int, int)); +char * intel686_cpu_name __P((int)); #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) static __inline u_char @@ -688,11 +690,11 @@ struct cpu_cpuid_nameclass i386_cpuid_cpus[] = { CPUCLASS_686, { 0, "Pentium Pro", 0, "Pentium II", - "Pentium Pro", "Pentium II", "Pentium II", + "Pentium Pro", "Pentium II", "Celeron", "Pentium III", 0, 0, 0, 0, 0, 0, 0, 0, "Pentium Pro" /* Default */ }, - NULL + intel686_cpu_setup } } }, { @@ -788,16 +790,19 @@ struct cpu_cpuid_feature i386_cpuid_features[] = { { CPUID_PGE, "PGE" }, { CPUID_MCA, "MCA" }, { CPUID_CMOV, "CMOV" }, + { CPUID_PAT, "PAT" }, + { CPUID_PSE36, "PSE36" }, + { CPUID_SER, "SER" }, { CPUID_MMX, "MMX" }, - { CPUID_EMMX, "EMMX" }, - { CPUID_3D, "AMD3D" }, - { CPUID_MMX2, "MMX2" } + { CPUID_FXSR, "FXSR" }, + { CPUID_SIMD, "SIMD" }, + { CPUID_3DNOW, "3DNOW" }, }; void -cyrix6x86_cpu_setup(cpu_device, model) +cyrix6x86_cpu_setup(cpu_device, model, step) const char *cpu_device; - int model; + int model, step; { #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) extern int cpu_feature; @@ -828,9 +833,9 @@ cyrix6x86_cpu_setup(cpu_device, model) } void -intel586_cpu_setup(cpu_device, model) +intel586_cpu_setup(cpu_device, model, step) const char *cpu_device; - int model; + int model, step; { #if defined(I586_CPU) fix_f00f(); @@ -839,17 +844,78 @@ intel586_cpu_setup(cpu_device, model) } void +intel686_cpu_setup(cpu_device, model, step) + const char *cpu_device; + int model, step; +{ + extern int cpu_feature; + + /* + * Original PPro returns SYSCALL in CPUID but is non-functional. + * From Intel Application Note #485. + */ + if ((model == 1) && (step < 3)) + cpu_feature &= ~CPUID_SYS2; +} + +char * +intel686_cpu_name(model) + int model; +{ + extern int cpu_cache_edx; + char *ret = NULL; + + switch (model) { + case 5: + switch (cpu_cache_edx & 0xFF) { + case 0x40: + case 0x41: + ret = "Celeron"; + break; + /* 0x42 should not exist in this model. */ + case 0x43: + ret = "Pentium II"; + break; + case 0x44: + case 0x45: + ret = "Pentium II Xeon"; + break; + } + break; + case 7: + switch (cpu_cache_edx & 0xFF) { + /* 0x40 - 0x42 should not exist in this model. */ + case 0x43: + ret = "Pentium III"; + break; + case 0x44: + case 0x45: + ret = "Pentium III Xeon"; + break; + } + break; + } + + return (ret); +} + +void identifycpu() { extern char cpu_vendor[]; extern int cpu_id; extern int cpu_feature; +#ifdef CPUDEBUG + extern int cpu_cache_eax, cpu_cache_ebx, cpu_cache_ecx, cpu_cache_edx; +#else + extern int cpu_cache_edx; +#endif const char *name, *modifier, *vendorname, *token; const char *cpu_device = "cpu0"; int class = CPUCLASS_386, vendor, i, max; - int family, model, step, modif; + int family, model, step, modif, cachesize; struct cpu_cpuid_nameclass *cpup = NULL; - void (*cpu_setup) __P((const char *, int)); + void (*cpu_setup) __P((const char *, int, int)); if (cpuid_level == -1) { #ifdef DIAGNOSTIC @@ -875,6 +941,9 @@ identifycpu() #ifdef CPUDEBUG printf("%s: family %x model %x step %x\n", cpu_device, family, model, step); + printf("%s: cpuid level %d cache eax %x ebx %x ecx %x edx %x\n", + cpu_device, cpuid_level, cpu_cache_eax, cpu_cache_ebx, + cpu_cache_ecx, cpu_cache_edx); #endif for (i = 0; i < max; i++) { @@ -909,7 +978,13 @@ identifycpu() } else if (model > CPU_MAXMODEL) model = CPU_DEFMODEL; i = family - CPU_MINFAMILY; - name = cpup->cpu_family[i].cpu_models[model]; + + /* Special hack for the PentiumII/III series. */ + if ((vendor == CPUVENDOR_INTEL) && (family == 6) + && ((model == 5) || (model == 7))) { + name = intel686_cpu_name(model); + } else + name = cpup->cpu_family[i].cpu_models[model]; if (name == NULL) name = cpup->cpu_family[i].cpu_models[CPU_DEFMODEL]; class = cpup->cpu_family[i].cpu_class; @@ -917,16 +992,31 @@ identifycpu() } } - if (*token) - sprintf(cpu_model, "%s %s%s (\"%s\" %s-class)", vendorname, - modifier, name, token, classnames[class]); - else - sprintf(cpu_model, "%s %s%s (%s-class)", vendorname, modifier, - name, classnames[class]); + /* Find the amount of on-chip L2 cache. Add support for AMD K6-3...*/ + cachesize = -1; + if ((vendor == CPUVENDOR_INTEL) && (cpuid_level >= 2)) { + int intel_cachetable[] = { 0, 128, 256, 512, 1024, 2048 }; + if ((cpu_cache_edx & 0xFF) >= 0x40 + && (cpu_cache_edx & 0xFF) <= 0x45) { + cachesize = intel_cachetable[(cpu_cache_edx & 0xFF) - 0x40]; + } + } + + if (cachesize > -1) { + sprintf(cpu_model, "%s %s%s (%s%s%s%s-class, %dKB L2 cache)", + vendorname, modifier, name, + ((*token) ? "\"" : ""), ((*token) ? token : ""), + ((*token) ? "\" " : ""), classnames[class], cachesize); + } else { + sprintf(cpu_model, "%s %s%s (%s%s%s%s-class)", + vendorname, modifier, name, + ((*token) ? "\"" : ""), ((*token) ? token : ""), + ((*token) ? "\" " : ""), classnames[class]); + } /* configure the CPU if needed */ if (cpu_setup != NULL) - cpu_setup(cpu_device, model); + cpu_setup(cpu_device, model, step); printf("%s: %s", cpu_device, cpu_model); diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h index 150f927211f..41187f703b1 100644 --- a/sys/arch/i386/include/cpu.h +++ b/sys/arch/i386/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.25 1999/02/23 04:10:12 marc Exp $ */ +/* $OpenBSD: cpu.h,v 1.26 1999/03/08 23:47:25 downsj Exp $ */ /* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ /*- @@ -134,7 +134,7 @@ struct cpu_nocpuid_nameclass { const char *cpu_vendorname; const char *cpu_name; int cpu_class; - void (*cpu_setup) __P((const char *, int)); + void (*cpu_setup) __P((const char *, int, int)); }; struct cpu_cpuid_nameclass { @@ -144,7 +144,7 @@ struct cpu_cpuid_nameclass { struct cpu_cpuid_family { int cpu_class; const char *cpu_models[CPU_MAXMODEL+2]; - void (*cpu_setup) __P((const char *, int)); + void (*cpu_setup) __P((const char *, int, int)); } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1]; }; diff --git a/sys/arch/i386/include/specialreg.h b/sys/arch/i386/include/specialreg.h index 22e37f88f5e..d3b8c027aff 100644 --- a/sys/arch/i386/include/specialreg.h +++ b/sys/arch/i386/include/specialreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: specialreg.h,v 1.6 1999/02/24 22:05:15 deraadt Exp $ */ +/* $OpenBSD: specialreg.h,v 1.7 1999/03/08 23:47:25 downsj Exp $ */ /* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */ /*- @@ -93,7 +93,7 @@ #define CPUID_FPU 0x00000001 /* processor has an FPU? */ #define CPUID_VME 0x00000002 /* has virtual mode (%cr4's VME/PVI) */ #define CPUID_DE 0x00000004 /* has debugging extension */ -#define CPUID_PSE 0x00000008 /* has page 4MB page size extension */ +#define CPUID_PSE 0x00000008 /* has 4MB page size extension */ #define CPUID_TSC 0x00000010 /* has time stamp counter */ #define CPUID_MSR 0x00000020 /* has mode specific registers */ #define CPUID_PAE 0x00000040 /* has phys address extension */ @@ -101,15 +101,19 @@ #define CPUID_CX8 0x00000100 /* has CMPXCHG8B instruction */ #define CPUID_APIC 0x00000200 /* has enabled APIC */ #define CPUID_SYS1 0x00000400 /* has SYSCALL/SYSRET inst. (Cyrix) */ -#define CPUID_SYS2 0x00000800 /* has SYSCALL/SYSRET inst. (AMD) */ +#define CPUID_SYS2 0x00000800 /* has SYSCALL/SYSRET inst. (AMD/Intel) */ #define CPUID_MTRR 0x00001000 /* has memory type range register */ #define CPUID_PGE 0x00002000 /* has page global extension */ #define CPUID_MCA 0x00004000 /* has machine check architecture */ #define CPUID_CMOV 0x00008000 /* has CMOVcc instruction */ +#define CPUID_PAT 0x00010000 /* has page attribute table */ +#define CPUID_PSE36 0x00020000 /* has 36bit page size extension */ +#define CPUID_SER 0x00040000 /* has processor serial number */ #define CPUID_MMX 0x00800000 /* has MMX instructions */ -#define CPUID_EMMX 0x01000000 /* has extended MMX (Cyrix) */ -#define CPUID_3D 0x80000000 /* has AMD-3D instructions (AMD) */ -#define CPUID_MMX2 0x02000000 /* has Intel MMX-2 instructions */ +#define CPUID_FXSR 0x01000000 /* has FXRSTOR instruction (Intel) */ +#define CPUID_EMMX 0x01000000 /* has extended MMX (Cyrix; obsolete) */ +#define CPUID_SIMD 0x02000000 /* has SIMD instructions (Intel) */ +#define CPUID_3DNOW 0x80000000 /* has 3DNow! instructions (AMD) */ /* * the following four 3-byte registers control the non-cacheable regions. |