diff -u -r linux.orig/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- linux.orig/arch/i386/kernel/head.S	Mon Mar 18 12:15:00 1996
+++ linux/arch/i386/kernel/head.S	Mon Nov 17 05:40:07 1997
@@ -109,7 +109,71 @@
  * apply at our cpl of 0 and the stack ought to be aligned already, and
  * we don't need to preserve eflags.
  */
-	movl $3, SYMBOL_NAME(x86)
+	/*
+	 * A Cyrix/IBM 6x86(L) preserves flags after dividing 5 by 2
+	 * (and it _must_ be 5 divided by 2) while other CPUs change
+	 * them in undefined ways. We need to know this since we may
+	 * need to enable the CPUID instruction at least.
+	 */
+	xor %ax,%ax
+	sahf
+	movb $5,%ax
+	movb $2,%bx
+	div %bl
+	lahf
+	cmpb $2,%ah
+	jne ncyrix
+
+	/*
+	 * It behaves like a Cyrix/IBM 6x86(L) so put "Cyrix" in the 
+	 * vendor id field. It may be overwritten later with the 
+	 * real thing if CPUID works.
+	 */
+	movl $0x69727943,SYMBOL_NAME(x86_vendor_id)	# low 4 chars
+	movl $0x00000078,SYMBOL_NAME(x86_vendor_id)+4	# next 4 chars
+
+	/*
+	 * N.B. The pattern of accesses to 0x22 and 0x23 is *essential*
+	 *      so do not try to "optimize" it! For the same reason we
+	 *	do all this with interrupts off.
+	 */
+#define setCx86(reg, val) \
+	movb reg,%ax;	\
+	outb %ax,$0x22;	\
+	movb val,%ax;	\
+	outb %ax,$0x23
+
+#define getCx86(reg) \
+	movb reg,%ax;	\
+	outb %ax,$0x22;	\
+	inb $0x23,%ax
+
+	cli
+	getCx86($0xc3)		# get CCR3
+	movb %ax,%cx		# Save old value
+	movb %ax,%bx
+	andb $0x0f,%bx		# Enable access to all config registers
+	orb $0x10,%bx		# by setting bit 4
+	setCx86($0xc3,%bx)
+
+	getCx86($0xe8)		# now we can get CCR4
+	orb $0x80,%ax		# and set bit 7 (CPUIDEN)
+	movb %ax,%bx		# to enable CPUID execution
+	setCx86($0xe8,%bx)
+
+        getCx86($0xfe)          # DIR0 : let's check this is a 6x86(L)
+        andb $0xf0,%ax		# should be 3xh
+	cmpb $0x30,%ax		# 
+	jne n6x86
+        getCx86($0xe9)          # CCR5 : we reset the SLOP bit
+        andb $0xfd,%ax		# so that udelay calculation
+        movb %ax,%bx		# is correct on 6x86(L) CPUs
+        setCx86($0xe9,%bx)
+
+n6x86:	setCx86($0xc3,%cx)	# Restore old CCR3
+	sti
+
+ncyrix:	movl $3, SYMBOL_NAME(x86)
 	pushfl			# push EFLAGS
 	popl %eax		# get EFLAGS
 	movl %eax,%ecx		# save original EFLAGS
@@ -146,8 +210,20 @@
 	andb $0x0f, %cl		# mask mask revision
 	movb %cl,SYMBOL_NAME(x86_mask)
 	movl %edx,SYMBOL_NAME(x86_capability)
+
+	xor %ax,%ax		# test again for Cyrix CPU
+	sahf
+	movb $5,%ax
+	movb $2,%bx
+	div %bl
+	lahf
+	cmpb $2,%ah
+	jne ncyrx2		# skip if not Cyrix CPU
+        getCx86($0xff)          # DIR1 : let's check the stepping
+	movb %al,SYMBOL_NAME(x86_mask)
+
 	/* get vendor info */
-	xorl %eax, %eax			# call CPUID with 0 -> return vendor ID
+ncyrx2:	xorl %eax, %eax			# call CPUID with 0 -> return vendor ID
 	.byte 0x0f, 0xa2		# CPUID
 	movl %ebx,SYMBOL_NAME(x86_vendor_id)	# lo 4 chars
 	movl %edx,SYMBOL_NAME(x86_vendor_id)+4	# next 4 chars
diff -u -r linux.orig/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux.orig/arch/i386/kernel/setup.c	Fri Sep 20 16:00:34 1996
+++ linux/arch/i386/kernel/setup.c	Mon Nov 17 06:31:55 1997
@@ -46,6 +46,11 @@
 
 char x86_vendor_id[13] = "unknown";
 
+unsigned char Cx86_step = 0;
+static const char *Cx86_type[] = {
+	"unknown", "1.3", "1.4", "2.4", "2.5", "2.6", "2.7 or 3.7", "4.2"
+	};
+
 char ignore_irq13 = 0;		/* set if exception 16 works */
 char wp_works_ok = -1;		/* set if paging hardware honours WP */ 
 char hlt_works_ok = 1;		/* set if the "hlt" instruction works */
@@ -225,6 +230,50 @@
 	return NULL;
 }
 
