⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 系统启动时检测内存状况的软件C代码
💻 C
字号:
/* main.c - MemTest-86  Version 3.2 * * Released under version 2 of the Gnu Public License. * By Chris Brady * ---------------------------------------------------- * MemTest86+ V1.65 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */#include "test.h"#include "defs.h"#undef TEST_TIMES#define DEFTESTS 11extern void bzero();const struct tseq tseq[] = {	{1,  5,  3,   0, 0, "[Address test, walking ones]          "},	{1,  6,  3,   2, 0, "[Address test, own address]           "},	{1,  0,  3,  14, 0, "[Moving inversions, ones & zeros]     "},	{1,  1,  2,  80, 0, "[Moving inversions, 8 bit pattern]    "},	{1, 10, 60, 300, 0, "[Moving inversions, random pattern]   "},	{1,  7, 64,  66, 0, "[Block move, 64 moves]                "},	{1,  2,  2, 320, 0, "[Moving inversions, 32 bit pattern]   "},	{1,  9, 40, 120, 0, "[Random number sequence]              "},	{1,  3,  4, 240, 0, "[Modulo 20, ones & zeros]             "},	{1,  8,  1,   2, 0, "[Bit fade test, 90 min, 2 patterns]   "},	{0,  4,  3,   2, 0, "[[Moving inversions, 0 & 1, uncached] "},	{0,  0,  0,   0, 0, NULL}};char firsttime = 0;struct vars variables = {};struct vars * const v = &variables;volatile ulong *p = 0;ulong p1 = 0, p2 = 0, p0 = 0;int segs = 0, bail = 0;int test_ticks;int nticks;static int window = 0;static struct pmap windows[] ={	{ 0/* Written at startup */, 0x100000 },	{ 0, RES_START >> 12 },	{ 0x100000, 0x180000 },	{ 0x180000, 0x200000 },	{ 0x200000, 0x280000 },	{ 0x280000, 0x300000 },	{ 0x300000, 0x380000 },	{ 0x380000, 0x400000 },	{ 0x400000, 0x480000 },	{ 0x480000, 0x500000 },	{ 0x500000, 0x580000 },	{ 0x580000, 0x600000 },	{ 0x600000, 0x680000 },	{ 0x680000, 0x700000 },	{ 0x700000, 0x780000 },	{ 0x780000, 0x800000 },	{ 0x800000, 0x880000 },	{ 0x880000, 0x900000 },	{ 0x900000, 0x980000 },	{ 0x980000, 0xA00000 },	{ 0xA00000, 0xA80000 },	{ 0xA80000, 0xB00000 },	{ 0xB00000, 0xB80000 },	{ 0xB80000, 0xC00000 },	{ 0xC00000, 0xC80000 },	{ 0xC80000, 0xD00000 },	{ 0xD00000, 0xD80000 },	{ 0xD80000, 0xE00000 },	{ 0xE00000, 0xE80000 },	{ 0xE80000, 0xF00000 },	{ 0xF00000, 0xF80000 },	{ 0xF80000, 0x1000000 },};#if (LOW_TEST_ADR >= HIGH_TEST_ADR)#error LOW_TEST_ADR and HIGH_TEST_ADR may not overlap#endif#if (LOW_TEST_ADR > (640*1024))#error LOW_TEST_ADR must be below 640K#endifstatic int find_ticks_for_test(unsigned long chunks, int test);static void compute_segments(int win);static void __run_at(unsigned long addr){	/* Copy memtest86 code */	memmove((void *)addr, &_start, _end - _start);	/* Jump to the start address */	p = (ulong *)(addr + startup_32 - _start);	goto *p;}static unsigned long run_at_addr = 0xffffffff;static void run_at(unsigned long addr){	unsigned long start;	unsigned long len;	run_at_addr = addr;	start = (unsigned long) &_start;	len = _end - _start;	if (	((start < addr) && ((start + len) >= addr)) ||		((addr < start) &&  ((addr + len) >= start))) {		/* Handle overlap by doing an extra relocation */		if (addr + len < HIGH_TEST_ADR) {			__run_at(HIGH_TEST_ADR);		}		else if (start + len < addr) {			__run_at(LOW_TEST_ADR);		}	}	__run_at(run_at_addr);}void do_test(void){	int i = 0;	unsigned long chunks;	unsigned long lo, hi;	/* If we have a partial relocation finish it */	if (run_at_addr == (unsigned long)&_start) {		run_at_addr = 0xffffffff;	} else if (run_at_addr != 0xffffffff) {		__run_at(run_at_addr);	}	/* If first time, initialize test */	if (firsttime == 0) {		if ((ulong)&_start != LOW_TEST_ADR) {			restart();		}		windows[0].start =			( LOW_TEST_ADR + (_end - _start) + 4095) >> 12;		init();		firsttime = 1;	}	bail = 0;	/* Find the memory areas I am going to test */	compute_segments(window);	if (segs == 0) {		goto skip_window;	}	/* Now map in the window... */	if (map_page(v->map[0].pbase_addr) < 0) {		goto skip_window;	}	/* Update display of memory segments being tested */	lo = page_of(v->map[0].start);	hi = page_of(v->map[segs -1].end);	aprint(LINE_RANGE, COL_MID+9, lo);	cprint(LINE_RANGE, COL_MID+14, " - ");	aprint(LINE_RANGE, COL_MID+17, hi);	aprint(LINE_RANGE, COL_MID+23, v->selected_pages);	cprint(LINE_RANGE, COL_MID+28,		((ulong)&_start == LOW_TEST_ADR)?"          ":" Relocated");#ifdef TEST_TIMES	{		ulong l, h, t;		asm __volatile__ (			"rdtsc\n\t"			"subl %%ebx,%%eax\n\t"			"sbbl %%ecx,%%edx\n\t"			:"=a" (l), "=d" (h)			:"b" (v->snapl), "c" (v->snaph)		);		cprint(20, 5, ":  :");		t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000;		t += (l / v->clks_msec) / 1000;		i = t % 60;		dprint(20, 10, i%10, 1, 0);		dprint(20, 9, i/10, 1, 0);		t /= 60;		i = t % 60;		dprint(20, +7, i % 10, 1, 0);		dprint(20, +6, i / 10, 1, 0);		t /= 60;		dprint(20, 0, t, 5, 0);		asm __volatile__ ("rdtsc":"=a" (v->snapl),"=d" (v->snaph));	}#endif	/* Now setup the test parameters based on the current test number */	/* Figure out the next test to run */	if (v->testsel >= 0) {		v->test = v->testsel;	}	dprint(LINE_TST, COL_MID+6, v->test, 2, 1);	cprint(LINE_TST, COL_MID+9, tseq[v->test].msg);	set_cache(tseq[v->test].cache);	/* Compute the number of SPINSZ memory segments */	chunks = 0;	for(i = 0; i < segs; i++) {		unsigned long len;		len = v->map[i].end - v->map[i].start;		chunks += (len + SPINSZ -1)/SPINSZ;	}	test_ticks = find_ticks_for_test(chunks, v->test);	nticks = 0;	v->tptr = 0;	cprint(1, COL_MID+8, "                                         ");	switch(tseq[v->test].pat) {	/* Now do the testing according to the selected pattern */	case 0:	/* Moving inversions, all ones and zeros */	case 1: /* Moving inversions, 8 bit wide walking ones and zeros. */	case 4:			if (tseq[v->test].pat == 1)			p0 = 0x80808080;		else			p0 = 0;		for ( ; ; ) {			movinv1(tseq[v->test].iter,p0,~p0);			BAILOUT;			/* Switch patterns */			movinv1(tseq[v->test].iter,~p0,p0);			BAILOUT			if ( !((unsigned char)(p0 >>= 1) & 0x7F) )				break;		}		break;	case 2: /* Moving inversions, 32 bit shifting pattern, very long */		for (i=0, p1=1; p1; p1=p1<<1, i++) {			movinv32(tseq[v->test].iter,p1, 1, 0x80000000, 0, i);			BAILOUT			movinv32(tseq[v->test].iter,~p1, 0xfffffffe, 0x7fffffff, 1, i);			BAILOUT		}		break;	case 3: /* Modulo X check, all ones and zeros */		p1=0;		for (i=0; i<MOD_SZ; i++) {			p2 = ~p1;			modtst(i, tseq[v->test].iter, p1, p2);			BAILOUT			/* Switch patterns */			p2 = p1;			p1 = ~p2;			modtst(i, tseq[v->test].iter, p1,p2);			BAILOUT		}		break;	case 5: /* Address test, walking ones */		addr_tst1();		BAILOUT;		break;	case 6: /* Address test, own address */		addr_tst2();		BAILOUT;		break;	case 7: /* Block move test */		block_move(tseq[v->test].iter);		BAILOUT;		break;	case 8: /* Bit fade test */		if (window == 0 ) {			bit_fade();		}		BAILOUT;		break;			case 9: /* Random Data Sequence */		for (i=0; i < tseq[v->test].iter; i++) {			movinvr();			BAILOUT;		}		break;	case 10: /* Random Data */		for (i=0; i < tseq[v->test].iter; i++) {			p1 = rand();			p2 = ~p1;			movinv1(2,p1,p2);			BAILOUT;		}		break;	} skip_window:	if (bail) {		goto bail_test;	}	/* Rever to the default mapping and enable the cache */	paging_off();	set_cache(1);	window++;	if (window >= sizeof(windows)/sizeof(windows[0])) {		window = 0;	}	/* We finished the test so clear the pattern */	cprint(LINE_PAT, COL_PAT, "            ");	if (window != 0) {		/* Relocate and run the high copy if:		 * - The window overwrites us.		 *   The lower limit is less than START_ADR		 * - There is more than 1 meg of memory		 */		if (windows[window].start <			(LOW_TEST_ADR + (_end - _start)) >> 12) {			if (v->pmap[v->msegs-1].end >				(((HIGH_TEST_ADR + (_end - _start)) >> 12) +1)) {				/* We need the high copy and we have enough				 * memory so use it.				 */				run_at(HIGH_TEST_ADR);			} else {				/* We can't use this window so skip it */				goto skip_window;			}		} else {			/* We don't need the high copy for this test */			run_at(LOW_TEST_ADR);		}	}	else {		/* We have run this test in all of the windows		 * advance to the next test.		 */	skip_test:		v->test++;	bail_test:		/* Revert to the default mapping		 * and enable the cache.		 */		paging_off();		set_cache(1);		check_input();		window = 0;		cprint(LINE_PAT, COL_PAT-3, "   ");		/* If this was the last test then we finished a pass */		if (v->test >= 9 || v->testsel >= 0) {			v->pass++;			dprint(LINE_INFO, COL_PASS, v->pass, 5, 0);			v->test = 0;			v->total_ticks = 0;			v->pptr = 0;			cprint(0, COL_MID+8,				"                                         ");		}		/* We always start a pass with the low copy */		run_at(LOW_TEST_ADR);	}}void restart(){	int i;	volatile char *pp;	/* clear variables */	firsttime = 0;	v->test = 0;	v->pass = 0;	v->msg_line = 0;	v->ecount = 0;	v->ecc_ecount = 0;	/* Clear the screen */	for(i=0, pp=(char *)(SCREEN_ADR+0); i<80*24; i++, pp+=2) {		*pp = ' ';	}	run_at(LOW_TEST_ADR);}/* Compute the total number of ticks per pass */void find_ticks(void){	int i, j, chunks;	v->pptr = 0;	/* Compute the number of SPINSZ memory segments in one pass */	chunks = 0;	for(j = 0; j < sizeof(windows)/sizeof(windows[0]); j++) {		compute_segments(j);		for(i = 0; i < segs; i++) {			unsigned long len;			len = v->map[i].end - v->map[i].start;			chunks += (len + SPINSZ -1)/SPINSZ;		}	}	compute_segments(window);	window = 0;	for (v->pass_ticks=0, i=0; ((i<DEFTESTS) && (DEFTESTS != NULL)); i++) {		/* Test to see if this test is selected for execution */		if (v->testsel >= 0) {			if (i != v->testsel) {				continue;			}		}		v->pass_ticks += find_ticks_for_test(chunks, i);	}}static int find_ticks_for_test(unsigned long chunks, int test){	int ticks;	ticks = chunks * tseq[test].ticks;	if (tseq[test].pat == 5) {		/* Address test, walking ones */		ticks = 4;	}	return ticks;}static void compute_segments(int win){	unsigned long wstart, wend;	int i;	/* Compute the window I am testing memory in */	wstart = windows[win].start;	wend = windows[win].end;	segs = 0;	/* Now reduce my window to the area of memory I want to test */	if (wstart < v->plim_lower) {		wstart = v->plim_lower;	}	if (wend > v->plim_upper) {		wend = v->plim_upper;	}	if (wstart >= wend) {		return;	}	/* List the segments being tested */	for (i=0; i< v->msegs; i++) {		unsigned long start, end;		start = v->pmap[i].start;		end = v->pmap[i].end;		if (start <= wstart) {			start = wstart;		}		if (end >= wend) {			end = wend;		}#if 0		cprint(LINE_SCROLL+(2*i), 0, " (");		hprint(LINE_SCROLL+(2*i), 2, start);		cprint(LINE_SCROLL+(2*i), 10, ", ");		hprint(LINE_SCROLL+(2*i), 12, end);		cprint(LINE_SCROLL+(2*i), 20, ") ");		cprint(LINE_SCROLL+(2*i), 22, "r(");		hprint(LINE_SCROLL+(2*i), 24, wstart);		cprint(LINE_SCROLL+(2*i), 32, ", ");		hprint(LINE_SCROLL+(2*i), 34, wend);		cprint(LINE_SCROLL+(2*i), 42, ") ");		cprint(LINE_SCROLL+(2*i), 44, "p(");		hprint(LINE_SCROLL+(2*i), 46, v->plim_lower);		cprint(LINE_SCROLL+(2*i), 54, ", ");		hprint(LINE_SCROLL+(2*i), 56, v->plim_upper);		cprint(LINE_SCROLL+(2*i), 64, ") ");		cprint(LINE_SCROLL+(2*i+1),  0, "w(");		hprint(LINE_SCROLL+(2*i+1),  2, windows[win].start);		cprint(LINE_SCROLL+(2*i+1), 10, ", ");		hprint(LINE_SCROLL+(2*i+1), 12, windows[win].end);		cprint(LINE_SCROLL+(2*i+1), 20, ") ");		cprint(LINE_SCROLL+(2*i+1), 22, "m(");		hprint(LINE_SCROLL+(2*i+1), 24, v->pmap[i].start);		cprint(LINE_SCROLL+(2*i+1), 32, ", ");		hprint(LINE_SCROLL+(2*i+1), 34, v->pmap[i].end);		cprint(LINE_SCROLL+(2*i+1), 42, ") ");		cprint(LINE_SCROLL+(2*i+1), 44, "i=");		hprint(LINE_SCROLL+(2*i+1), 46, i);		cprint(LINE_SCROLL+(2*i+2), 0,			"                                        "			"                                        ");		cprint(LINE_SCROLL+(2*i+3), 0,			"                                        "			"                                        ");#endif		if ((start < end) && (start < wend) && (end > wstart)) {			v->map[segs].pbase_addr = start;			v->map[segs].start = mapping(start);			v->map[segs].end = emapping(end);#if 0			cprint(LINE_SCROLL+(2*i+1), 54, " segs: ");			hprint(LINE_SCROLL+(2*i+1), 61, segs);#endif			segs++;		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -