Cyrix patch maintainer

Andre Derrick Balsa (andrewbalsa@usa.net)
Tue, 11 Nov 1997 14:42:57 +0100


This is a multi-part message in MIME format.

--------------7A3D6FAA1B3E538DD377014
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi there,

As stated before, I am changing the direction of the previous thread
about Cyrix support in the Linux kernel.

There seems to be a consensus at least on a single point: the kernel has
to be patched to support Cyrix processors adequately. This is specially
true after I came up with:

1) The 6x86MX kernel oops in time.c which I first reported on 11/03.
With a workaround which needs a kernel patch.

2) The Cyrix hidden CLI bug, first reported by Erik Corry on 11/08. A
few hours later on 11/08 I posted both a gcc demo program and a proposed
workaround. This workaround may be implemented as a kernel patch _or_ as
a user-space rc.cyrix script, called from rc.local.

So, a new patch is needed, since the otherwise excellent 2.1.39 patch by
Mike Jagdis does not account for these two issues at all.

Mike has already signaled that he is not willing to maintain the 2.1.39
Cyrix patch. Personally, I DO NOT wish to maintain Mike's patch either.
It is much beyond my competence and time availability.

I am perfectly willing to start afresh from my proposed small patch
(attached), which can be found on my Linux/6x86 site:
http://www.tux.org/~balsa/linux/cyrix and already addresses issue 1).
The patch is properly documented on the News page.

I would add features as I deem necessary, accepting input from Linux
users that effectively have Cyrix processors. This excludes a lot of
people who have posted to the previous thread, and I wish in the future
they would keep out of this thread too. I am certainly not out to say
what the Alpha code should do without having an Alpha myself, and the
same applies to Cyrix processors, scaled down, of course.

As for any Linux driver maintainer, accepting input means I will add
code or take into account suggestions as I deem fit, unless of course
somebody else applies for patch maintenance. However, this is not a
driver: all code changes have to go through the more complex approval
process of Linus himself taking a look at them and adding them to the
kernel source.

Regards,

========================================================
Andrew D. Balsa
Home Page: http://www.tux.org/~balsa
andrewbalsa@usa.net
========================================================

--------------7A3D6FAA1B3E538DD377014
Content-Type: text/plain; charset=us-ascii; name="Cyrix.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="Cyrix.patch"

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 Tue Nov 4 15:34:27 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
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);
}

--------------7A3D6FAA1B3E538DD377014--