Cyrix detection PATCH ([2.1.105] Cyrix 6x86 reduced to 486)

Rafael R. Reilova (rreilova@ececs.uc.edu)
Wed, 10 Jun 1998 12:28:18 -0500 (EST)


Hi,

Andre Balsa posted a patch against the 2.0.33 that correctly identified
the Cyrix cpu's without disturbing those touchy PII-BX boards. This is my
1/2 version of the patch, only the low-level stuff in head.S is changed.
If this is correct decoding the step/rev to actual chip names should be
almost trivial (the other 1/2). The TSC stuff, that's another story ;)

The patch is almost a complete cut-and-paste of Andre's, with a few
changes to make it work on the 2.1.x's. Someone familiar with this code
please eyeball it closely (it was really late when I finished, and
assembly is not kind to typos). Of course, also please test and confirm
this is correct. The patch is against 2.1.105, but should patch to
2.1.10[345]. BTW, who maintains this part of the code?

Cheers,

Rafael

--- /usr/src/linux-2.1.105/arch/i386/kernel/head.S Thu May 28 13:11:51 1998
+++ /usr/src/linux/arch/i386/kernel/head.S Wed Jun 10 12:21:31 1998
@@ -152,29 +152,44 @@
* apply at our cpl of 0 and the stack ought to be aligned already, and
* we don't need to preserve eflags.
*/
+ movl $3,X86 # at least 386
+ pushfl # push EFLAGS
+ popl %eax # get EFLAGS
+ movl %eax,%ecx # save original EFLAGS
+ xorl $0x40000,%eax # flip AC bit in EFLAGS
+ pushl %eax # copy to EFLAGS
+ popfl # set EFLAGS
+ pushfl # get new EFLAGS
+ popl %eax # put it in eax
+ xorl %ecx,%eax # change in flags
+ andl $0x40000,%eax # check if AC bit changed
+ je is386

-/*
- * Don't do this here. Do it in the CPU init code in C, right now we
- * must _not_ play unsafe games with the IO ports.
- *
- * A PPro and a P-II will also preserve the flags after a division,
- * so this "cyrix" test is just completely unsafe. IO port 0x22 is
- * some magic ACPI port on non-cyrix chips, so if this trashes that
- * we're screwed.
- *
- * This code belongs in "asm-i386/bugs.h" anyway (at which point we
- * _have_ done a CPUID for CPU's that support it directly, so we'll
- * be able to tell a intel P-II trivially at that point).
- */
-#undef CYRIX_CODE_BREAKAGE
-#ifdef CYRIX_CODE_BREAKAGE
+ movl $4,X86 # at least 486
+ movl %ecx,%eax
+ xorl $0x200000,%eax # check ID flag
+ pushl %eax
+ popfl # if we are on a straight 486DX, SX, or
+ pushfl # 487SX we can't change it
+ popl %eax # also if we are on a Cyrix 6x86(L)
+ xorl %ecx,%eax # OTOH 6x86MXs and MIIs check OK
+ pushl %ecx # restore original EFLAGS
+ popfl
+ andl $0x200000,%eax
+ jne has_cpuid

+/* Now we test if we have a Cyrix w/o cpuid. We didn't test before to avoid
+ * clobbering the new BX chipset used with the Pentium II, which has a register
+ * at the same addresses as those used to access the Cyrix special configuration
+ * registers (CCRs). Anything in with BX should have cpuid!
+ */
/*
- * A Cyrix preserves flags in cases where other CPUs change
+ * A Cyrix/IBM 486 or better 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. (Cyrix chips
- * prior to M2 have CPUID disabled by default, the Cx486s
- * didn't have it at all.)
+ * need to enable the CPUID instruction at least.
+ * We couldn't use this test before since the PPro and PII behave
+ * like Cyrix chips in this respect.
*/
xor %ax,%ax
sahf
@@ -183,7 +198,7 @@
div %bl
lahf
cmpb $2,%ah
- jne ncyrix
+ jne is486

