[PATCH] old 486 grade cpu detection(cyrix/nexgen)
From: Hiroshi Miura
Date: Tue May 04 2004 - 07:37:57 EST
Hi Dave,
An old Cyrix and Nexgen 486 base CPU are not identified on 2.6 series kernel.
These CPUs needs to probe a vendor id very-early and magically.
I splited these very-early detection codes from nexgen.c and cyrix.c,
and create new oldcpuident.c as old historical cpu ident.
If setup code(common.c) cannot detect any vendor id on 486 grade cpu,
then it try to do a cyrix and nexgen magical vendor id enabler.
After that, if it detects cx486 or nexgen486 cpu, normal initialization on
cyrix.c or nexgen.c is called by normal scheme.
If it cannot detect these, kernel think it is 'UNKNOWN 486'.
I need to detect cyrix 486 cpu as Cyrix because I try to write
a CPUFreq driver for ZFx86 that is based on Cx486dx2/4 cpu.
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1670.1.2 -> 1.1670.1.3
# arch/i386/kernel/cpu/common.c 1.26 -> 1.27
# arch/i386/kernel/cpu/nexgen.c 1.3 -> 1.4
# arch/i386/kernel/cpu/cyrix.c 1.11 -> 1.11.1.1
# arch/i386/kernel/cpu/Makefile 1.6 -> 1.7
# (new) -> 1.1 arch/i386/kernel/cpu/oldcpuident.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/04/14 torvalds@xxxxxxxxxxxxxxx 1.1801
# Linux 2.6.6-rc1
# --------------------------------------------
# 04/04/15 miura@xxxxxxxxxx 1.1670.1.3
# enable old Cyrix/Nexgen vendor id detection hacks on 486 cpu which have not devid in normal way.
# --------------------------------------------
#
diff -Nru a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile
--- a/arch/i386/kernel/cpu/Makefile Tue May 4 21:11:40 2004
+++ b/arch/i386/kernel/cpu/Makefile Tue May 4 21:11:40 2004
@@ -12,6 +12,7 @@
obj-y += rise.o
obj-y += nexgen.o
obj-y += umc.o
+obj-y += oldcpuident.o
obj-$(CONFIG_X86_MCE) += mcheck/
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c Tue May 4 21:11:40 2004
+++ b/arch/i386/kernel/cpu/common.c Tue May 4 21:11:40 2004
@@ -17,6 +17,7 @@
struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
extern void mcheck_init(struct cpuinfo_x86 *c);
+extern int try_enable_cpuid(struct cpuinfo_x86 *c);
extern int disable_pse;
@@ -164,7 +165,6 @@
}
__setup("nofxsr", x86_fxsr_setup);
-
/* Standard macro to see if a specific flag is changeable */
static inline int flag_is_changeable_p(u32 flag)
{
@@ -235,6 +235,9 @@
if ( xlvl >= 0x80000004 )
get_model_name(c); /* Default name */
}
+ } else { /* no cpuid */
+ try_enable_cpuid(c);
+ get_cpu_vendor(c);
}
}
diff -Nru a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
--- a/arch/i386/kernel/cpu/cyrix.c Tue May 4 21:11:40 2004
+++ b/arch/i386/kernel/cpu/cyrix.c Tue May 4 21:11:40 2004
@@ -336,51 +336,18 @@
return;
}
-/*
- * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
- * by the fact that they preserve the flags across the division of 5/2.
- * PII and PPro exhibit this behavior too, but they have cpuid available.
- */
-
-/*
- * Perform the Cyrix 5/2 test. A Cyrix won't change
- * the flags, while other 486 chips will.
- */
-static inline int test_cyrix_52div(void)
-{
- unsigned int test;
-
- __asm__ __volatile__(
- "sahf\n\t" /* clear flags (%eax = 0x0005) */
- "div %b2\n\t" /* divide 5 by 2 */
- "lahf" /* store flags into %ah */
- : "=a" (test)
- : "0" (5), "q" (2)
- : "cc");
-
- /* AH is 0x02 on Cyrix after the divide.. */
- return (unsigned char) (test >> 8) == 0x02;
-}
-
static void cyrix_identify(struct cpuinfo_x86 * c)
{
- /* Detect Cyrix with disabled CPUID */
- if ( c->x86 == 4 && test_cyrix_52div() ) {
+ /* Actually enable cpuid on the older cyrix */
+ if ( c->x86 == 4 ) {
unsigned char dir0, dir1;
-
- strcpy(c->x86_vendor_id, "CyrixInstead");
- c->x86_vendor = X86_VENDOR_CYRIX;
-
- /* Actually enable cpuid on the older cyrix */
-
+
/* Retrieve CPU revisions */
-
do_cyrix_devid(&dir0, &dir1);
dir0>>=4;
/* Check it is an affected model */
-
if (dir0 == 5 || dir0 == 3)
{
unsigned char ccr3, ccr4;
@@ -395,7 +362,7 @@
local_irq_restore(flags);
}
}
- generic_identify(c);
+
}
static struct cpu_dev cyrix_cpu_dev __initdata = {
diff -Nru a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c
--- a/arch/i386/kernel/cpu/nexgen.c Tue May 4 21:11:40 2004
+++ b/arch/i386/kernel/cpu/nexgen.c Tue May 4 21:11:40 2004
@@ -5,42 +5,11 @@
#include "cpu.h"
-/*
- * Detect a NexGen CPU running without BIOS hypercode new enough
- * to have CPUID. (Thanks to Herbert Oppmann)
- */
-
-static int __init deep_magic_nexgen_probe(void)
-{
- int ret;
-
- __asm__ __volatile__ (
- " movw $0x5555, %%ax\n"
- " xorw %%dx,%%dx\n"
- " movw $2, %%cx\n"
- " divw %%cx\n"
- " movl $0, %%eax\n"
- " jnz 1f\n"
- " movl $1, %%eax\n"
- "1:\n"
- : "=a" (ret) : : "cx", "dx" );
- return ret;
-}
-
static void __init init_nexgen(struct cpuinfo_x86 * c)
{
c->x86_cache_size = 256; /* A few had 1 MB... */
}
-static void nexgen_identify(struct cpuinfo_x86 * c)
-{
- /* Detect NexGen with old hypercode */
- if ( deep_magic_nexgen_probe() ) {
- strcpy(c->x86_vendor_id, "NexGenDriven");
- }
- generic_identify(c);
-}
-
static struct cpu_dev nexgen_cpu_dev __initdata = {
.c_vendor = "Nexgen",
.c_ident = { "NexGenDriven" },
@@ -51,7 +20,7 @@
},
},
.c_init = init_nexgen,
- .c_identify = nexgen_identify,
+ .c_identify = generic_identify,
};
int __init nexgen_init_cpu(void)
diff -Nru a/arch/i386/kernel/cpu/oldcpuident.c b/arch/i386/kernel/cpu/oldcpuident.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/i386/kernel/cpu/oldcpuident.c Tue May 4 21:11:40 2004
@@ -0,0 +1,81 @@
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#include "cpu.h"
+
+/*
+ * This is early identify routine for old (386, 486 level non-intel) CPUs
+ */
+
+
+/*
+ * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
+ * by the fact that they preserve the flags across the division of 5/2.
+ * PII and PPro exhibit this behavior too, but they have cpuid available.
+ */
+
+/*
+ * Perform the Cyrix 5/2 test. A Cyrix won't change
+ * the flags, while other 486 chips will.
+ */
+static inline int test_cyrix_52div(void)
+{
+ unsigned int test;
+
+ __asm__ __volatile__(
+ "sahf\n\t" /* clear flags (%eax = 0x0005) */
+ "div %b2\n\t" /* divide 5 by 2 */
+ "lahf" /* store flags into %ah */
+ : "=a" (test)
+ : "0" (5), "q" (2)
+ : "cc");
+
+ /* AH is 0x02 on Cyrix after the divide.. */
+ return (unsigned char) (test >> 8) == 0x02;
+}
+
+/*
+ * Detect a NexGen CPU running without BIOS hypercode new enough
+ * to have CPUID. (Thanks to Herbert Oppmann)
+ */
+
+static int __init deep_magic_nexgen_probe(void)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ " movw $0x5555, %%ax\n"
+ " xorw %%dx,%%dx\n"
+ " movw $2, %%cx\n"
+ " divw %%cx\n"
+ " movl $0, %%eax\n"
+ " jnz 1f\n"
+ " movl $1, %%eax\n"
+ "1:\n"
+ : "=a" (ret) : : "cx", "dx" );
+ return ret;
+}
+
+
+/* try enabling cpuid for old cyrix and nexgen cpus.
+ * call from common.c if cpu do not have CPUID.
+ */
+
+int __init try_enable_cpuid(struct cpuinfo_x86 * c)
+{
+ /* Detect Cyrix with disabled CPUID */
+ if ( c->x86 == 4 && test_cyrix_52div() ) {
+ strcpy(c->x86_vendor_id, "CyrixInstead");
+ c->x86_vendor = X86_VENDOR_CYRIX;
+ return 1;
+ } else {
+ /* Detect NexGen with old hypercode */
+ if ( deep_magic_nexgen_probe() ) {
+ strcpy(c->x86_vendor_id, "NexGenDriven");
+ return 1;
+ }
+ }
+ return 0;
+}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/