From: herr@hp11.iti.informatik.th-darmstadt.de (Gabor Herr)
Subject: AMD386 vs. Intel386 & external cache problems
Date: Wed, 12 Aug 1992 15:31:49 GMT
Organization: TU Darmstadt
Keywords: AMD 386 Intel cache

Hello Linuxers,

two weeks ago I posted to this newsgroup, that I had problems with my new 386
motherboard (AMD386, 40MHz, ETEQ Cougar chipset, 64KB cache, 8MB memory).
Running Linux on it, from time to time some processes or even
the kernel died with a signal SIGSEGV, which was caused by a `general protection
error'. After turning off the onboard external cache everything worked
fine. 

To localize the error and make it reproducible I tested the machine
with the following two endless loops under Linux 0.96cp2: 

in VT1 a kernel compiling:

$ cd /usr/src/linux
$ while true; do make clean; make Image; done

in VT2 formatting of a manpage

$ while true; do groff -Tps -e -t -man bash.1 > bash.ps; done

With cacheing enabled either gcc or groff or the kernel died with a SIGSEGV
within a half an hour. I considered a configuration as working if the
loops ran at least one hour.

As I already mentioned in the first posting I exchanged my board for an
other one with 33MHz (AMD386, 33MHz, C&T Peak chipset, 64KB cache),
because one of my frieds had a similar machine, where Linux was running
without any problems (he tried the above test). The only difference between
the two boards: different manufacturer and his had an Intel 386 processor
on it. After installing the new board I was quite amazed as I got exactly
the same errors as before.

To narrow down the problem we begun to exchange the other components
of his and my machine. Finally we could reproduce the errors with my
board in his machine whereas his board with my IO cards worked
correctly. 

The second approach was to test the board's external cache memory. I wrote the
two test programs below cachetest and memtest. The first one reads and writes a
small data area (1-64KB) which completly fits into the cache and checks its
consistency. The latter does the same on a bigger area (ca. 1-8MB),
causing the cache always to be reloaded. I got following results:

cachetest 1000		ran 3 hours without error (buffer 1000 Bytes)
memtest	1100		did 2000 cycles (1 hour) without error (buffer 4.4MB) 
memtest 3000		did 22 cycles  (1 hour) without errors (buffer 12MB)

memtest 1000 &
memtest 1000		(the two programs parallel) ran 1 hour, then
			the first exited with a SIGSEGV

The tests show that this *cannot* be a cache problem. In the last case
memtest died because of a memory error in the code segment, which is
about 17k big. The probability for a `failed assertion' in 4-12 MB data
area would be much higher in case of a bad cache. It also cannot be a
HD problem: the second and the third test made Linux swap a lot (the
third one even caused tharshing, so I had to stop one of the processes and
let it continue later...). I never saw those `HD timeout errors' or
`unexpected HD interrupt's described in many postings.

As a last try I went back to my dealer and after he made me a good
price, I changed the board for an Intel 486DX, 33Mhz, 256KB cache, 
C&T Peak chipset. And now Linux works fine on this even much faster
machine. I stopped the gcc/groff test after 4 hours of running without
any errors.:-)

My problem is solved, but there could be somebody out in the net
despaired of those intermitting SIGSEGV`s (I can feel with him ;-)),
whom my experiences probably will help. 

I also want to know what was the reason for this kind of errors.
Therefore some questions:

- Is there anybody out in the net using Linux on a configuration
  similar to my old one? Please try to run the above tests and tell me
  if it worked...

- Are there differences between AMD 386 and Intel 386? Has the AMD
  probably some bugs?

Thanx...

Gabor


############################################################################
Gabor Herr			Email: herr@iti.informatik.th-darmstadt.de
Computer Science Department
Technical University of Darmstadt, Germany


PS: just for info, my other machine components:

HD:	Seagate ST3144A, IDE, 124MB
VGA:	ColorIMAGE, ET4000, 1MB
Memory:	8MB, as 8x1MB SIMMS
Serial:	noname MultiIO Card (not used in most of the tests)


----------------------------- cut here ---------------------------------------
/* 
 * cachetest.c		Test onboard external cache
 *
 * usage: cachetest <n>	
 *		<n> buffer size in bytes
 */

#include <stdio.h>
#include <assert.h>

#define MAXBUFFER	4096

main( argc, argv )
int argc;
char **argv;
{
  static unsigned int buffer[MAXBUFFER];

  unsigned i;
  unsigned n;
  unsigned cycle;

  n = atoi( argv[1] );

  printf("Testing cache, buffer size is %d...\n",n);

  for ( i = 0; i < n; i++ )
    buffer[i] = 0;

   for ( cycle = 0; ; cycle++ ) {
     for ( i = 0; i < n; i++ ) {
       assert( buffer[i] == cycle );
       (buffer[i])++;
     }
/*     if ( cycle % 1000 == 0 ) printf("%d\n",cycle); */
   }
}

----------------------------- cut here --------------------------------------
/* 
 * memtest.c		Test onboard external cache
 *
 * usage: memtest <n>	
 *		<n> buffer size in KWords
 */


#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

main( int argc, char **argv )
{
  unsigned *memstart, *memend, *addr, offset;
  int kws;

  kws = atoi(argv[1]);

  fprintf( stderr, "Testing %d KWord system memory...\n", kws);

  if ((memstart = (char *) malloc( kws * 1024 * 4)) == NULL) {
    fprintf(stderr, "out of memory\n");
    exit(1);
  }

  memend = memstart + kws * 1024;
  
  for ( addr = memstart; addr < memend; addr++ )
    *addr = addr;

  for ( offset = 0; ; offset++ ) {
    fprintf(stderr,"memtest: offset = %d\n",offset);  
    for ( addr = memstart; addr < memend; addr++ ) {
      assert(*addr == (unsigned)addr + offset);
      (*addr)++;
    }
  } 
}

----------------------------------- cut here ---------------------------------