+static const char * Cx86model(void)
+{
+	unsigned char nr6x86 = 0;
+	static const char *model[] = {
+		"unknown", "6x86", "6x86L", "6x86MX", "6x86MXi"
+	};
+	switch (x86) {
+		case 5:
+			nr6x86 = ((x86_capability & (1 << 8)) ? 2 : 1); /* cx8 flag only on 6x86L */
+			break;
+		case 6:
+			nr6x86 = 3;
+			break;
+		default:
+			nr6x86 = 0;
+	}
+	switch (x86_mask) {
+		case 0x03:
+			Cx86_step =  1;	/* 6x86MX Rev 1.3 */
+			break;
+		case 0x04:
+			Cx86_step =  2;	/* 6x86MX Rev 1.4 */
+			break;
+		case 0x14:
+			Cx86_step =  3;	/* 6x86 Rev 2.4 */
+			break;
+		case 0x15:
+			Cx86_step =  4;	/* 6x86 Rev 2.5 */
+			break;
+		case 0x16:
+			Cx86_step =  5;	/* 6x86 Rev 2.6 */
+			break;
+		case 0x17:
+			Cx86_step =  6;	/* 6x86 Rev 2.7 or 3.7 */
+			break;
+		case 0x22:
+			Cx86_step =  7;	/* 6x86L Rev 4.2 */
+			break;
+		default:
+			Cx86_step = 0;
+	}
+	return model[nr6x86];
+}
+
 static const char * i686model(unsigned int nr)
 {
 	static const char *model[] = {
@@ -239,16 +288,20 @@
 {
         const char *p = NULL;
         static char nbuf[12];
-	switch (x86) {
-		case 4:
-			p = i486model(model);
-			break;
-		case 5:
-			p = i586model(model);
-			break;
-		case 6:
-			p = i686model(model);
-			break;
+	if (strncmp(x86_vendor_id, "Cyrix", 5) == 0)
+		p = Cx86model();
+	else {
+		switch (x86) {
+			case 4:
+				p = i486model(model);
+				break;
+			case 5:
+				p = i586model(model);
+				break;
+			case 6:
+				p = i686model(model);
+				break;
+		}
 	}
         if (p)
                 return p;
@@ -296,9 +349,16 @@
                                        CD(x86_vendor_id));
         
                         if (CD(x86_mask))
-                                len += sprintf(buffer+len,
-                                               "stepping\t: %d\n",
-                                               CD(x86_mask));
+                                if (strncmp(x86_vendor_id, "Cyrix", 5) != 0) {
+                                	len += sprintf(buffer+len,
+                                        	       "stepping\t: %d\n",
+                                             	       CD(x86_mask));
+                                }
+                                else { 			/* we have a Cyrix */
+                                	len += sprintf(buffer+len,
+                                        	       "stepping\t: %s\n",
+                                             	       Cx86_type[Cx86_step]);
+                                }
                         else
                                 len += sprintf(buffer+len, 
                                                "stepping\t: unknown\n");
diff -u -r linux.orig/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- linux.orig/arch/i386/kernel/time.c	Sun Nov 10 18:40:53 1996
+++ linux/arch/i386/kernel/time.c	Tue Nov  4 15:45:43 1997
@@ -463,29 +463,30 @@
 				/* Don't use them if a suspend/resume could
                                    corrupt the timer value.  This problem
                                    needs more debugging. */
-	if (x86_capability & 16) {
-		do_gettimeoffset = do_fast_gettimeoffset;
+	if (x86_capability & 16)
+		if (strncmp(x86_vendor_id, "Cyrix", 5) != 0) {
+			do_gettimeoffset = do_fast_gettimeoffset;
 
-		if( strcmp( x86_vendor_id, "AuthenticAMD" ) == 0 ) {
-			if( x86 == 5 ) {
-				if( x86_model == 0 ) {
-					/* turn on cycle counters during power down */
-					__asm__ __volatile__ (" movl $0x83, %%ecx \n \
-								.byte 0x0f,0x32 \n \
-								orl $1,%%eax \n \
-								.byte 0x0f,0x30 \n " 
-                                                                : : : "ax", "cx", "dx" );
-					udelay(500);
+			if( strcmp( x86_vendor_id, "AuthenticAMD" ) == 0 ) {
+				if( x86 == 5 ) {
+					if( x86_model == 0 ) {
+						/* turn on cycle counters during power down */
+						__asm__ __volatile__ (" movl $0x83, %%ecx \n \
+									.byte 0x0f,0x32 \n \
+									orl $1,%%eax \n \
+									.byte 0x0f,0x30 \n " 
+                                                                	: : : "ax", "cx", "dx" );
+						udelay(500);
+					}
 				}
-			}
-		}
+			}	
 
-		/* read Pentium cycle counter */
-		__asm__(".byte 0x0f,0x31"
-			:"=a" (init_timer_cc.low),
-			 "=d" (init_timer_cc.high));
-		irq0.handler = pentium_timer_interrupt;
-	}
+			/* read Pentium cycle counter */
+			__asm__(".byte 0x0f,0x31"
+				:"=a" (init_timer_cc.low),
+			 	"=d" (init_timer_cc.high));
+			irq0.handler = pentium_timer_interrupt;
+		}
 #endif
 	setup_x86_irq(0, &irq0);
 }
