summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1999-03-08 23:47:27 +0000
committerJason Downs <downsj@cvs.openbsd.org>1999-03-08 23:47:27 +0000
commit4d5babe9a53a5ba8e34500bef93832521e116ba6 (patch)
treeb166b51a1410c9cd064f29d5504332b7d65b26c0
parent2492f35aa95abb2800f1632d1049bbc8c334c96f (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.
-rw-r--r--sys/arch/i386/i386/locore.s27
-rw-r--r--sys/arch/i386/i386/machdep.c134
-rw-r--r--sys/arch/i386/include/cpu.h6
-rw-r--r--sys/arch/i386/include/specialreg.h16
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.