A long v3 memtest was requested. It doesn't take long before Memtest stops, sometimes it is immediate after startup. The serial console looks like this:
Memtest-86 v3.4 | Pass 10% ### 498.1MHz | Test 51% ################### L1 Cache: Unknown | Test #4 [Moving inversions, random pattern] L2 Cache: Unknown | Testing: 120K - 248M 247M Memory : 247M | Pattern: 3430d8ec Chipset :
WallTime Cached RsvdMem MemMap Cache ECC Test Pass Errors ECC Errs --------- ------ ------- -------- ----- --- ---- ---- ------ -------- 0:06:53 247M 0K LinuxBIOS on off Std 0 0 ----------------------------------------------------------------------------- Unexpected Interrupt - Halting Test Errors Lowest Error Address: 00000fffffc -Stack:.9MB 0 0 Type: Gen_Prot Addreax: 3430d8ec70f -0001b874M00000000 0001b8a4 00000002 0 PC: 00003bb9ror Mebx: 00000000 0001b878 3430d8ec 0001b8a8 0f7dff00 0 CS: 00000010 - Toecx: ffffffff 1 M0001b87cv0000000d 0001b8ac 0f7dff00 0 Eflag: 00010012s Erredx: 037dfefc 0001b880 00000000 0001b8b0 00100000 3 Code: 00000000e Erredi: ffffffff 0001b884 00003bb9 0001b8b4 00000001 0 Errors per Memory Sesi: 0001bab8 0001b888 00000010 0001b8b8 00000000 0 ebp: 00000001 0001b88c 00010012 0001b8bc 000000ec 0 esp: 0001b874 0001b890 0000000a 0001b8c0 0000000a 0 0001b894 00000028 0001b8c4 00000028 0 CS:EIP: 89 07 39 fa 75 f1 83 ef 04 eb 0001b898 00010c27 0001b8c8 00db7fc0 (ESC)exit (c)configuration (SP)scrol0001b89c(037dfefcl_0001b8cc 0001a850 0001b8a0 00000001 0001b8d0 0000001e
//Peter
minicom console? believe it or not I'd get these when the minicom window was not exactly 80x24. I am not making this up.
ron
On 09.05.2008 07:01, Peter Stuge wrote:
A long v3 memtest was requested. It doesn't take long before Memtest stops, sometimes it is immediate after startup. The serial console looks like this:
I tried to make sense of the output, but I'm not completely sure I got it right.
Memtest-86 v3.4 | Pass 10% ###
Which gcc? Newer gcc miscompile memtest86 and memtest86+ due to undefined statements in the memtest code. This not only causes memtest to throw errors which don't exist, in theory it also could lead to overwriting of its own stack and code.
[...] Unexpected Interrupt - Halting Lowest Error Address: 00000fffffc Type: Gen_Prot eax: 3430d8ec PC: 00003bb9 ebx: 00000000 CS: 00000010 ecx: ffffffff Eflag: 00010012s edx: 037dfefc Code: 00000000e edi: ffffffff esi: 0001bab8 ebp: 00000001 esp: 0001b874
CS:EIP: 89 07 39 fa 75 f1 83 ef 04 eb
It seems we definitely need memtest to use libpayload and display graphical results. That would at least rule out problems caused by serial output. Then again, having memtest send its results as POST codes should work well if you can capture POST codes.
Regards, Carl-Daniel
On 09.05.2008 12:21, Carl-Daniel Hailfinger wrote:
On 09.05.2008 07:01, Peter Stuge wrote:
A long v3 memtest was requested. It doesn't take long before Memtest stops, sometimes it is immediate after startup. The serial console looks like this:
I tried to make sense of the output, but I'm not completely sure I got it right.
Memtest-86 v3.4 | Pass 10% ###
Which gcc? Newer gcc miscompile memtest86 and memtest86+ due to undefined statements in the memtest code. This not only causes memtest to throw errors which don't exist, in theory it also could lead to overwriting of its own stack and code.
Try memtest86+ v2.01 from http://www.memtest.org/ with the patches contained in the openSUSE source RPM from a few days ago (attached). fix-overflows.diff is the one enabling memtest86+ to work well with recent gcc. You may or may not want to apply the other patches as well.
Regards, Carl-Daniel
diff -ur memtest86+-1.70.orig/Makefile memtest86+-1.70/Makefile --- memtest86+-1.70.orig/Makefile 2006-12-27 02:34:57.000000000 +0100 +++ memtest86+-1.70/Makefile 2007-01-25 16:34:01.000000000 +0100 @@ -7,6 +7,7 @@ # Path for the floppy disk device # FDISK=/dev/fd0 +TARGETDIR=/boot
CC=gcc # @@ -116,7 +117,10 @@ wormkill: rm -f *~
-install: all +install: + install -o root -g root memtest.bin $(DESTDIR)$(TARGETDIR)/ + +install-floppy: all dd <memtest.bin >$(FDISK) bs=8192
install-bin: Only in memtest86+-1.70: Makefile.orig
diff -urp memtest86+-2.01.mm/io.h memtest86+-2.01/io.h --- memtest86+-2.01.mm/io.h 2008-02-21 12:26:05.000000000 +0100 +++ memtest86+-2.01/io.h 2008-04-30 12:32:34.787275000 +0200 @@ -31,7 +31,7 @@ */
#define __OUT1(s,x) \ -extern inline void __out##s(unsigned x value, unsigned short port) { +static inline void __out##s(unsigned x value, unsigned short port) {
#define __OUT2(s,s1,s2) \ __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" @@ -43,7 +43,7 @@ __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; }
#define __IN1(s) \ -extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v; +static inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v;
#define __IN2(s,s1,s2) \ __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" @@ -55,7 +55,7 @@ __IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) __IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; }
#define __OUTS(s) \ -extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ +static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ { __asm__ __volatile__ ("cld ; rep ; outs" #s \ : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
diff -urp memtest86+-2.01.mm/test.c memtest86+-2.01/test.c --- memtest86+-2.01.mm/test.c 2008-02-21 12:26:05.000000000 +0100 +++ memtest86+-2.01/test.c 2008-04-30 14:15:56.666389000 +0200 @@ -25,6 +25,22 @@ void poll_errors();
int ecount = 0;
+static inline volatile ulong * sat_add(volatile ulong *ptr, ulong i, volatile ulong *end) +{ + if ((ulong)ptr + i * sizeof(*ptr) > (ulong)ptr) + return ptr + i; + else + return end; +} + +static inline volatile ulong * sat_sub(volatile ulong *ptr, ulong i, volatile ulong *start) +{ + if ((ulong)ptr > i * sizeof(*ptr)) + return ptr - i; + else + return start; +} + static inline ulong roundup(ulong value, ulong mask) { return (value + mask) & ~mask; @@ -150,11 +166,7 @@ void addr_tst2() done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -194,11 +206,7 @@ void addr_tst2() done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -280,11 +288,7 @@ void movinvr() done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -331,11 +335,7 @@ void movinvr() done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -419,7 +419,8 @@ void movinv1(int iter, ulong p1, ulong p hprint(LINE_PAT, COL_PAT, p1);
/* Initialize memory with the initial pattern. */ - for (j=0; j<segs; j++) { + for (j=0; j<segs; j++) + { start = v->map[j].start; end = v->map[j].end; pe = start; @@ -427,11 +428,7 @@ void movinv1(int iter, ulong p1, ulong p done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -440,17 +437,19 @@ void movinv1(int iter, ulong p1, ulong p if (p == pe ) { break; } -/* Original C code replaced with hand tuned assembly code - * for (; p < pe; p++) { - * *p = p1; - * } - */ +/* Original C code replaced with hand tuned assembly code */ +#if 0 + for (; p < pe; p++) { + *p = p1; + } +#else asm __volatile__ ( "rep\n\t" \ "stosl\n\t" : "=D" (p) : "c" (len), "0" (p), "a" (p1) ); +#endif do_tick(); BAILR } while (!done); @@ -460,7 +459,8 @@ void movinv1(int iter, ulong p1, ulong p * write the complement for each memory location. Test from bottom * up and then from the top down. */ for (i=0; i<iter; i++) { - for (j=0; j<segs; j++) { + for (j=0; j<segs; j++) + { start = v->map[j].start; end = v->map[j].end; pe = start; @@ -468,11 +468,7 @@ void movinv1(int iter, ulong p1, ulong p done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -480,14 +476,16 @@ void movinv1(int iter, ulong p1, ulong p if (p == pe ) { break; } -/* Original C code replaced with hand tuned assembly code - * for (; p < pe; p++) { - * if ((bad=*p) != p1) { - * error((ulong*)p, p1, bad); - * } - * *p = p2; - * } - */ +/* Original C code replaced with hand tuned assembly code */ +#if 0 + for (; p < pe; p++) { + ulong bad; + if ((bad=*p) != p1) { + error((ulong*)p, p1, bad); + } + *p = p2; + } +#else asm __volatile__ ( "jmp L2\n\t" \
@@ -522,10 +520,12 @@ void movinv1(int iter, ulong p1, ulong p : "a" (p1), "0" (p), "d" (pe), "b" (p2) : "ecx" ); +#endif do_tick(); BAILR } while (!done); } + for (j=segs-1; j>=0; j--) { start = v->map[j].start; end = v->map[j].end; @@ -534,11 +534,7 @@ void movinv1(int iter, ulong p1, ulong p done = 0; do { /* Check for underflow */ - if (pe - SPINSZ < pe) { - pe -= SPINSZ; - } else { - pe = start; - } + pe = sat_sub(pe, SPINSZ, start); if (pe <= start) { pe = start; done++; @@ -546,14 +542,16 @@ void movinv1(int iter, ulong p1, ulong p if (p == pe ) { break; } -/* Original C code replaced with hand tuned assembly code - * do { - * if ((bad=*p) != p2) { - * error((ulong*)p, p2, bad); - * } - * *p = p1; - * } while (p-- > pe); - */ +/* Original C code replaced with hand tuned assembly code */ +#if 0 + do { + ulong bad; + if ((bad=*p) != p2) { + error((ulong*)p, p2, bad); + } + *p = p1; + } while (p-- > pe); +#else asm __volatile__ ( "addl $4, %%edi\n\t" "jmp L9\n\t" @@ -590,6 +588,7 @@ void movinv1(int iter, ulong p1, ulong p : "a" (p1), "0" (p), "d" (pe), "b" (p2) : "ecx" ); +#endif do_tick(); BAILR } while (!done); @@ -623,11 +622,7 @@ void movinv32(int iter, ulong p1, ulong pat = p1; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -685,11 +680,7 @@ void movinv32(int iter, ulong p1, ulong pat = p1; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -798,11 +789,7 @@ void movinv32(int iter, ulong p1, ulong done = 0; do { /* Check for underflow */ - if (pe - SPINSZ < pe) { - pe -= SPINSZ; - } else { - pe = start; - } + pe = sat_sub(pe, SPINSZ, start); if (pe <= start) { pe = start; done++; @@ -906,11 +893,7 @@ void modtst(int offset, int iter, ulong done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -951,11 +934,7 @@ void modtst(int offset, int iter, ulong k = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++; @@ -1009,11 +988,7 @@ void modtst(int offset, int iter, ulong done = 0; do { /* Check for overflow */ - if (pe + SPINSZ > pe) { - pe += SPINSZ; - } else { - pe = end; - } + pe = sat_add(pe, SPINSZ, end); if (pe >= end) { pe = end; done++;
--- memtest86+-1.70/memtest_shared.lds 2007-02-19 16:00:35.000000000 +0100 +++ memtest86+-1.70/memtest_shared.lds.fixed 2007-02-19 15:55:24.000000000 +0100 @@ -19,6 +19,7 @@ .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } .dynamic : { *(.dynamic) }
.rel.text : { *(.rel.text .rel.text.*) }
diff -ur memtest86+-1.70.orig/memtest_shared.lds memtest86+-1.70/memtest_shared.lds --- memtest86+-1.70.orig/memtest_shared.lds 2006-12-27 02:33:06.000000000 +0100 +++ memtest86+-1.70/memtest_shared.lds 2007-01-25 16:34:19.000000000 +0100 @@ -8,6 +8,7 @@ _start = .; *(.text) *(.text.*) + *(.gnu.linkonce.t.*) *(.plt) _etext = . ; } = 0x9090
--- memtest86+-2.01/config.h +++ memtest86+-2.01/config.h @@ -13,7 +13,7 @@ /* SERIAL_CONSOLE_DEFAULT - The default state of the serial console. */ /* This is normally off since it slows down testing. Change to a 1 */ /* to enable. */ -#define SERIAL_CONSOLE_DEFAULT 0 +#define SERIAL_CONSOLE_DEFAULT 1
/* SERIAL_TTY - The default serial port to use. 0=ttyS0, 1=ttyS1 */ #define SERIAL_TTY 0 --- memtest86+-2.01/init.c +++ memtest86+-2.01/init.c @@ -40,6 +40,7 @@ static void cacheable(void); static int cpuspeed(void); int beepmode; +extern short serial_cons;
static void display_init(void) { @@ -76,6 +77,9 @@ }
serial_echo_print("\x1B[0m"); + + if (!serial_cons && SERIAL_CONSOLE_DEFAULT) + cprint (23, 0, "Timout on serial console: disabled"); }
/* --- memtest86+-2.01/serial.h +++ memtest86+-2.01/serial.h @@ -140,10 +140,12 @@ #define serial_echo_inb(a) inb((a)+serial_base_ports[serial_tty]) #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) /* Wait for transmitter & holding register to empty */ -#define WAIT_FOR_XMITR \ - do { \ - lsr = serial_echo_inb(UART_LSR); \ - } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) +#define WAIT_FOR_XMITR \ + int _i = 1<<15; \ + do { \ + lsr = serial_echo_inb(UART_LSR); \ + } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY && --_i); \ + if (!_i) serial_cons = 0
#if 0 static inline void serial_echo(int ch)