Re: Pentium (and Cyrix) DEATH in user-mode

B. James Phillippe (bryan@Terran.ORG)
Sat, 8 Nov 1997 16:26:44 -0800 (PST)


On Sat, 8 Nov 1997, Andre Derrick Balsa wrote:

> Hi Erik,
>
> Erik wrote:
>
> > In article <199711080849.VAA02265@karaka.chch.cri.nz> you wrote:
> > > Doesn't stop Cyrix 166 MMX's
> >
> > There seems to be a different sequence that affects Cyrixes though.
> >
> > See <http://www.heise.de/ct/art_ab97/9713030/>. If you don't
>
> Here are the *bad* news:
> ========================
>
> You *can* deadlock a 6x86 in user mode with the sequence or a small
> variations on the sequence proposed in the article.
> Here is the source of a small user-space program that will lock your
> Cyrix in a loop:
>
> 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");
> }
>
> Explanation (my guess, I may be completely wrong):
> ==================================================
> The exchange instruction (xchgl above) on the 6x86 will lock the cpu bus
> and effectively disable interrupts during its execution. It seems that
> the combination of speculative execution and register renaming plus the
> intelligent pipelines in the 6x86 will prevent interrupt servicing
> during the execution of the movl and jmp instructions. Consequently
> interrupts never get serviced and the processor is effectively locked in
> a loop that runs in its cache line.
>
> And here are the good news:
> ===========================
>
> Setting the NO_LOCK bit in CCR1 will prevent the deadlock caused by the
> above code sequence. Here is a short call to set6x86 that does this:
>
> set6x86 -p 0xc1 -s 0x10.
>
> Page table accesses and interrupt acknowledge cycles will still be
> executed in locked cycles, but the xchgl instruction will *not* generate
> locked cycles anymore.
>
> I don't know if setting the NO_LOCK bit will cause problems when running
> Linux. I don't think so...
>
> Comments are welcome.

Hi Andrew,

I am most greatful for your shedding of light on this matter.
Here are some comments you might find interesting. I own a 6x86 myself.
After reading this information, I tried the code you posted and it indeed
put my box in the closet until I hard reset it. Now the interesting part.
Your explanation of locked cycles was interesting, because the original
Mike Jagdis 6x86 patch (against 2.1.39) had a config option to do just
what your set6x86 call does. I had this feature turned on, and so was
quite surprised why my box still threw a shoe. When I used the set6x86
command, however, it did not have the problem. So I took another look
through the 2.1.39 Cyrix patch, and discovered a typo in the
CONFIG_CYRIX_6X86_NOLOCK code, which was setting the wrong register!
After making a 2 character change, my kernel now boots up protected from
this nuisance as it should be. The change was so minor I don't know if a
full-fledged patch would be necessary. Simply change the
setCx86($0xe8,%bx) to setCx86($0xc1,%bx) and you're set. FWIW, the Mike
Jagdis patch claims this should be a useful performance-enhancing feature
to have on all the time anyway (although since it wasn't working, I guess
it wasn't tested very well).

I'm using 2.1.62 on the following Cyrix:

processor : 0
cpu family : 5
model : 6x86 2x Core/Bus Clock
vendor_id : CyrixInstead
stepping : 1 rev 7
fdiv_bug : no
hlt_bug : no
sep_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu
bogomips : 104.65

Tangent: I had "upgraded" from my old Cyrix6x86 P150+ to an Intel Pentium
200 (vanilla), and after finding out about the horrible Pentium problem, I
dug my Cyrix out of my desk and swapped it back in. The funny thing is
that I havn't noticed the speed difference yet. :)

cheers,
-bp

--
B. James Phillippe <bryan@Terran.ORG>
UNIX, Linux, networks, C, Perl, Java, etc.
NIC:BJP4 # http://w3.terran.org/~bryan