Re: Cyrix 6x86MX and Centaur C6 CPUs in 2.1.102

Trevor Johnson (trevor@jpj.net)
Tue, 19 May 1998 22:11:06 -0700 (PDT)


Linus Torvalds wrote:

> Ok, this looks otherwise ok, but the badtsc capability mustn't be in the
> same word as the other capabilities, because that will result in problems
> in the future when intel adds new capability masks in their hardware.

OK. I took that out.

> So I'd really like to see a "anti-capability" mask. So you'd have

> X86_BUG_WP 1 /* WP doesn't work in supervisor mode */

> Would you be willing to re-do the patch with something like the above?

I started, but don't know how to do the inline assembly in
include/asm-i386/bugs.h. Below is what I have (it's also at
http://jpj.net/~trevor/linux/x86_capability-2.1.102v2.diff). It should
not compile.

This patch has a corrected test for which CPUs are likely to have the bad
TSC, based on information from Alan Cox and Phil Jaenke. It also has a
correction, from Michael Chastain, to the sep_bug test.
___
Trevor Johnson

NB: this is not supposed to compile.

diff -ru linux-2.1.102.orig/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- linux-2.1.102.orig/arch/i386/kernel/mtrr.c Sun May 3 11:58:36 1998
+++ linux/arch/i386/kernel/mtrr.c Tue May 19 21:33:36 1998
@@ -148,8 +148,6 @@
#define TRUE 1
#define FALSE 0

-#define X86_FEATURE_MTRR 0x1000 /* memory type registers */
-
#define MTRRcap_MSR 0x0fe
#define MTRRdefType_MSR 0x2ff

diff -ru linux-2.1.102.orig/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.1.102.orig/arch/i386/kernel/setup.c Wed May 13 11:47:26 1998
+++ linux/arch/i386/kernel/setup.c Tue May 19 21:39:45 1998
@@ -8,7 +8,7 @@
*/

/*
- * This file handles the architecture-dependent parts of initialization
+ * This file handles the architecture-dependent parts of initialization.
*/

#include <linux/errno.h>
@@ -32,19 +32,20 @@
#ifdef CONFIG_BLK_DEV_RAM
#include <linux/blk.h>
#endif
+#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/smp.h>

/*
- * Machine setup..
+ * Machine setup
*/

char ignore_irq13 = 0; /* set if exception 16 works */
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };

/*
- * Bus types ..
+ * Bus types
*/
int EISA_bus = 0;
int MCA_bus = 0;
@@ -172,7 +173,7 @@
if (to != command_line) to--;
if (!memcmp(from+4, "nopentium", 9)) {
from += 9+4;
- boot_cpu_data.x86_capability &= ~8;
+ boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
} else {
memory_end = simple_strtoul(from+4, &from, 0);
if ( *from == 'K' || *from == 'k' ) {
@@ -210,7 +211,7 @@
}
#endif

- /* request io space for devices used on all i[345]86 PC'S */
+ /* request I/O space for devices used on all i[345]86 PCs */
request_region(0x00,0x20,"dma1");
request_region(0x40,0x20,"timer");
request_region(0x80,0x10,"dma page reg");
@@ -238,9 +239,6 @@
int nr = c->x86_model;
char *buf = c->x86_model_id;

- /* Cyrix claims they have a TSC, but it is broken */
- c->x86_capability &= ~16;
-
/* Note that some of the possibilities this decoding allows
* have never actually been manufactured - but those that
* do actually exist are correctly decoded.
@@ -264,7 +262,7 @@
} else if (nr >= 0x20 && nr <= 0x4f) { /* 5x86, 6x86 or Gx86 */
char *s = "";
if (nr >= 0x30 && nr < 0x40) { /* 6x86 */
- if (c->x86 == 5 && (c->x86_capability & (1 << 8)))
+ if (c->x86 == 5 && (c->x86_capability & X86_FEATURE_CXS))
s = "L"; /* 6x86L */
else if (c->x86 == 6)
s = "MX"; /* 6x86MX */
@@ -477,10 +475,20 @@
sep_bug = c->x86_vendor == X86_VENDOR_INTEL &&
c->x86 == 0x06 &&
c->cpuid_level >= 0 &&
- (c->x86_capability & 0x800) &&
+ (c->x86_capability & X86_FEATURE_SEP) &&
c->x86_model < 3 &&
c->x86_mask < 3;

+ /* RDTSC problems on Cyrix 6x86MXs prior to step 0, rev 3
+ and on Winchip C6s with stepping 0 */
+ tsc_bug = (c->x86_capability & X86_FEATURE_TSC) &&
+ ((c->x86_vendor == X86_VENDOR_CYRIX &&
+ c->x86_model == 6 && !(c->x86_mask >> 4) &&
+ (c->x86_mask & 0x0f < 3)) ||
+ (c->x86_vendor == X86_VENDOR_CENTAUR &&
+ c->x86_mask == 0));
+ if (tsc_bug) c->x86_bugs |= X86_BUG_TSC;
+
p += sprintf(p, "fdiv_bug\t: %s\n"
"hlt_bug\t\t: %s\n"
"sep_bug\t\t: %s\n"
@@ -490,10 +498,11 @@
"cpuid level\t: %d\n"
"wp\t\t: %s\n"
"flags\t\t:",
- c->fdiv_bug ? "yes" : "no",
+ (c->x86_bugs & X86_BUG_FDIV) ? "yes" : "no",
c->hlt_works_ok ? "no" : "yes",
sep_bug ? "yes" : "no",
c->f00f_bug ? "yes" : "no",
+ (c->x86_bugs & X86_BUG_TSC) ? "yes" : "no",
c->hard_math ? "yes" : "no",
(c->hard_math && ignore_irq13) ? "yes" : "no",
c->cpuid_level,
diff -ru linux-2.1.102.orig/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- linux-2.1.102.orig/arch/i386/kernel/smp.c Thu May 14 09:43:35 1998
+++ linux/arch/i386/kernel/smp.c Tue May 19 21:33:37 1998
@@ -603,6 +603,7 @@
/*
* Mask B, Pentium, but not Pentium MMX
*/
+/* XXX to do--change to use x86_bugs */
if (c->x86_vendor == X86_VENDOR_INTEL &&
c->x86 == 5 &&
c->x86_mask >= 1 && c->x86_mask <= 4 &&
diff -ru linux-2.1.102.orig/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- linux-2.1.102.orig/arch/i386/kernel/time.c Wed May 13 13:23:13 1998
+++ linux/arch/i386/kernel/time.c Tue May 19 21:33:37 1998
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/smp.h>

+#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -525,7 +526,8 @@
xtime.tv_usec = 0;

/* If we have the CPU hardware time counters, use them */
- if (boot_cpu_data.x86_capability & 16) {
+ if (boot_cpu_data.x86_capability & X86_FEATURE_TSC &&
+ !boot_cpu_data.x86_bugs && X86_BUG_TSC) {
do_gettimeoffset = do_fast_gettimeoffset;
do_get_fast_time = do_x86_get_fast_time;

diff -ru linux-2.1.102.orig/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- linux-2.1.102.orig/arch/i386/mm/init.c Tue Apr 28 13:04:00 1998
+++ linux/arch/i386/mm/init.c Tue May 19 21:33:37 1998
@@ -22,6 +22,7 @@
#include <linux/blk.h>
#endif

+#include <asm/processor.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -115,23 +116,6 @@
#define X86_CR4_MCE 0x0040 /* Machine check enable */
#define X86_CR4_PGE 0x0080 /* enable global pages */
#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */
-
-#define X86_FEATURE_FPU 0x0001 /* internal FPU */
-#define X86_FEATURE_VME 0x0002 /* vm86 extensions */
-#define X86_FEATURE_DE 0x0004 /* debugging extensions */
-#define X86_FEATURE_PSE 0x0008 /* Page size extensions */
-#define X86_FEATURE_TSC 0x0010 /* Time stamp counter */
-#define X86_FEATURE_MSR 0x0020 /* RDMSR/WRMSR */
-#define X86_FEATURE_PAE 0x0040 /* Physical address extension */
-#define X86_FEATURE_MCE 0x0080 /* Machine check exception */
-#define X86_FEATURE_CXS 0x0100 /* cmpxchg8 available */
-#define X86_FEATURE_APIC 0x0200 /* internal APIC */
-#define X86_FEATURE_10 0x0400
-#define X86_FEATURE_11 0x0800
-#define X86_FEATURE_MTRR 0x1000 /* memory type registers */
-#define X86_FEATURE_PGE 0x2000 /* Global page */
-#define X86_FEATURE_MCA 0x4000 /* Machine Check Architecture */
-#define X86_FEATURE_CMOV 0x8000 /* Cmov/fcomi */

/*
* Save the cr4 feature set we're using (ie
diff -ru linux-2.1.102.orig/drivers/char/hfmodem/refclock.c linux/drivers/char/hfmodem/refclock.c
--- linux-2.1.102.orig/drivers/char/hfmodem/refclock.c Thu May 7 23:50:19 1998
+++ linux/drivers/char/hfmodem/refclock.c Tue May 19 21:33:38 1998
@@ -30,6 +30,7 @@
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/hfmodem.h>
+#include <asm/processor.h>

/* --------------------------------------------------------------------- */

@@ -67,10 +68,10 @@
#ifdef __i386__
__initfunc(static void i386_capability(void))
{
- if (boot_cpu_data.x86_capability & 0x10)
+ if (boot_cpu_data.x86_capability & X86_FEATURE_TSC))
rdtsc_ok = 1;
else
- printk(KERN_INFO "%s: cpu does not support the rdtsc instruction\n", hfmodem_drvname);
+ printk(KERN_INFO "%s: CPU does not support the rdtsc instruction\n", hfmodem_drvname);
}
#endif /* __i386__ */

diff -ru linux-2.1.102.orig/drivers/char/random.c linux/drivers/char/random.c
--- linux-2.1.102.orig/drivers/char/random.c Wed May 6 10:56:03 1998
+++ linux/drivers/char/random.c Tue May 19 21:33:38 1998
@@ -237,6 +237,7 @@
#include <linux/poll.h>
#include <linux/init.h>

+#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -585,7 +586,7 @@
begin_benchmark(&timer_benchmark);
#endif
#if defined (__i386__)
- if (boot_cpu_data.x86_capability & 16) {
+ if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
unsigned long low, high;
__asm__(".byte 0x0f,0x31"
:"=a" (low), "=d" (high));
diff -ru linux-2.1.102.orig/drivers/net/hamradio/soundmodem/sm.h linux/drivers/net/hamradio/soundmodem/sm.h
--- linux-2.1.102.orig/drivers/net/hamradio/soundmodem/sm.h Mon Jun 16 16:35:56 1997
+++ linux/drivers/net/hamradio/soundmodem/sm.h Tue May 19 21:33:39 1998
@@ -32,6 +32,7 @@

#include <linux/hdlcdrv.h>
#include <linux/soundmodem.h>
+#include <asm/processor.h>

#define SM_DEBUG

@@ -293,7 +294,7 @@

extern int sm_x86_capability;

-#define HAS_RDTSC (sm_x86_capability & 0x10)
+#define HAS_RDTSC (sm_x86_capability & (X86_FEATURE_TSC)

/*
* only do 32bit cycle counter arithmetic; we hope we won't overflow :-)
diff -ru linux-2.1.102.orig/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- linux-2.1.102.orig/include/asm-i386/bugs.h Thu May 14 14:37:47 1998
+++ linux/include/asm-i386/bugs.h Tue May 19 21:33:39 1998
@@ -95,12 +95,12 @@
"fistpl %0\n\t"
"fwait\n\t"
"fninit"
- : "=m" (*&boot_cpu_data.fdiv_bug)
+ : "=m" (*&boot_cpu_data.fdiv_bug) # XXX needs fixing, should set X86_BUG_FDIV bit in boot_cpu_data.x86_bugs
: "m" (*&x), "m" (*&y));
- if (!boot_cpu_data.fdiv_bug)
- printk("Ok, fpu using exception 16 error reporting.\n");
+ if (c->x86_bugs & X86_BUG_FDIV)
+ printk("Hmm, FPU using exception 16 error reporting with FDIV bug.\n");
else
- printk("Hmm, fpu using exception 16 error reporting with FDIV bug.\n");
+printk("Ok, FPU using exception 16 error reporting.\n");
}

__initfunc(static void check_hlt(void))
diff -ru linux-2.1.102.orig/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- linux-2.1.102.orig/include/asm-i386/processor.h Tue Apr 14 12:54:05 1998
+++ linux/include/asm-i386/processor.h Tue May 19 21:33:39 1998
@@ -31,7 +31,7 @@
__u32 x86_capability;
char x86_vendor_id[16];
char x86_model_id[64];
- int fdiv_bug;
+ __u32 x86_bugs; /* flags for various bugs */
int f00f_bug;
unsigned long loops_per_sec;
};
@@ -43,6 +43,55 @@
#define X86_VENDOR_NEXGEN 4
#define X86_VENDOR_CENTAUR 5
#define X86_VENDOR_UNKNOWN 0xff
+
+/*
+ * capabilities of CPUs
+ */
+
+#define X86_FEATURE_FPU 0x1 /* internal FPU */
+#define X86_FEATURE_VME 0x2 /* vm86 extensions */
+#define X86_FEATURE_DE 0x4 /* debugging extensions */
+#define X86_FEATURE_PSE 0x8 /* Page size extensions */
+#define X86_FEATURE_TSC 0x10 /* Time stamp counter */
+#define X86_FEATURE_MSR 0x20 /* RDMSR/WRMSR */
+#define X86_FEATURE_PAE 0x40 /* Physical address extension */
+#define X86_FEATURE_MCE 0x80 /* Machine check exception */
+#define X86_FEATURE_CXS 0x100 /* cmpxchg8 available */
+#define X86_FEATURE_APIC 0x200 /* internal APIC */
+#define X86_FEATURE_10 0x400
+#define X86_FEATURE_SEP 0x800
+#define X86_FEATURE_MTRR 0x1000 /* memory type range registers */
+#define X86_FEATURE_PGE 0x2000 /* Global page */
+#define X86_FEATURE_MCA 0x4000 /* Machine Check Architecture */
+#define X86_FEATURE_CMOV 0x8000 /* Cmov/fcomi */
+#define X86_FEATURE_FCMOV 0x10000
+#define X86_FEATURE_17 0x20000
+#define X86_FEATURE_18 0x40000
+#define X86_FEATURE_19 0x80000
+#define X86_FEATURE_20 0x100000
+#define X86_FEATURE_21 0x200000
+#define X86_FEATURE_22 0x400000
+#define X86_FEATURE_MMX 0x800000 /* multimedia extensions */
+#define X86_FEATURE_OSFXSR 0x1000000
+#define X86_FEATURE_25 0x2000000
+#define X86_FEATURE_26 0x4000000
+#define X86_FEATURE_27 0x8000000
+#define X86_FEATURE_28 0x10000000
+#define X86_FEATURE_29 0x20000000
+#define X86_FEATURE_30 0x40000000
+#define X86_FEATURE_AMD3D 0x80000000
+
+/*
+ * bugs in CPUs
+ */
+
+#define X86_BUG_WP 0x1 /* WP doesn't work in supervisor mode */
+#define X86_BUG_HLT 0x2 /* "hlt" can hang */
+#define X86_BUG_IRQ13 0x4 /* exception 16 doesn't work */
+#define X86_BUG_FDIV 0x8 /* FPU is subtly broken */
+#define X86_BUG_POPAD 0x10 /* popad can crash the machine */
+#define X86_BUG_F00F 0x20 /* F0 0F can hang the machine */
+#define X86_BUG_TSC 0x40 /* TSC doesn't increment reliably */

extern struct cpuinfo_x86 boot_cpu_data;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu