diff options
Diffstat (limited to 'test.c')
-rw-r--r-- | test.c | 1301 |
1 files changed, 719 insertions, 582 deletions
@@ -1,53 +1,94 @@ - -/* test.c - MemTest-86 Version 3.2 +/* test.c - MemTest-86 Version 3.4 * * Released under version 2 of the Gnu Public License. - * By Chris Brady, cbrady@sgi.com + * By Chris Brady * ---------------------------------------------------- - * MemTest86+ V3.00 Specific code (GPL V2.0) + * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org + * Thanks to Passmark for calculate_chunk() and various comments ! */ - + #include "test.h" #include "config.h" +#include "stdint.h" +#include "cpuid.h" +#include "smp.h" #include <sys/io.h> -#include "dmi.h" -#include <inttypes.h> -extern int segs, bail; -extern volatile ulong *p; -extern ulong p1, p2; +extern struct cpu_ident cpu_id; +extern volatile int mstr_cpu; +extern volatile int run_cpus; +extern volatile int test; +extern volatile int segs, bail; extern int test_ticks, nticks; extern struct tseq tseq[]; extern void update_err_counts(void); extern void print_err_counts(void); +void rand_seed( unsigned int seed1, unsigned int seed2, int me); +ulong rand(int me); void poll_errors(); -int ecount = 0; - static inline ulong roundup(ulong value, ulong mask) { return (value + mask) & ~mask; } + +// start / end - return values for range to test +// me - this threads CPU number +// j - index into v->map for current segment we are testing +// align - number of bytes to align each block to +void calculate_chunk(ulong** start, ulong** end, int me, int j, int makeMultipleOf) +{ + ulong chunk; + + + // If we are only running 1 CPU then test the whole block + if (run_cpus == 1) { + *start = v->map[j].start; + *end = v->map[j].end; + } + else{ + + // Divide the current segment by the number of CPUs + chunk = (ulong)v->map[j].end-(ulong)v->map[j].start; + chunk /= run_cpus; + + // Round down to the nearest desired bitlength multiple + chunk = (chunk + (makeMultipleOf-1)) & ~(makeMultipleOf-1); + + // Figure out chunk boundaries + *start = (ulong*)((ulong)v->map[j].start+(chunk*me)); + /* Set end addrs for the highest CPU num to the + * end of the segment for rounding errors */ + // Also rounds down to boundary if needed, may miss some ram but better than crashing or producing false errors. + // This rounding probably will never happen as the segments should be in 4096 bytes pages if I understand correctly. + if (me == mstr_cpu) { + *end = (ulong*)(v->map[j].end); + } else { + *end = (ulong*)((ulong)(*start) + chunk); + (*end)--; + } + } +} + /* * Memory address test, walking ones */ -void addr_tst1() +void addr_tst1(int me) { int i, j, k; - volatile ulong *pt; - volatile ulong *end; - ulong bad, mask, bank; + volatile ulong *p, *pt, *end; + ulong bad, mask, bank, p1; /* Test the global address bits */ for (p1=0, j=0; j<2; j++) { - hprint(LINE_PAT, COL_PAT, p1); + hprint(LINE_PAT, COL_PAT, p1); /* Set pattern in our lowest multiple of 0x20000 */ p = (ulong *)roundup((ulong)v->map[0].start, 0x1ffff); *p = p1; - + /* Now write pattern compliment */ p1 = ~p1; end = v->map[segs-1].end; @@ -55,23 +96,23 @@ void addr_tst1() mask = 4; do { pt = (ulong *)((ulong)p | mask); - if ((uintptr_t)pt == (uintptr_t)p) { + if (pt == p) { mask = mask << 1; continue; } - if ((uintptr_t)pt >= (uintptr_t)end) { + if (pt >= end) { break; } *pt = p1; - if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) { + if ((bad = *p) != ~p1) { ad_err1((ulong *)p, (ulong *)mask, - bad, ~p1); + bad, ~p1); i = 1000; } mask = mask << 1; } while(mask); } - do_tick(); + do_tick(me); BAILR } @@ -84,48 +125,49 @@ void addr_tst1() bank = 0x40000; } for (p1=0, k=0; k<2; k++) { - hprint(LINE_PAT, COL_PAT, p1); + hprint(LINE_PAT, COL_PAT, p1); for (j=0; j<segs; j++) { p = v->map[j].start; /* Force start address to be a multiple of 256k */ p = (ulong *)roundup((ulong)p, bank - 1); end = v->map[j].end; - while ((uintptr_t)p < (uintptr_t)end) { + /* Redundant checks for overflow */ + while (p < end && p > v->map[j].start && p != 0) { *p = p1; p1 = ~p1; - for (i=0; i<200; i++) { + for (i=0; i<50; i++) { mask = 4; do { pt = (ulong *) ((ulong)p | mask); - if ((uintptr_t)pt == (uintptr_t)p) { + if (pt == p) { mask = mask << 1; continue; } - if ((uintptr_t)pt >= (uintptr_t)end) { + if (pt >= end) { break; } *pt = p1; - if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) { + if ((bad = *p) != ~p1) { ad_err1((ulong *)p, - (ulong *)mask, - bad,~p1); + (ulong *)mask, + bad,~p1); i = 200; } mask = mask << 1; } while(mask); } - if ((uintptr_t)(p + bank/4) > (uintptr_t)p) { - p += bank/4; + if (p + bank > p) { + p += bank; } else { p = end; } p1 = ~p1; } } - do_tick(); + do_tick(me); BAILR p1 = ~p1; } @@ -134,13 +176,12 @@ void addr_tst1() /* * Memory address test, own address */ -void addr_tst2() +void addr_tst2(int me) { int j, done; - volatile ulong *pe; - volatile ulong *end, *start; + ulong *p, *pe, *end, *start; - cprint(LINE_PAT, COL_PAT, " "); + cprint(LINE_PAT, COL_PAT, "address "); /* Write each address with it's own address */ for (j=0; j<segs; j++) { @@ -150,39 +191,40 @@ void addr_tst2() p = start; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code - * for (; p < pe; p++) { + * for (; p <= pe; p++) { * *p = (ulong)p; * } */ asm __volatile__ ( - "jmp L90\n\t" - + "jmp L91\n\t" ".p2align 4,,7\n\t" "L90:\n\t" - "movl %%edi,(%%edi)\n\t" "addl $4,%%edi\n\t" + "L91:\n\t" + "movl %%edi,(%%edi)\n\t" "cmpl %%edx,%%edi\n\t" "jb L90\n\t" - : "=D" (p) - : "D" (p), "d" (pe) + : : "D" (p), "d" (pe) ); - do_tick(); - BAILR + p = pe + 1; } while (!done); } @@ -194,41 +236,44 @@ void addr_tst2() p = start; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { - pe += SPINSZ; - } else { - pe = end; - } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe + SPINSZ > pe && pe != 0) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe ) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code - * for (; p < pe; p++) { + * for (; p <= pe; p++) { * if((bad = *p) != (ulong)p) { * ad_err2((ulong)p, bad); * } * } */ asm __volatile__ ( - "jmp L91\n\t" - + "jmp L95\n\t" ".p2align 4,,7\n\t" - "L91:\n\t" + "L99:\n\t" + "addl $4,%%edi\n\t" + "L95:\n\t" "movl (%%edi),%%ecx\n\t" "cmpl %%edi,%%ecx\n\t" - "jne L93\n\t" - "L92:\n\t" - "addl $4,%%edi\n\t" + "jne L97\n\t" + "L96:\n\t" "cmpl %%edx,%%edi\n\t" - "jb L91\n\t" - "jmp L94\n\t" - - "L93:\n\t" + "jb L99\n\t" + "jmp L98\n\t" + + "L97:\n\t" "pushl %%edx\n\t" "pushl %%ecx\n\t" "pushl %%edi\n\t" @@ -236,15 +281,13 @@ void addr_tst2() "popl %%edi\n\t" "popl %%ecx\n\t" "popl %%edx\n\t" - "jmp L92\n\t" + "jmp L96\n\t" - "L94:\n\t" - : "=D" (p) - : "D" (p), "d" (pe) + "L98:\n\t" + : : "D" (p), "d" (pe) : "ecx" ); - do_tick(); - BAILR + p = pe + 1; } while (!done); } } @@ -255,16 +298,17 @@ void addr_tst2() * produce random numbers in reverse order testing is only done in the forward * direction. */ -void movinvr() +void movinvr(int me) { int i, j, done, seed1, seed2; - volatile ulong *pe; - volatile ulong *start,*end; - ulong num; - uintptr_t seg_start; + ulong *p; + ulong *pe; + ulong *start,*end; + ulong xorVal; + //ulong num, bad; /* Initialize memory with initial sequence of random numbers. */ - if (v->rdtsc) { + if (cpu_id.fid.bits.rdtsc) { asm __volatile__ ("rdtsc":"=a" (seed1),"=d" (seed2)); } else { seed1 = 521288629 + v->pass; @@ -272,85 +316,87 @@ void movinvr() } /* Display the current seed */ - hprint(LINE_PAT, COL_PAT, seed1); - rand_seed(seed1, seed2); + if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, seed1); + rand_seed(seed1, seed2, me); for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 4); pe = start; p = start; - seg_start = (uintptr_t)p; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if (seg_start == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code */ /* - for (; p < pe; p++) { - *p = rand(); + for (; p <= pe; p++) { + *p = rand(me); } */ - asm __volatile__ ( - "jmp L200\n\t" - ".p2align 4,,7\n\t" - "L200:\n\t" - "call rand\n\t" + asm __volatile__ ( + "jmp L200\n\t" + ".p2align 4,,7\n\t" + "L201:\n\t" + "addl $4,%%edi\n\t" + "L200:\n\t" + "pushl %%ecx\n\t" \ + "call rand\n\t" + "popl %%ecx\n\t" \ "movl %%eax,(%%edi)\n\t" - "addl $4,%%edi\n\t" - "cmpl %%ebx,%%edi\n\t" - "jb L200\n\t" - : "=D" (p) - : "D" (p), "b" (pe) - : "eax", "edx" - ); - - do_tick(); - BAILR + "cmpl %%ebx,%%edi\n\t" + "jb L201\n\t" + : : "D" (p), "b" (pe), "c" (me) + : "eax" + ); + p = pe + 1; } while (!done); } /* Do moving inversions test. Check for initial pattern and then - * write the complement for each memory location. Test from bottom - * up and then from the top down. */ + * write the complement for each memory location. + */ for (i=0; i<2; i++) { - rand_seed(seed1, seed2); + rand_seed(seed1, seed2, me); for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 4); pe = start; p = start; - seg_start = (uintptr_t)p; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if (seg_start == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code */ -/* - for (; p < pe; p++) { - num = rand(); + + /*for (; p <= pe; p++) { + num = rand(me); if (i) { num = ~num; } @@ -358,51 +404,85 @@ void movinvr() error((ulong*)p, num, bad); } *p = ~num; - } -*/ + }*/ + if (i) { - num = 0xffffffff; + xorVal = 0xffffffff; } else { - num = 0; + xorVal = 0; } asm __volatile__ ( - "jmp L26\n\t" \ + + "pushl %%ebp\n\t" - ".p2align 4,,7\n\t" \ - "L26:\n\t" \ + // Skip first increment + "jmp L26\n\t" + ".p2align 4,,7\n\t" + + // increment 4 bytes (32-bits) + "L27:\n\t" + "addl $4,%%edi\n\t" + + // Check this byte + "L26:\n\t" + + // Get next random number, pass in me(edx), random value returned in num(eax) + // num = rand(me); + // cdecl call maintains all registers except eax, ecx, and edx + // We maintain edx with a push and pop here using it also as an input + // we don't need the current eax value and want it to change to the return value + // we overwrite ecx shortly after this discarding its current value + "pushl %%edx\n\t" // Push function inputs onto stack "call rand\n\t" - "xorl %%ebx,%%eax\n\t" \ - "movl (%%edi),%%ecx\n\t" \ - "cmpl %%eax,%%ecx\n\t" \ - "jne L23\n\t" \ - "L25:\n\t" \ - "movl $0xffffffff,%%edx\n\t" \ - "xorl %%edx,%%eax\n\t" \ - "movl %%eax,(%%edi)\n\t" \ - "addl $4,%%edi\n\t" \ - "cmpl %%esi,%%edi\n\t" \ - "jb L26\n\t" \ - "jmp L24\n" \ + "popl %%edx\n\t" // Remove function inputs from stack - "L23:\n\t" \ - "pushl %%esi\n\t" \ - "pushl %%ecx\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%edi\n\t" \ - "call error\n\t" \ - "popl %%edi\n\t" \ - "popl %%eax\n\t" \ - "popl %%ecx\n\t" \ - "popl %%esi\n\t" \ - "jmp L25\n" \ + // XOR the random number with xorVal(ebx), which is either 0xffffffff or 0 depending on the outer loop + // if (i) { num = ~num; } + "xorl %%ebx,%%eax\n\t" + + // Move the current value of the current position p(edi) into bad(ecx) + // (bad=*p) + "movl (%%edi),%%ecx\n\t" + + // Compare bad(ecx) to num(eax) + "cmpl %%eax,%%ecx\n\t" - "L24:\n\t" \ - : "=D" (p) - : "D" (p), "S" (pe), "b" (num) - : "eax", "ecx", "edx" + // If not equal jump the error case + "jne L23\n\t" + + // Set a new value or not num(eax) at the current position p(edi) + // *p = ~num; + "L25:\n\t" + "movl $0xffffffff,%%ebp\n\t" + "xorl %%ebp,%%eax\n\t" + "movl %%eax,(%%edi)\n\t" + + // Loop until current position p(edi) equals the end position pe(esi) + "cmpl %%esi,%%edi\n\t" + "jb L27\n\t" + "jmp L24\n" + + // Error case + "L23:\n\t" + // Must manually maintain eax, ecx, and edx as part of cdecl call convention + "pushl %%edx\n\t" + "pushl %%ecx\n\t" // Next three pushes are functions input + "pushl %%eax\n\t" + "pushl %%edi\n\t" + "call error\n\t" + "popl %%edi\n\t" // Remove function inputs from stack and restore register values + "popl %%eax\n\t" + "popl %%ecx\n\t" + "popl %%edx\n\t" + "jmp L25\n" + + "L24:\n\t" + "popl %%ebp\n\t" + :: "D" (p), "S" (pe), "b" (xorVal), + "d" (me) + : "eax", "ecx" ); - do_tick(); - BAILR + p = pe + 1; } while (!done); } } @@ -412,51 +492,54 @@ void movinvr() * Test all of memory using a "moving inversions" algorithm using the * pattern in p1 and it's complement in p2. */ -void movinv1(int iter, ulong p1, ulong p2) +void movinv1 (int iter, ulong p1, ulong p2, int me) { int i, j, done; - volatile ulong *pe; - volatile ulong len; - volatile ulong *start,*end; + ulong *p, *pe, len, *start, *end; /* Display the current pattern */ - hprint(LINE_PAT, COL_PAT, p1); + if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 4); + + pe = start; p = start; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - len = pe - p; - if ((uintptr_t)p == (uintptr_t)pe) { + len = pe - p + 1; + 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 + // seems broken + /*for (; p <= pe; p++) { + *p = p1; + }*/ + asm __volatile__ ( "rep\n\t" \ "stosl\n\t" - : "=D" (p) - : "c" (len), "0" (p), "a" (p1) + : : "c" (len), "D" (p), "a" (p1) ); - do_tick(); - BAILR + + p = pe + 1; } while (!done); } @@ -465,46 +548,50 @@ void movinv1(int iter, ulong p1, ulong p2) * up and then from the top down. */ for (i=0; i<iter; i++) { for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 4); pe = start; p = start; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + 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 + // seems broken + /*for (; p <= pe; p++) { + if ((bad=*p) != p1) { + error((ulong*)p, p1, bad); + } + *p = p2; + }*/ + asm __volatile__ ( "jmp L2\n\t" \ - ".p2align 4,,7\n\t" \ + "L0:\n\t" \ + "addl $4,%%edi\n\t" \ "L2:\n\t" \ "movl (%%edi),%%ecx\n\t" \ "cmpl %%eax,%%ecx\n\t" \ "jne L3\n\t" \ "L5:\n\t" \ "movl %%ebx,(%%edi)\n\t" \ - "addl $4,%%edi\n\t" \ "cmpl %%edx,%%edi\n\t" \ - "jb L2\n\t" \ + "jb L0\n\t" \ "jmp L4\n" \ "L3:\n\t" \ @@ -522,57 +609,61 @@ void movinv1(int iter, ulong p1, ulong p2) "jmp L5\n" \ "L4:\n\t" \ - : "=D" (p) - : "a" (p1), "0" (p), "d" (pe), "b" (p2) + :: "a" (p1), "D" (p), "d" (pe), "b" (p2) : "ecx" ); - do_tick(); - BAILR + p = pe + 1; } while (!done); } for (j=segs-1; j>=0; j--) { - start = v->map[j].start; - end = v->map[j].end; - pe = end -1; - p = end -1; + calculate_chunk(&start, &end, me, j, 4); + pe = end; + p = end; done = 0; do { + do_tick(me); + BAILR + /* Check for underflow */ - if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) { + if (pe - SPINSZ < pe && pe != 0) { pe -= SPINSZ; } else { pe = start; + done++; } - if ((uintptr_t)pe <= (uintptr_t)start) { + + /* Since we are using unsigned addresses a + * redundent check is required */ + if (pe < start || pe > end) { pe = start; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + 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 + // seems broken + /*do { + if ((bad=*p) != p2) { + error((ulong*)p, p2, bad); + } + *p = p1; + } while (--p >= pe);*/ + asm __volatile__ ( - "addl $4, %%edi\n\t" "jmp L9\n\t" - ".p2align 4,,7\n\t" - "L9:\n\t" + "L11:\n\t" "subl $4, %%edi\n\t" + "L9:\n\t" "movl (%%edi),%%ecx\n\t" "cmpl %%ebx,%%ecx\n\t" "jne L6\n\t" "L10:\n\t" "movl %%eax,(%%edi)\n\t" "cmpl %%edi, %%edx\n\t" - "jne L9\n\t" - "subl $4, %%edi\n\t" + "jne L11\n\t" "jmp L7\n\t" "L6:\n\t" @@ -590,58 +681,52 @@ void movinv1(int iter, ulong p1, ulong p2) "jmp L10\n" "L7:\n\t" - : "=D" (p) - : "a" (p1), "0" (p), "d" (pe), "b" (p2) + :: "a" (p1), "D" (p), "d" (pe), "b" (p2) : "ecx" ); - do_tick(); - BAILR + p = pe - 1; } while (!done); } } } -void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) +void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off,int me) { - int i, j, k=0, done; - volatile ulong *pe; - volatile ulong *start, *end; - ulong pat = 0; - -/* CDH start - * ulong p3 = sval << 31; - * CDH end - */ + int i, j, k=0, n=0, done; + ulong *p, *pe, *start, *end, pat = 0, p3; + p3 = sval << 31; /* Display the current pattern */ - hprint(LINE_PAT, COL_PAT, p1); + if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 64); pe = start; p = start; done = 0; k = off; pat = p1; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } /* Do a SPINSZ section of memory */ /* Original C code replaced with hand tuned assembly code - * while (p < pe) { + * while (p <= pe) { * *p = pat; * if (++k >= 32) { * pat = lb; @@ -654,24 +739,29 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) * } */ asm __volatile__ ( - "jmp L20\n\t" - ".p2align 4,,7\n\t" - -/* CDH start */ - "L20:\n\t" - "movl %%ecx,(%%edi)\n\t" - "incb %%bl\n\t" - "addl $4,%%edi\n\t" - "roll $1,%%ecx\n\t" - "cmpl %%edx,%%edi\n\t" - "jb L20\n\t" - "andb $31,%%bl\n\t" - : "=b" (k), "=D" (p), "=c" (pat) - : "D" (p),"d" (pe),"b" (k),"c" (pat) -/* CDH end */ + "jmp L20\n\t" + ".p2align 4,,7\n\t" + "L923:\n\t" + "addl $4,%%edi\n\t" + "L20:\n\t" + "movl %%ecx,(%%edi)\n\t" + "addl $1,%%ebx\n\t" + "cmpl $32,%%ebx\n\t" + "jne L21\n\t" + "movl %%esi,%%ecx\n\t" + "xorl %%ebx,%%ebx\n\t" + "jmp L22\n" + "L21:\n\t" + "shll $1,%%ecx\n\t" + "orl %%eax,%%ecx\n\t" + "L22:\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L923\n\t" + : "=b" (k), "=c" (pat) + : "D" (p),"d" (pe),"b" (k),"c" (pat), + "a" (sval), "S" (lb) ); - do_tick(); - BAILR + p = pe + 1; } while (!done); } @@ -680,33 +770,38 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) * up and then from the top down. */ for (i=0; i<iter; i++) { for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 64); pe = start; p = start; done = 0; k = off; pat = p1; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code - * while (p < pe) { + * while (1) { * if ((bad=*p) != pat) { * error((ulong*)p, pat, bad); * } * *p = ~pat; + * if (p >= pe) break; + * p++; + * * if (++k >= 32) { * pat = lb; * k = 0; @@ -714,112 +809,108 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) * pat = pat << 1; * pat |= sval; * } - * p++; * } */ asm __volatile__ ( - "pushl %%ebp\n\t" - "jmp L30\n\t" - - ".p2align 4,,7\n\t" - "L30:\n\t" - "movl (%%edi),%%ebp\n\t" - "cmpl %%ecx,%%ebp\n\t" - "jne L34\n\t" - -/* CDH start */ - "L35:\n\t" - "notl %%ecx\n\t" - "movl %%ecx,(%%edi)\n\t" - "notl %%ecx\n\t" - "addl $4,%%edi\n\t" - "incb %%bl\n\t" - "roll $1,%%ecx\n\t" - "cmpl %%edx,%%edi\n\t" - "jb L30\n\t" - "jmp L33\n\t" -/* CDH end */ - - "L34:\n\t" \ - "pushl %%esi\n\t" - "pushl %%eax\n\t" - "pushl %%ebx\n\t" - "pushl %%edx\n\t" - "pushl %%ebp\n\t" - "pushl %%ecx\n\t" - "pushl %%edi\n\t" - "call error\n\t" - "popl %%edi\n\t" - "popl %%ecx\n\t" - "popl %%ebp\n\t" - "popl %%edx\n\t" - "popl %%ebx\n\t" - "popl %%eax\n\t" - "popl %%esi\n\t" - "jmp L35\n" - -/* CDH start */ - "L33:\n\t" - "andb $31,%%bl\n\t" - "popl %%ebp\n\t" - : "=b" (k), "=D" (p), "=c" (pat) - : "D" (p),"d" (pe),"b" (k),"c" (pat) -/* CDH end */ + "pushl %%ebp\n\t" + "jmp L30\n\t" + ".p2align 4,,7\n\t" + "L930:\n\t" + "addl $4,%%edi\n\t" + "L30:\n\t" + "movl (%%edi),%%ebp\n\t" + "cmpl %%ecx,%%ebp\n\t" + "jne L34\n\t" + + "L35:\n\t" + "notl %%ecx\n\t" + "movl %%ecx,(%%edi)\n\t" + "notl %%ecx\n\t" + "incl %%ebx\n\t" + "cmpl $32,%%ebx\n\t" + "jne L31\n\t" + "movl %%esi,%%ecx\n\t" + "xorl %%ebx,%%ebx\n\t" + "jmp L32\n" + "L31:\n\t" + "shll $1,%%ecx\n\t" + "orl %%eax,%%ecx\n\t" + "L32:\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L930\n\t" + "jmp L33\n\t" + + "L34:\n\t" \ + "pushl %%esi\n\t" + "pushl %%eax\n\t" + "pushl %%ebx\n\t" + "pushl %%edx\n\t" + "pushl %%ebp\n\t" + "pushl %%ecx\n\t" + "pushl %%edi\n\t" + "call error\n\t" + "popl %%edi\n\t" + "popl %%ecx\n\t" + "popl %%ebp\n\t" + "popl %%edx\n\t" + "popl %%ebx\n\t" + "popl %%eax\n\t" + "popl %%esi\n\t" + "jmp L35\n" + + "L33:\n\t" + "popl %%ebp\n\t" + : "=b" (k),"=c" (pat) + : "D" (p),"d" (pe),"b" (k),"c" (pat), + "a" (sval), "S" (lb) ); - do_tick(); - BAILR + p = pe + 1; } while (!done); } - /* Since we already adjusted k and the pattern this - * code backs both up one step - */ -/* CDH start */ -/* Original C code replaced with hand tuned assembly code - * pat = lb; - * if ( 0 != (k = (k-1) & 31) ) { - * pat = (pat << k); - * if ( sval ) - * pat |= ((sval << k) - 1); - * } - * k++; - */ - asm __volatile__ ( - "decl %%ecx\n\t" - "andl $31,%%ecx\n\t" - "roll %%cl,%%ebx\n\t" - "incb %%cl\n\t" - : "=c" (k), "=b" (pat) - : "c" (k), "b" (lb) - ); -/* CDH end */ + if (--k < 0) { + k = 31; + } + for (pat = lb, n = 0; n < k; n++) { + pat = pat << 1; + pat |= sval; + } + k++; for (j=segs-1; j>=0; j--) { - start = v->map[j].start; - end = v->map[j].end; - p = end -1; - pe = end -1; + calculate_chunk(&start, &end, me, j, 64); + p = end; + pe = end; done = 0; do { + do_tick(me); + BAILR + /* Check for underflow */ - if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) { - pe -= SPINSZ; - } else { - pe = start; - } - if ((uintptr_t)pe <= (uintptr_t)start) { + if (pe - SPINSZ < pe && pe != 0) { + pe -= SPINSZ; + } else { + pe = start; + done++; + } + /* We need this redundant check because we are + * using unsigned longs for the address. + */ + if (pe < start || pe > end) { pe = start; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code - * do { + * while(1) { * if ((bad=*p) != ~pat) { * error((ulong*)p, ~pat, bad); * } * *p = pat; + if (p >= pe) break; + p++; * if (--k <= 0) { * pat = hb; * k = 32; @@ -827,61 +918,62 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) * pat = pat >> 1; * pat |= p3; * } - * } while (p-- > pe); + * }; */ asm __volatile__ ( - "pushl %%ebp\n\t" - "addl $4,%%edi\n\t" - "jmp L40\n\t" - - ".p2align 4,,7\n\t" - "L40:\n\t" - "subl $4,%%edi\n\t" - "movl (%%edi),%%ebp\n\t" - "notl %%ecx\n\t" - "cmpl %%ecx,%%ebp\n\t" - "jne L44\n\t" - -/* CDH start */ - "L45:\n\t" - "notl %%ecx\n\t" - "movl %%ecx,(%%edi)\n\t" - "decb %%bl\n\t" - "rorl $1,%%ecx\n\t" - "cmpl %%edx,%%edi\n\t" - "ja L40\n\t" - "jmp L43\n\t" -/* CDH end */ - - "L44:\n\t" \ - "pushl %%esi\n\t" - "pushl %%eax\n\t" - "pushl %%ebx\n\t" - "pushl %%edx\n\t" - "pushl %%ebp\n\t" - "pushl %%ecx\n\t" - "pushl %%edi\n\t" - "call error\n\t" - "popl %%edi\n\t" - "popl %%ecx\n\t" - "popl %%ebp\n\t" - "popl %%edx\n\t" - "popl %%ebx\n\t" - "popl %%eax\n\t" - "popl %%esi\n\t" - "jmp L45\n" - -/* CDH start */ - "L43:\n\t" - "andb $31,%%bl\n\t" - "subl $4,%%edi\n\t" - "popl %%ebp\n\t" - : "=b" (k), "=D" (p), "=c" (pat) - : "D" (p),"d" (pe),"b" (k),"c" (pat) -/* CDH end */ + "pushl %%ebp\n\t" + "jmp L40\n\t" + ".p2align 4,,7\n\t" + "L49:\n\t" + "subl $4,%%edi\n\t" + "L40:\n\t" + "movl (%%edi),%%ebp\n\t" + "notl %%ecx\n\t" + "cmpl %%ecx,%%ebp\n\t" + "jne L44\n\t" + + "L45:\n\t" + "notl %%ecx\n\t" + "movl %%ecx,(%%edi)\n\t" + "decl %%ebx\n\t" + "cmpl $0,%%ebx\n\t" + "jg L41\n\t" + "movl %%esi,%%ecx\n\t" + "movl $32,%%ebx\n\t" + "jmp L42\n" + "L41:\n\t" + "shrl $1,%%ecx\n\t" + "orl %%eax,%%ecx\n\t" + "L42:\n\t" + "cmpl %%edx,%%edi\n\t" + "ja L49\n\t" + "jmp L43\n\t" + + "L44:\n\t" \ + "pushl %%esi\n\t" + "pushl %%eax\n\t" + "pushl %%ebx\n\t" + "pushl %%edx\n\t" + "pushl %%ebp\n\t" + "pushl %%ecx\n\t" + "pushl %%edi\n\t" + "call error\n\t" + "popl %%edi\n\t" + "popl %%ecx\n\t" + "popl %%ebp\n\t" + "popl %%edx\n\t" + "popl %%ebx\n\t" + "popl %%eax\n\t" + "popl %%esi\n\t" + "jmp L45\n" + + "L43:\n\t" + "popl %%ebp\n\t" + : "=b" (k), "=c" (pat) + : "D" (p),"d" (pe),"b" (k),"c" (pat), + "a" (p3), "S" (hb) ); - do_tick(); - BAILR + p = pe - 1; } while (!done); } } @@ -890,40 +982,46 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) /* * Test all of memory using modulo X access pattern. */ -void modtst(int offset, int iter, ulong p1, ulong p2) +void modtst(int offset, int iter, ulong p1, ulong p2, int me) { int j, k, l, done; - volatile ulong *pe; - volatile ulong *start, *end; + ulong *p; + ulong *pe; + ulong *start, *end; /* Display the current pattern */ - hprint(LINE_PAT, COL_PAT-2, p1); - cprint(LINE_PAT, COL_PAT+6, "-"); - dprint(LINE_PAT, COL_PAT+7, offset, 2, 1); + if (mstr_cpu == me) { + hprint(LINE_PAT, COL_PAT-2, p1); + cprint(LINE_PAT, COL_PAT+6, "-"); + dprint(LINE_PAT, COL_PAT+7, offset, 2, 1); + } /* Write every nth location with pattern */ for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 4); + end -= MOD_SZ; /* adjust the ending address */ pe = (ulong *)start; p = start+offset; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code - * for (; p < pe; p += MOD_SZ) { + * for (; p <= pe; p += MOD_SZ) { * *p = p1; * } */ @@ -939,36 +1037,36 @@ void modtst(int offset, int iter, ulong p1, ulong p2) : "=D" (p) : "D" (p), "d" (pe), "a" (p1) ); - do_tick(); - BAILR } while (!done); } /* Write the rest of memory "iter" times with the pattern complement */ for (l=0; l<iter; l++) { for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 4); pe = (ulong *)start; p = start; done = 0; k = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code - * for (; p < pe; p++) { + * for (; p <= pe; p++) { * if (k != offset) { * *p = p2; * } @@ -981,6 +1079,8 @@ void modtst(int offset, int iter, ulong p1, ulong p2) "jmp L50\n\t" \ ".p2align 4,,7\n\t" \ + "L54:\n\t" \ + "addl $4,%%edi\n\t" \ "L50:\n\t" \ "cmpl %%ebx,%%ecx\n\t" \ "je L52\n\t" \ @@ -991,43 +1091,43 @@ void modtst(int offset, int iter, ulong p1, ulong p2) "jle L53\n\t" \ "xorl %%ebx,%%ebx\n\t" \ "L53:\n\t" \ - "addl $4,%%edi\n\t" \ "cmpl %%edx,%%edi\n\t" \ - "jb L50\n\t" \ - : "=D" (p), "=b" (k) + "jb L54\n\t" \ + : "=b" (k) : "D" (p), "d" (pe), "a" (p2), "b" (k), "c" (offset) ); - do_tick(); - BAILR + p = pe + 1; } while (!done); } } /* Now check every nth location */ for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; + calculate_chunk(&start, &end, me, j, 4); pe = (ulong *)start; p = start+offset; done = 0; + end -= MOD_SZ; /* adjust the ending address */ do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { + if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { - + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code - * for (; p < pe; p += MOD_SZ) { + * for (; p <= pe; p += MOD_SZ) { * if ((bad=*p) != p1) { * error((ulong*)p, p1, bad); * } @@ -1064,211 +1164,231 @@ void modtst(int offset, int iter, ulong p1, ulong p2) : "D" (p), "d" (pe), "a" (p1) : "ecx" ); - do_tick(); - BAILR } while (!done); } - cprint(LINE_PAT, COL_PAT, " "); } - - /* - * Test memory using block moves + * Test memory using block moves * Adapted from Robert Redelmeier's burnBX test */ -void block_move(int iter) +void block_move(int iter, int me) { int i, j, done; ulong len; - volatile ulong p, pe, pp; - volatile ulong start, end; + ulong *p, *pe, pp; + ulong *start, *end; - cprint(LINE_PAT, COL_PAT-2, " "); + cprint(LINE_PAT, COL_PAT-2, " "); /* Initialize memory with the initial pattern. */ for (j=0; j<segs; j++) { - start = (ulong)v->map[j].start; -#ifdef USB_WAR - /* We can't do the block move test on low memory beacuase - * BIOS USB support clobbers location 0x410 and 0x4e0 - */ - if (start < 0x4f0) { - start = 0x4f0; - } -#endif - end = (ulong)v->map[j].end; + calculate_chunk(&start, &end, me, j, 64); + + // end is always xxxxxffc, so increment so that length calculations are correct + end = end + 1; + pe = start; p = start; + done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) { - pe += SPINSZ*4; + if (pe + SPINSZ > pe && pe != 0) { + pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { - + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { - + if (p == pe ) { break; } len = ((ulong)pe - (ulong)p) / 64; + //len++; asm __volatile__ ( "jmp L100\n\t" ".p2align 4,,7\n\t" "L100:\n\t" + + // First loop eax is 0x00000001, edx is 0xfffffffe "movl %%eax, %%edx\n\t" "notl %%edx\n\t" - "movl %%eax,0(%%edi)\n\t" - "movl %%eax,4(%%edi)\n\t" - "movl %%eax,8(%%edi)\n\t" - "movl %%eax,12(%%edi)\n\t" - "movl %%edx,16(%%edi)\n\t" - "movl %%edx,20(%%edi)\n\t" - "movl %%eax,24(%%edi)\n\t" - "movl %%eax,28(%%edi)\n\t" - "movl %%eax,32(%%edi)\n\t" - "movl %%eax,36(%%edi)\n\t" - "movl %%edx,40(%%edi)\n\t" - "movl %%edx,44(%%edi)\n\t" - "movl %%eax,48(%%edi)\n\t" - "movl %%eax,52(%%edi)\n\t" - "movl %%edx,56(%%edi)\n\t" - "movl %%edx,60(%%edi)\n\t" - "rcll $1, %%eax\n\t" + + // Set a block of 64-bytes // First loop DWORDS are + "movl %%eax,0(%%edi)\n\t" // 0x00000001 + "movl %%eax,4(%%edi)\n\t" // 0x00000001 + "movl %%eax,8(%%edi)\n\t" // 0x00000001 + "movl %%eax,12(%%edi)\n\t" // 0x00000001 + "movl %%edx,16(%%edi)\n\t" // 0xfffffffe + "movl %%edx,20(%%edi)\n\t" // 0xfffffffe + "movl %%eax,24(%%edi)\n\t" // 0x00000001 + "movl %%eax,28(%%edi)\n\t" // 0x00000001 + "movl %%eax,32(%%edi)\n\t" // 0x00000001 + "movl %%eax,36(%%edi)\n\t" // 0x00000001 + "movl %%edx,40(%%edi)\n\t" // 0xfffffffe + "movl %%edx,44(%%edi)\n\t" // 0xfffffffe + "movl %%eax,48(%%edi)\n\t" // 0x00000001 + "movl %%eax,52(%%edi)\n\t" // 0x00000001 + "movl %%edx,56(%%edi)\n\t" // 0xfffffffe + "movl %%edx,60(%%edi)\n\t" // 0xfffffffe + + // rotate left with carry, + // second loop eax is 0x00000002 + // second loop edx is (~eax) 0xfffffffd + "rcll $1, %%eax\n\t" + + // Move current position forward 64-bytes (to start of next block) "leal 64(%%edi), %%edi\n\t" + + // Loop until end "decl %%ecx\n\t" "jnz L100\n\t" + : "=D" (p) : "D" (p), "c" (len), "a" (1) : "edx" ); - do_tick(); - BAILR } while (!done); } + s_barrier(); - /* Now move the data around + /* Now move the data around * First move the data up half of the segment size we are testing * Then move the data to the original location + 32 bytes */ for (j=0; j<segs; j++) { - start = (ulong)v->map[j].start; -#ifdef USB_WAR - /* We can't do the block move test on low memory beacuase - * BIOS USB support clobbers location 0x410 and 0x4e0 - */ - if (start < 0x4f0) { - start = 0x4f0; - } -#endif - end = (ulong)v->map[j].end; + calculate_chunk(&start, &end, me, j, 64); + + // end is always xxxxxffc, so increment so that length calculations are correct + end = end + 1; pe = start; p = start; done = 0; + do { + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) { - pe += SPINSZ*4; + if (pe + SPINSZ > pe && pe != 0) { + pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } - pp = p + ((pe - p) / 2); - len = ((ulong)pe - (ulong)p) / 8; + pp = (ulong)p + (((ulong)pe - (ulong)p) / 2); // Mid-point of this block + len = ((ulong)pe - (ulong)p) / 8; // Half the size of this block in DWORDS for(i=0; i<iter; i++) { + do_tick(me); + BAILR asm __volatile__ ( "cld\n" "jmp L110\n\t" ".p2align 4,,7\n\t" "L110:\n\t" - "movl %1,%%edi\n\t" - "movl %0,%%esi\n\t" - "movl %2,%%ecx\n\t" + + // + // At the end of all this + // - the second half equals the inital value of the first half + // - the first half is right shifted 32-bytes (with wrapping) + // + + // Move first half to second half + "movl %1,%%edi\n\t" // Destionation, pp (mid point) + "movl %0,%%esi\n\t" // Source, p (start point) + "movl %2,%%ecx\n\t" // Length, len (size of a half in DWORDS) "rep\n\t" "movsl\n\t" + + // Move the second half, less the last 32-bytes. To the first half, offset plus 32-bytes "movl %0,%%edi\n\t" - "addl $32,%%edi\n\t" - "movl %1,%%esi\n\t" + "addl $32,%%edi\n\t" // Destination, p(start-point) plus 32 bytes + "movl %1,%%esi\n\t" // Source, pp(mid-point) "movl %2,%%ecx\n\t" - "subl $8,%%ecx\n\t" + "subl $8,%%ecx\n\t" // Length, len(size of a half in DWORDS) minus 8 DWORDS (32 bytes) "rep\n\t" "movsl\n\t" - "movl %0,%%edi\n\t" - "movl $8,%%ecx\n\t" + + // Move last 8 DWORDS (32-bytes) of the second half to the start of the first half + "movl %0,%%edi\n\t" // Destination, p(start-point) + // Source, 8 DWORDS from the end of the second half, left over by the last rep/movsl + "movl $8,%%ecx\n\t" // Length, 8 DWORDS (32-bytes) "rep\n\t" "movsl\n\t" + :: "g" (p), "g" (pp), "g" (len) : "edi", "esi", "ecx" ); - do_tick(); - BAILR } p = pe; } while (!done); } + s_barrier(); - /* Now check the data + /* Now check the data * The error checking is rather crude. We just check that the * adjacent words are the same. */ for (j=0; j<segs; j++) { - start = (ulong)v->map[j].start; -#ifdef USB_WAR - /* We can't do the block move test on low memory beacuase - * BIOS USB support clobbers location 0x4e0 and 0x410 - */ - if (start < 0x4f0) { - start = 0x4f0; - } -#endif - end = (ulong)v->map[j].end; + calculate_chunk(&start, &end, me, j, 64); + + // end is always xxxxxffc, so increment so that length calculations are correct + end = end + 1; pe = start; p = start; done = 0; do { + do_tick(me); + BAILR + /* Check for overflow */ - if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) { - pe += SPINSZ*4; + if (pe + SPINSZ > pe && pe != 0) { + pe += SPINSZ; } else { pe = end; } - if ((uintptr_t)pe >= (uintptr_t)end) { + if (pe >= end) { pe = end; done++; } - if ((uintptr_t)p == (uintptr_t)pe) { + if (p == pe ) { break; } + pe-=2; /* the last dwords to test are pe[0] and pe[1] */ asm __volatile__ ( "jmp L120\n\t" ".p2align 4,,7\n\t" + "L124:\n\t" + "addl $8,%%edi\n\t" // Next QWORD "L120:\n\t" + + // Compare adjacent DWORDS "movl (%%edi),%%ecx\n\t" "cmpl 4(%%edi),%%ecx\n\t" - "jnz L121\n\t" + "jnz L121\n\t" // Print error if they don't match + // Loop until end of block "L122:\n\t" - "addl $8,%%edi\n\t" "cmpl %%edx,%%edi\n\t" - "jb L120\n" + "jb L124\n" "jmp L123\n\t" "L121:\n\t" + // eax not used so we don't need to save it as per cdecl + // ecx is used but not restored, however we don't need it's value anymore after this point "pushl %%edx\n\t" "pushl 4(%%edi)\n\t" "pushl %%ecx\n\t" @@ -1283,79 +1403,104 @@ void block_move(int iter) : "D" (p), "d" (pe) : "ecx" ); - do_tick(); - BAILR } while (!done); } } /* - * Test memory for bit fade. + * Test memory for bit fade, fill memory with pattern. */ -#define STIME 5400 -void bit_fade() +void bit_fade_fill(ulong p1, int me) { - int j; - volatile ulong *pe; - volatile ulong bad; - volatile ulong *start,*end; - - test_ticks += (STIME * 2); - v->pass_ticks += (STIME * 2); + int j, done; + ulong *p, *pe; + ulong *start,*end; - /* Do -1 and 0 patterns */ - p1 = 0; - while (1) { + /* Display the current pattern */ + hprint(LINE_PAT, COL_PAT, p1); - /* Display the current pattern */ - hprint(LINE_PAT, COL_PAT, p1); + /* Initialize memory with the initial pattern. */ + for (j=0; j<segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = (ulong *)start; + p = start; + done = 0; + do { + do_tick(me); + BAILR - /* Initialize memory with the initial pattern. */ - for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; - pe = start; - p = start; - for (p=start; p<end; p++) { + /* Check for overflow */ + if (pe + SPINSZ > pe && pe != 0) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (p == pe ) { + break; + } + for (; p < pe;) { *p = p1; + p++; } - do_tick(); + p = pe + 1; + } while (!done); + } +} + +void bit_fade_chk(ulong p1, int me) +{ + int j, done; + ulong *p, *pe, bad; + ulong *start,*end; + + /* Make sure that nothing changed while sleeping */ + for (j=0; j<segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = (ulong *)start; + p = start; + done = 0; + do { + do_tick(me); BAILR - } - /* Snooze for 90 minutes */ - sleep (STIME, 0); - /* Make sure that nothing changed while sleeping */ - for (j=0; j<segs; j++) { - start = v->map[j].start; - end = v->map[j].end; - pe = start; - p = start; - for (p=start; p<end; p++) { - if ((bad=*p) != p1) { + /* Check for overflow */ + if (pe + SPINSZ > pe && pe != 0) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (p == pe ) { + break; + } + for (; p < pe;) { + if ((bad=*p) != p1) { error((ulong*)p, p1, bad); } + p++; } - do_tick(); - BAILR - } - if (p1 == 0) { - p1=-1; - } else { - break; - } + p = pe + 1; + } while (!done); } } -/* Sleep function */ -void sleep(int n, int sms) + +/* Sleep for N seconds */ +void sleep(long n, int flag, int me, int sms) { - int i, ip; - ulong sh, sl, l, h, t; + ulong sh, sl, l, h, t, ip=0; - ip = 0; /* save the starting time */ asm __volatile__( "rdtsc":"=a" (sl),"=d" (sh)); @@ -1363,6 +1508,7 @@ void sleep(int n, int sms) /* loop for n seconds */ while (1) { asm __volatile__( + "rep ; nop\n\t" "rdtsc":"=a" (l),"=d" (h)); asm __volatile__ ( "subl %2,%0\n\t" @@ -1378,31 +1524,21 @@ void sleep(int n, int sms) t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000; t += (l / v->clks_msec) / 1000; } - + /* Is the time up? */ if (t >= n) { break; } - /* Display the elapsed time on the screen */ - if (sms == 0) { - - i = t % 60; - dprint(LINE_TIME, COL_TIME+9, i%10, 1, 0); - dprint(LINE_TIME, COL_TIME+8, i/10, 1, 0); - - if (i != ip) { - check_input(); - ip = i; - } + /* Only display elapsed time if flag is set */ + if (flag == 0) { + continue; + } - t /= 60; - i = t % 60; - dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0); - dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0); - t /= 60; - dprint(LINE_TIME, COL_TIME, t, 4, 0); + if (t != ip) { + do_tick(me); BAILR + ip = t; } } } @@ -1411,6 +1547,7 @@ void sleep(int n, int sms) void beep(unsigned int frequency) { + unsigned int count = 1193180 / frequency; // Switch on the speaker @@ -1424,7 +1561,7 @@ void beep(unsigned int frequency) outb((count >> 8) & 0xff, 0x42); // Block for 100 microseconds - sleep(100, 1); + sleep(100, 0, 0, 1); // Switch off the speaker outb(inb_p(0x61)&0xFC, 0x61); |