COMMAND
CPU [HW stuff]
SYSTEMS AFFECTED
Cyrix 6x86, 6x86L, and 6x86MX up to Rev. 1.4
PROBLEM
Following was found by Serguei Shtyliov and was published in c't
13/97. It's about an endless loop, done with just a few very
basic instructions that locks every 6x86-CPU by IBM Cyrix and
SGS, inclusive the M2. The bug is called 'Hidden CLI' because
it seems to show up when the Interrupt-Flag of the CPU is deleted.
The CPU ignores the keyboard interrupt and even maskable
Interrupts over the ISA-bus (NMI), also a reset via the keyboard-
controller - the CPU is in a dead-lock.
The error will persists even under the following conditions:
Usage of other registers
Deactivation of Data bypassing and forwarding
Deactivation of Write Allocation
Dependend jumps instead of JMP ADD, AND, XOR or MOV instead
of STI
The assembler code is:
MOV BX,70h
STI
again: XCHG AX,[BX]
MOV DX,AX
JMP again
C people should use:
static unsigned char c[4] = {0x36, 0x78, 0x38, 0x36};
main()
{
asm ("movl $c, %ebx\n\t"
"again: xchgl (%ebx), %eax\n\t"
"movl %eax, %edx\n\t"
"jmp again\n\t");
}
The program above basically consists of the following loop:
1. Exchange the contents of memory location pointed by ebx
with contents of eax (32 bits): xchg opcode.
2. Copy the new contents of eax to edx (32 bits): mov opcode.
3. Unconditionally jump back to step 1: jmp opcode.
This, in itself, is an infinite loop. The only way for the
processor to get out of this loop is by getting interrupted. So
far so good, since any multitasking OS and even DOS will interrupt
the processor. However, as you will see for yourself if you try
to run this loop or a variant of it, the processor does not
respond to any interrupt once in the loop. This is the symptom
that led the c't magazine crew to call it the hidden CLI bug.
SOLUTION
This effect is not reproduceable on other 586-processors. Pentium,
K6, K5 and others are also in the endless loop but still react to
the keyboard interrupt (pressing ctrl-alt-del for example). The
error will not show up under the following conditions:
L1-Cache is deactivated
Adding NOP or other commands in the loop
Resolving the dependency of MOV and XCHG
OUT instead of STI
ADD, TEST, AND or MOV instead of XCHG
According to another post on linux-kernel, it is fixed by:
set6x86 -p 0xc1 -s 0x10
This means setting the NO_LOCK bit in CCR1. This will prevent
the deadlock caused by the above code sequence. Page table
accesses and interrupt acknowledge cycles will still be executed
in locked cycles, but the xchgl instruction will *not* generate
locked cycles anymore. Note that Cyrix has reported having had
problems with the DOS4GW Extensions when NO-LOCK is set (no
details provided). The DOS4GW extensions are used by DOOM and
QUAKE and other DOS packages to enable access to extended memory.
However, this incompatibility is irrelevant to the serious problem
caused by the Cyrix Coma bug: a security breach in multiuser,
multitasking protected-mode OS's. According to Andrew D. Balsa
you should add the following lines to your rc.cyrix script, in the
part where it has MAPEN enabled:
set6x86 -p 0x31 -s 0xF8
set6x86 -p 0x32 -s 0x7f
set6x86 -p 0x33 -c 0xFF
set6x86 -p 0x3c -s 0x87
Be careful to copy exactly as shown, particularly the -c on the
third line. Basically what this script does is setup the 6x86 for
detection of the xchg opcode (0x87). When detected in the
instruction stream, the xchg opcode will be serialized, bypassing
the pipeline. The performance hit of this solution is almost zero.