/*
* It behaves like a Cyrix so put "Cyrix" in the vendor id
@@ -194,9 +209,9 @@
movl $0x00000078,X86_VENDOR_ID+4 # next 4 chars

/*
- * N.B. The pattern of accesses to 0x22 and 0x23 is *important*
- * so do not try and "optimise" it! For the same reason we
- * do all this with interrupts off just to be sure.
+ * 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,%al; \
@@ -209,51 +224,35 @@
outb %al,$0x22; \
inb $0x23,%al

+ getCx86($0xfe) # DIR0 : let's check this is a 6x86(L)
+ andb $0xf0,%al # should be 3xh
+ cmpb $0x30,%al
+ jne cyrix_id # Cx486/586?
+
+ /* The Cyrix 6x86(L) has the cpuid instruction off by default.
+ * Turn it on and also fix the udelay calculation problem.
+ */
+
getCx86($0xc3) # get CCR3
movb %al,%cl # Save old value
movb %al,%bl
- andb $0x0f,%bl # Enable all config registers (for CCR4 access)
- orb $0x10,%bl
+ andb $0x0f,%bl # Enable access to all config registers
+ orb $0x10,%bl # by setting bit 4
setCx86($0xc3,%bl)

- getCx86($0xe8) # CCR4 |= CPUID
- orb $0x80,%al
- movb %al,%bl
+ getCx86($0xe8) # now we can get CCR4
+ orb $0x80,%al # and set bit 7 (CPUIDEN)
+ movb %al,%bl # to enable CPUID execution
setCx86($0xe8,%bl)

+ getCx86($0xe9) # CCR5 : we reset the SLOP bit
+ andb $0xfd,%al # so that udelay calculation
+ movb %al,%bl # is correct on 6x86(L) CPUs
+ setCx86($0xe9,%bl)
setCx86($0xc3,%cl) # Restore old CCR3

-ncyrix:
-
-#endif
-
- movl $3,X86 # at least 386
- pushfl # push EFLAGS
- popl %eax # get EFLAGS
- movl %eax,%ecx # save original EFLAGS
- xorl $0x40000,%eax # flip AC bit in EFLAGS
- pushl %eax # copy to EFLAGS
- popfl # set EFLAGS
- pushfl # get new EFLAGS
- popl %eax # put it in eax
- xorl %ecx,%eax # change in flags
- andl $0x40000,%eax # check if AC bit changed
- je is386
-
- movl $4,X86 # at least 486
- movl %ecx,%eax
- xorl $0x200000,%eax # check ID flag
- pushl %eax
- popfl # if we are on a straight 486DX, SX, or
- pushfl # 487SX we can't change it
- popl %eax
- xorl %ecx,%eax
- pushl %ecx # restore original EFLAGS
- popfl
- andl $0x200000,%eax
- je nocpuid
-
/* get vendor info */
+has_cpuid:
xorl %eax,%eax # call CPUID with 0 -> return vendor ID
cpuid
movl %eax,X86_CPUID # save CPUID level
@@ -262,7 +261,7 @@
movl %ecx,X86_VENDOR_ID+8 # last 4 chars

orl %eax,%eax # do we have processor info as well?
- je nocpuid
+ je cyrix_id

movl $1,%eax # Use the CPUID instruction to get CPU type
cpuid
@@ -276,15 +275,14 @@
movb %cl,X86_MASK
movl %edx,X86_CAPABILITY

-nocpuid:
-
-#ifdef CYRIX_CODE_BREAKAGE
+cyrix_id:
/*
* Even if we had CPUID Cyrix tries to look compatible with
* Intel so we have to go elsewhere for the nitty gritty.
+ * We already tested for cpuid, so non-cyrixes should be safe.
*/
cmpl $0x69727943,X86_VENDOR_ID # "Cyri[x.*]"?
- jne is486 # maybe ...
+ jne is486

movb $0xfe,X86_MODEL # Generic Cx486?
movb $0,X86_MASK
@@ -305,14 +303,6 @@
movb %al,X86_MASK
getCx86($0xfe)
movb %al,X86_MODEL
- andb $0xf0,%al # Check for 6x86(L)
- cmp $0x30,%al
- jnz is486
- getCx86($0xe9) # CCR5: reset SLOP bit, so that the udelay loop
- andb $0xfd,%al # works well on 6x86(L) CPU's.
- movb %al,%bl
- setCx86($0xe9,%bl)
-#endif

is486:
movl %cr0,%eax # 486 or better

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