📄 test.c
字号:
/* test.c - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com * ---------------------------------------------------- * MemTest86+ V1.70 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */#include "test.h"#include "config.h"#include <sys/io.h>#include "dmi.h"extern int segs, bail, beepmode;extern volatile ulong *p;extern ulong p1, p2;extern int test_ticks, nticks;extern struct tseq tseq[];void poll_errors();int ecount = 0;static void update_err_counts(void);static void print_err_counts(void);static inline ulong roundup(ulong value, ulong mask){ return (value + mask) & ~mask;}/* * Memory address test, walking ones */void addr_tst1(){ int i, j, k; volatile ulong *pt; volatile ulong *end; ulong bad, mask, bank; /* Test the global address bits */ for (p1=0, j=0; j<2; j++) { 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; for (i=0; i<1000; i++) { mask = 4; do { pt = (ulong *)((ulong)p | mask); if (pt == p) { mask = mask << 1; continue; } if (pt >= end) { break; } *pt = p1; if ((bad = *p) != ~p1) { ad_err1((ulong *)p, (ulong *)mask, bad, ~p1); i = 1000; } mask = mask << 1; } while(mask); } do_tick(); BAILR } /* Now check the address bits in each bank */ /* If we have more than 8mb of memory then the bank size must be */ /* bigger than 256k. If so use 1mb for the bank size. */ if (v->pmap[v->msegs - 1].end > (0x800000 >> 12)) { bank = 0x100000; } else { bank = 0x40000; } for (p1=0, k=0; k<2; k++) { 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 (p < end) { *p = p1; p1 = ~p1; for (i=0; i<200; i++) { mask = 4; do { pt = (ulong *) ((ulong)p | mask); if (pt == p) { mask = mask << 1; continue; } if (pt >= end) { break; } *pt = p1; if ((bad = *p) != ~p1) { ad_err1((ulong *)p, (ulong *)mask, bad,~p1); i = 200; } mask = mask << 1; } while(mask); } if (p + bank/4 > p) { p += bank/4; } else { p = end; } p1 = ~p1; } } do_tick(); BAILR p1 = ~p1; }}/* * Memory address test, own address */void addr_tst2(){ int j, done; volatile ulong *pe; volatile ulong *end, *start; cprint(LINE_PAT, COL_PAT, " "); /* Write each address with it's own address */ for (j=0; j<segs; j++) { start = v->map[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { /* Check for overflow */ if (pe + SPINSZ > pe) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; }/* Original C code replaced with hand tuned assembly code * for (; p < pe; p++) { * *p = (ulong)p; * } */ asm __volatile__ ( "jmp L90\n\t" ".p2align 4,,7\n\t" "L90:\n\t" "movl %%edi,(%%edi)\n\t" "addl $4,%%edi\n\t" "cmpl %%edx,%%edi\n\t" "jb L90\n\t" : "=D" (p) : "D" (p), "d" (pe) ); do_tick(); BAILR } while (!done); } /* Each address should have its own address */ for (j=0; j<segs; j++) { start = v->map[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { /* Check for overflow */ if (pe + SPINSZ > pe) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; }/* Original C code replaced with hand tuned assembly code * for (; p < pe; p++) { * if((bad = *p) != (ulong)p) { * ad_err2((ulong)p, bad); * } * } */ asm __volatile__ ( "jmp L91\n\t" ".p2align 4,,7\n\t" "L91:\n\t" "movl (%%edi),%%ecx\n\t" "cmpl %%edi,%%ecx\n\t" "jne L93\n\t" "L92:\n\t" "addl $4,%%edi\n\t" "cmpl %%edx,%%edi\n\t" "jb L91\n\t" "jmp L94\n\t" "L93:\n\t" "pushl %%edx\n\t" "pushl %%ecx\n\t" "pushl %%edi\n\t" "call ad_err2\n\t" "popl %%edi\n\t" "popl %%ecx\n\t" "popl %%edx\n\t" "jmp L92\n\t" "L94:\n\t" : "=D" (p) : "D" (p), "d" (pe) : "ecx" ); do_tick(); BAILR } while (!done); }}/* * Test all of memory using a "half moving inversions" algorithm using random * numbers and their complment as the data pattern. Since we are not able to * produce random numbers in reverse order testing is only done in the forward * direction. */void movinvr(){ int i, j, done, seed1, seed2; volatile ulong *pe; volatile ulong *start,*end; ulong num; /* Initialize memory with initial sequence of random numbers. */ if (v->rdtsc) { asm __volatile__ ("rdtsc":"=a" (seed1),"=d" (seed2)); } else { seed1 = 521288629 + v->pass; seed2 = 362436069 - v->pass; } /* Display the current seed */ hprint(LINE_PAT, COL_PAT, seed1); rand_seed(seed1, seed2); for (j=0; j<segs; j++) { start = v->map[j].start; end = v->map[j].end; pe = start; p = start; done = 0; do { /* Check for overflow */ if (pe + SPINSZ > pe) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; }/* Original C code replaced with hand tuned assembly code *//* for (; p < pe; p++) { *p = rand(); } */ asm __volatile__ ( "jmp L200\n\t" ".p2align 4,,7\n\t" "L200:\n\t" "call rand\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" ); do_tick(); BAILR } 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. */ for (i=0; i<2; i++) { rand_seed(seed1, seed2); for (j=0; j<segs; j++) { start = v->map[j].start; end = v->map[j].end; pe = start; p = start; done = 0; do { /* Check for overflow */ if (pe + SPINSZ > pe) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; }/* Original C code replaced with hand tuned assembly code *//* for (; p < pe; p++) { num = rand(); if (i) { num = ~num; } if ((bad=*p) != num) { error((ulong*)p, num, bad); } *p = ~num; }*/ if (i) { num = 0xffffffff; } else { num = 0; } asm __volatile__ ( "jmp L26\n\t" \ ".p2align 4,,7\n\t" \ "L26:\n\t" \ "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" \ "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" \ "L24:\n\t" \ : "=D" (p) : "D" (p), "S" (pe), "b" (num) : "eax", "ecx", "edx" ); do_tick(); BAILR } while (!done); } }}/* * 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){ int i, j, done; volatile ulong *pe; volatile ulong len; volatile ulong *start,*end; /* 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 = start; p = start; done = 0; do { /* Check for overflow */ if (pe + SPINSZ > pe) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } len = pe - p; if (p == pe ) { break; }/* Original C code replaced with hand tuned assembly code * for (; p < pe; p++) { * *p = p1; * } */ asm __volatile__ ( "rep\n\t" \ "stosl\n\t" : "=D" (p) : "c" (len), "0" (p), "a" (p1) ); do_tick(); BAILR } 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. */ for (i=0; i<iter; i++) { for (j=0; j<segs; j++) { start = v->map[j].start; end = v->map[j].end; pe = start; p = start; done = 0; do { /* Check for overflow */ if (pe + SPINSZ > pe) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } 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; * } */ asm __volatile__ ( "jmp L2\n\t" \ ".p2align 4,,7\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" \ "jmp L4\n" \ "L3:\n\t" \ "pushl %%edx\n\t" \ "pushl %%ebx\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 %%ebx\n\t" \ "popl %%edx\n\t" \ "jmp L5\n" \ "L4:\n\t" \ : "=D" (p) : "a" (p1), "0" (p), "d" (pe), "b" (p2) : "ecx" ); do_tick(); BAILR } 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; done = 0; do { /* Check for underflow */ if (pe - SPINSZ < pe) { pe -= SPINSZ; } else { pe = start; } if (pe <= start) { pe = start; done++; } 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); */ asm __volatile__ ( "addl $4, %%edi\n\t" "jmp L9\n\t" ".p2align 4,,7\n\t" "L9:\n\t" "subl $4, %%edi\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" "jmp L7\n\t" "L6:\n\t" "pushl %%edx\n\t" "pushl %%eax\n\t" "pushl %%ecx\n\t" "pushl %%ebx\n\t" "pushl %%edi\n\t" "call error\n\t" "popl %%edi\n\t" "popl %%ebx\n\t" "popl %%ecx\n\t" "popl %%eax\n\t" "popl %%edx\n\t" "jmp L10\n" "L7:\n\t" : "=D" (p)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -