From 87e047292b0d563504fe4162596b11be132cbf1a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 18 Sep 2009 04:37:36 +0100 Subject: [import] Import version 1.40 http://www.memtest.org/download/1.40/memtest86+-1.40.tar.gz --- Makefile | 5 +- README | 1663 ++++++++++++++++++++++++++------------------------ README.build-process | 78 +-- bootsect.S | 750 +++++++++++------------ changelog | 7 - config.c | 264 +++----- controller.c | 19 +- head.S | 14 + init.c | 12 +- lib.c | 16 +- main.c | 109 ++-- makeiso.sh | 39 ++ memsize.c | 72 +-- memtest.bin.lds | 30 +- memtest.lds | 22 +- memtest_shared.lds | 104 ++-- mt86+_loader.asm | 4 +- mt86+_loader.bin | Bin 784 -> 784 bytes precomp.bin | Bin 99516 -> 95352 bytes random.c | 31 + setup.S | 230 +++---- stdin.h | 52 -- stdint.h | 52 ++ test.c | 231 ++++++- test.h | 76 +-- 25 files changed, 1990 insertions(+), 1890 deletions(-) delete mode 100644 changelog mode change 100755 => 100644 init.c create mode 100755 makeiso.sh create mode 100644 random.c delete mode 100644 stdin.h create mode 100644 stdint.h diff --git a/Makefile b/Makefile index f7dcf1d..f8498ec 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ CCFLAGS=-Wall -m32 -march=i486 -Os -fomit-frame-pointer -fno-builtin -ffreestand AS=as -32 -OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o config.o linuxbios.o memsize.o pci.o controller.o extra.o +OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o config.o linuxbios.o memsize.o pci.o controller.o extra.o random.o all: memtest.bin memtest @@ -44,6 +44,9 @@ lib.o: lib.c test.h defs.h io.h screen_buffer.h serial.h config.h screen_buffer.o: screen_buffer.c screen_buffer.h test.h config.h $(CC) -c $(CCFLAGS) -fPIC screen_buffer.c +random.o: random.c + $(CC) -c $(CCFLAGS) -fPIC random.c + patn.o: patn.c $(CC) -c $(CCFLAGS) -fPIC patn.c diff --git a/README b/README index 598a3e2..dccbfd0 100644 --- a/README +++ b/README @@ -1,813 +1,850 @@ - =================== - = MemTest-86 v3.0 = - =================== - -Table of Contents -================= - 1) Introduction - 2) Licensing - 3) Installation - 4) Serial Port Console - 5) Online Commands - 6) Memory Sizing - 7) Error Display - 8) Trouble-shooting Memory Errors - 9) Execution Time - 10) Memory Testing Philosophy - 11) Memtest86 Test Algorithms - 12) Individual Test Descriptions - 13) Problem Reporting - Contact Information - 14) Known Problems - 15) Planned Features List - 16) Change Log - 17) Acknowledgments - - -1) Introduction -=============== -Memtest86 is thorough, stand alone memory test for Intel i386 architecture -systems. BIOS based memory tests are only a quick check and often miss -failures that are detected by Memtest86. - -For updates go to the Memtest86 web page: - - http://www.memtest86.com - -To report problems or provide feedback send email to: - - cbrady@cray.com - - -2) Licensing -============ -Memtest86 is released under the terms of the Gnu Public License (GPL). Other -than the provisions of the GPL there are no restrictions for use, private or -commercial. See: http://www.gnu.org/licenses/gpl.html for details. - - -3) Installation (Linux Only) -============================ -Memtest86 is a stand alone program and can be loaded from either a disk -partition or from a floppy disk. - -To build Memtest86: - 1) Review the Makefile and adjust options as needed. - 2) Type "make" - -This creates a file named "memtest.bin" which is a bootable image. This -image file may be copied to a floppy disk or lilo may be used to boot this -image from a hard disk partition. - -To create a Memtest86 bootdisk - 1) Insert a blank write enabled floppy disk. - 2) As root, Type "make install" - -To boot from a disk partition via lilo - 1) Copy the image file to a permanent location (ie. /memtest). - 2) Add an entry in the lilo config file (usually /etc/lilo.conf) to boot - memtest86. Only the image and label fields need to be specified. - The following is a sample lilo entry for booting memtest86: - - image = /memtest - label = memtest - - 3) As root, type "lilo" - - At the lilo prompt enter memtest to boot memtest86. - -If you encounter build problems a binary image has been included (precomp.bin). -To create a boot-disk with this pre-built image do the following: - 1) Insert a blank write enabled floppy disk. - 2) Type "make install-bin" - -If you have problems with memory sizing an option is available to get -the memory size from the BIOS. To enable this option uncomment the -define for BIOS_MEMSZ in config.h and then rebuild and install the test. - - -4) Serial Console -================= -Memtest86 can be used on PC's equipped with a serial port for the console. -By default serial port console support is not enabled since it slows -down testing. To enable change the SERIAL_CONSOLE_DEFAULT define in -config.h from a zero to a one. The serial console baud rate may also -be set in config.h with the SERIAL_BAUD_RATE define. The other serial -port settings are no parity, 8 data bits, 1 stop bit. All of the features -used by memtest86 are accessible via the serial console. However, the -screen sometimes is garbled when the online commands are used. - - -5) Online Commands -================== -Memtest86 has a limited number of online commands. Online commands -provide control over caching, test selection, address range and error -scrolling. A help bar is displayed at the bottom of the screen listing -the available on-line commands. - - Command Description - - ESC Exits the test and does a warm restart via the BIOS. - - c Enters test configuration menu - Menu options are: - 1) Cache mode - 2) Test selection - 3) Address Range - 4) Memory Sizing - 5) Error Summary - 6) Error Report Mode - 7) ECC Mode - 8) Restart Test - 9) Reprint Screen - - SP Set scroll lock (Stops scrolling of error messages) - Note: Testing is stalled when the scroll lock is - set and the scroll region is full. - - CR Clear scroll lock (Enables error message scrolling) - - -6) Memory Sizing -================ -The BIOS in modern PC's will often reserve several sections of memory for -it's use and also to communicate information to the operating system (ie. -ACPI tables). It is just as important to test these reserved memory blocks -as it is for the remainder of memory. For proper operation all of memory -needs to function properly regardless of what the eventual use is. For -this reason Memtest86 has been designed to test as much memory as is -possible. - -However, safely and reliably detecting all of the available memory has been -problematic. Versions of Memtest86 prior to v2.9 would probe to find where -memory is. This works for the vast majority of motherboards but is not 100% -reliable. Sometimes the memory size is incorrect and worse probing the wrong -places can in some cases cause the test to hang or crash. - -Starting in version 2.9 alternative methods are available for determining the -memory size. By default the test attempts to get the memory size from the -BIOS using the "e820" method. With "e820" the BIOS provides a table of memory -segments and identifies what they will be used for. By default Memtest86 -will test all of the ram marked as available and also the area reserved for -the ACPI tables. This is safe since the test does not use the ACPI tables -and the "e820" specifications state that this memory may be reused after the -tables have been copied. Although this is a safe default some memory will -not be tested. - -Two additional options are available through online configuration options. -The first option (BIOS-All) also uses the "e820" method to obtain a memory -map. However, when this option is selected all of the reserved memory -segments are tested, regardless of what their intended use is. The only -exception is memory segments that begin above 3gb. Testing has shown that -these segments are typically not safe to test. The BIOS-All option is more -thorough but could be unstable with some motherboards. - -The second option for memory sizing is the traditional "Probe" method. -This is a very thorough but not entirely safe method. In the majority of -cases the BIOS-All and Probe methods will return the same memory map. - -For older BIOS's that do not support the "e820" method there are two -additional methods (e801 and e88) for getting the memory size from the -BIOS. These methods only provide the amount of extended memory that is -available, not a memory table. When the e801 and e88 methods are used -the BIOS-All option will not be available. - -The MemMap field on the display shows what memory size method is in use. -Also the RsvdMem field shows how much memory is reserved and is not being -tested. - - -7) Error Information -====================== -Memtest has two options for reporting errors. The default is to report -individual errors. In BadRAM Patterns mode patterns are created for -use with the Linux BadRAM feature. This slick feature allows Linux to -avoid bad memory pages. Details about the BadRAM feature can be found at: - - http://home.zonnet.nl/vanrein/badram - -For individual errors the following information is displayed when a memory -error is detected. An error message is only displayed for errors with a -different address or failing bit pattern. All displayed values are in -hexadecimal. - - Tst: Test number - Failing Address : Failing memory address - Good: Expected data pattern - Bad: Failing data pattern - Err-Bits: Exclusive or of good and bad data (this shows the - position of the failing bit(s)) - Count: Number of consecutive errors with the same address - and failing bits - -In BadRAM Patterns mode, Lines are printed in a form badram=F1,M1,F2,M2. -In each F/M pair, the F represents a fault address, and the corresponding M -is a bitmask for that address. These patterns state that faults have -occurred in addresses that equal F on all "1" bits in M. Such a pattern may -capture more errors that actually exist, but at least all the errors are -captured. These patterns have been designed to capture regular patterns of -errors caused by the hardware structure in a terse syntax. - -The BadRAM patterns are `grown' increment-ally rather than `designed' from an -overview of all errors. The number of pairs is constrained to five for a -number of practical reasons. As a result, handcrafting patterns from the -output in address printing mode may, in exceptional cases, yield better -results. - - -8) Trouble-shooting Memory Errors -================================ -Please be aware that not all errors reported by Memtest86 are due to -bad memory. The test implicitly tests the CPU, L1 and L2 caches as well as -the motherboard. It is impossible for the test to determine what causes -the failure to occur. Most failures will be due to a problem with memory. -When it is not, the only option is to replace parts until the failure is -corrected. - -Once a memory error has been detected, determining the failing SIMM/DIMM -module is not a clear cut procedure. With the large number of motherboard -vendors and possible combinations of simm slots it would be difficult if -not impossible to assemble complete information about how a particular -error would map to a failing memory module. However, there are steps -that may be taken to determine the failing module. Here are three -techniques that you may wish to use: - -1) Removing modules -This is simplest method for isolating a failing modules, but may only be -employed when one or more modules can be removed from the system. By -selectively removing modules from the system and then running the test -you will be able to find the bad module(s). Be sure to note exactly which -modules are in the system when the test passes and when the test fails. - -2) Rotating modules -When none of the modules can be removed then you may wish to rotate modules -to find the failing one. This technique can only be used if there are -three or more modules in the system. Change the location of two modules -at a time. For example put the module from slot 1 into slot 2 and put -the module from slot 2 in slot 1. Run the test and if either the failing -bit or address changes then you know that the failing module is one of the -ones just moved. By using several combinations of module movement you -should be able to determine which module is failing. - -3) Replacing modules -If you are unable to use either of the previous techniques then you are -left to selective replacement of modules to find the failure. - -4) Avoiding allocation -The printing mode for BadRAM patterns is intended to construct boot time -parameters for a Linux kernel that is compiled with BadRAM support. This -work-around makes it possible for Linux to reliably run on your average damaged -RAM (or clearly panic if it cannot). For more information on BadRAM support -for Linux, sail to - - http://home.zonnet.nl/vanrein/badram - -Sometimes memory errors show up due to component incompatibility. A memory -DIMM/SIMM may work fine in one system and not in another. This is not -uncommon and is a source of confusion. The components are not necessarily -bad but certain combinations may need to be avoided. - -I am often asked about the reliability of errors reported by Mestest86. -In the vast majority of cases errors reported by the test are valid. -There are some systems that cause Memtest86 to be confused about the size of -memory and it will try to test non-existent memory. This will cause a large -number of consecutive addresses to be reported as bad and generally there -will be many bits in error. If you have a relatively small number of -failing addresses and only one or two bits in error you can be certain -that the errors are valid. Also intermittent errors are always valid. - -All valid memory errors should be corrected. It is possible that a -particular error will never show up in normal operation. However, operating -with marginal memory is risky and can result in data loss and even -disk corruption. You can be sure that Murphy will get you if you know -about a memory error and ignore it. - -Memtest86 can not diagnose many types of PC failures. For example a -faulty CPU that causes Windows to crash will most likely just cause -Memtest86 to crash in the same way. - - -9) Execution Time -================== -The time required for a complete pass of Memtest86 will vary greatly -depending on CPU speed, memory speed and memory size. Here are the -execution times from a Cleron-366 with 64MB of SDRAM: - - Test 0: 0:05 - Test 1: 0:18 - Test 2: 1:02 - Test 3: 1:38 - Test 4: 8:05 - Test 5: 1:40 - Test 6: 4:24 - Test 7: 6:04 - - Total Time for Default tests: 23:16 - - Test 8: 12:30 - Test 9: 49:30 - Test 10: 30:34 - Test 11: 3:29:40 - - Total Time for All tests: 5:25:30 - - -10) Memory Testing Philosophy -============================ -There are many good approaches for testing memory. However, many tests -simply throw some patterns at memory without much thought or knowledge -of the memory architecture or how errors can best be detected. This -works fine for hard memory failures but does little to find intermittent -errors. The BIOS based memory tests are useless for finding intermittent -memory errors. - -Memory chips consist of a large array of tightly packed memory cells, -one for each bit of data. The vast majority of the intermittent failures -are a result of interaction between these memory cells. Often writing a -memory cell can cause one of the adjacent cells to be written with the -same data. An effective memory test should attempt to test for this -condition. Therefore, an ideal strategy for testing memory would be -the following: - - 1) write a cell with a zero - 2) write all of the adjacent cells with a one, one or more times - 3) check that the first cell still has a zero - -It should be obvious that this strategy requires an exact knowledge -of how the memory cells are laid out on the chip. In addition there is a -never ending number of possible chip layouts for different chip types -and manufacturers making this strategy impractical. However, there -are testing algorithms that can approximate this ideal strategy. - - -11) Memtest86 Test Algorithms -============================ -Memtest86 uses two algorithms that provide a reasonable approximation -of the ideal test strategy above. The first of these strategies is called -moving inversions. The moving inversion test works as follows: - - 1) Fill memory with a pattern - 2) Starting at the lowest address - 2a check that the pattern has not changed - 2b write the patterns complement - 2c increment the address - repeat 2a - 2c - 3) Starting at the highest address - 3a check that the pattern has not changed - 3b write the patterns complement - 3c decrement the address - repeat 3a - 3c - -This this algorithm is a good approximation of an ideal memory test but -there are some limitations. Most high density chips today store data -4 to 16 bits wide. With chips that are more than one bit wide it -is impossible to selectively read or write just one bit. This means -that we cannot guarantee that all adjacent cells have been tested -for interaction. In this case the best we can do is to use some -patterns to insure that all adjacent cells have at least been written -with all possible one and zero combinations. - -It can also be seen that caching, buffering and out of order execution -will interfere with the moving inversions algorithm and make less effective. -It is possible to turn off cache but the memory buffering in new high -performance chips can not be disabled. To address this limitation a new -algorithm I call Modulo-X was created. This algorithm is not affected by -cache or buffering. The algorithm works as follows: - 1) For starting offsets of 0 - 20 do - 1a write every 20th location with a pattern - 1b write all other locations with the patterns complement - repeat 1b one or more times - 1c check every 20th location for the pattern - -This algorithm accomplishes nearly the same level of adjacency testing -as moving inversions but is not affected by caching or buffering. Since -separate write passes (1a, 1b) and the read pass (1c) are done for all of -memory we can be assured that all of the buffers and cache have been -flushed between passes. The selection of 20 as the stride size was somewhat -arbitrary. Larger strides may be more effective but would take longer to -execute. The choice of 20 seemed to be a reasonable compromise between -speed and thoroughness. - - -12) Individual Test Descriptions -=============================== -Memtest86 executes a series of numbered test sections to check for -errors. These test sections consist of a combination of test -algorithm, data pattern and caching. The execution order for these tests -were arranged so that errors will be detected as rapidly as possible. -Tests 8, 9, 10 and 11 are very long running extended tests and are only -executed when extended testing is selected. The extended tests have a -low probability of finding errors that were missed by the default tests. -A description of each of the test sections follows: - -Test 0 [Address test, walking ones, no cache] - Tests all address bits in all memory banks by using a walking ones - address pattern. Errors from this test are not used to calculate - BadRAM patterns. - -Test 1 [Moving Inv, ones&zeros, cached] - This test uses the moving inversions algorithm with patterns of only - ones and zeros. Cache is enabled even though it interferes to some - degree with the test algorithm. With cache enabled this test does not - take long and should quickly find all "hard" errors and some more - subtle errors. This section is only a quick check. - -Test 2 [Address test, own address, no cache] - Each address is written with its own address and then is checked - for consistency. In theory previous tests should have caught any - memory addressing problems. This test should catch any addressing - errors that somehow were not previously detected. - -Test 3 [Moving inv, 8 bit pat, cached] - This is the same as test zero but uses a 8 bit wide pattern of - "walking" ones and zeros. This test will better detect subtle errors - in "wide" memory chips. A total of 20 data patterns are used. - -Test 4 [Moving inv, 32 bit pat, cached] - This is a variation of the moving inversions algorithm that - shifts the data pattern left one bit for each successive address. - The starting bit position is shifted left for each pass. To use - all possible data patterns 32 passes are required. This test is - very effective at detecting data sensitive errors in "wide" memory - chips. - -Test 5 [Block move, 64 moves, cached] - This test stresses memory by using block move (movsl) instructions - and is based on Robert Redelmeier's burnBX test. Memory is initialized - with shifting patterns that are inverted every 8 bytes. Then 4MB blocks - of memory are moved around using the movsl instruction. After the moves - are completed the data patterns are checked. Because the data is checked - only after the memory moves are completed it is not possible to know - where the error occurred. The addresses reported are only for where the - bad pattern was found. Since the moves are constrained to a 8MB segment - of memory the failing address will always be lest than 8MB away from the - reported address. Errors from this test are not used to calculate - BadRAM patterns. - -Test 6 [Modulo 20, ones&zeros, cached] - Using the Modulo-X algorithm should uncover errors that are not - detected by moving inversions due to cache and buffering interference - with the the algorithm. As with test one only ones and zeros are - used for data patterns. - -Test 7 [Moving inv, ones&zeros, no cache] - This is the same as test one but without cache. With cache off - there will be much less interference with the test algorithm. - However, the execution time is much, much longer. This test may - find very subtle errors missed by tests one and two. - -Test 8 [Block move, 512 moves, cached] - This is the same as test #5 except that we do a lot more memory moves - before checking memory. Errors from this test are not used to calculate - BadRAM patterns. - -Test 9 [Moving inv, 8 bit pat, no cache] - This is the first extended test. By using an 8 bit pattern with - cache off this test should be effective in detecting all types of - errors. However, it takes a very long time to execute and there is - a low probability that it will detect errors not found by the previous - tests. - -Test 10 [Modulo 20, 8 bit, cached] - This is the first test to use the modulo 20 algorithm with a data - pattern other than ones and zeros. This combination of algorithm and - data pattern should be quite effective. However, it's very long - execution time relegates it to the extended test section. - -Test 11 [Moving inv, 32 bit pat, no cache] - This test should be the most effective in finding errors that are - data pattern sensitive. However, without cache it's execution time - is excessively long. - - -13) Problem Reporting - Contact Information -=========================================== -Due to the growing popularity of Memtest86 I am being inundated by, -questions, feedback, problem reports and requests for enhancements. -Memtest86 is a side project and often my day job interferes with Memtest86 -support. To help me keep up with this project, please use the following -guidelines. - -Problems/Bugs: -Before submitting a problem report please check the Known Problems section -to see if this problem has already been reported. Be sure to include the -version number and also any details that may be relevant. - -Memtest86 sometimes just dies with no hints as to what went wrong. -Without any details it is nearly impossible to fix these failures. Fixing -these problems will require debugging assistance on your part. There is -no point in reporting these failures unless you have a Linux system and -would be willing to assist me in finding the failure. - -Enhancements: -If you would like to request an enhancement please see if is already on -the Planned Features List before sending your request. All requests will -be considered, but not all can be implemented. If you are be interested in -contributing code please contact me so that the integration can be -co-ordinated. - -Feedback: -I have received a lot of feedback about the effectiveness of various -tests. I am still interested in hearing about failures that only a single -test was able to detect. Of course, gratitude, praise and cash are always -accepted. - -Chris Brady, Email: cbrady@cray.com - - -14) Known Problems -================== -Sometimes when booting from a floppy disk the following messages scroll up -on the screen: - X:8000 - AX:0212 - BX:8600 - CX:0201 - DX:0000 -This the BIOS reporting floppy disk read errors. Either re-write or toss -the floppy disk. - -Memtest86 has no support for multiple CPUs. Memtest86 should run -without problems, but it will only use one CPU. - -Memtest86 can not diagnose many types of PC failures. For example a -faulty CPU that causes Windows to crash will most likely just cause -Memtest86 to crash in the same way. - -There have been numerous reports of errors in only tests 5 and 8 on Athlon -systems. Often the memory works in a different system or the vendor insists -that it is good. In these cases the memory is not necessarily bad but is -not able to operate reliably at Athlon speeds. Sometimes more conservative -memory timings on the motherboard will correct these errors. In other -cases the only option is to replace the memory with better quality, higher -speed memory. Don't buy cheap memory and expect it to work with an Athlon! - -Memtest86 supports all types of memory. If fact the test has absolutely -no knowledge of the memory type nor does it need to. This not a problem -or bug but is listed here due to the many questions I get about this issue. - -Changes in the compiler and loader have caused problems with -Memtest86 resulting in both build failures and errors in execution. A -binary image (precomp.bin) of the test is included and may be used if -problems are encountered. - -15) Planned Features List -========================= -This is a list of enhancements planned for future releases of Memtest86. -There is no timetable for when these will be implemented, if ever. - - - Option to allow printing of error information on an attached printer. - - Option to write error information to a floppy disk. - - Supply Memtest in RPM format. - - Read and display RAM SPD information. - - -16) Change Log -============== -Enhancements in v3.0 (22/May/2002) Provided by Eric Biederman - - Testing of more than 2gb of memory is at last fixed (tested with 6Gb) - - The infrastructure is to poll ecc error reporting chipset regisets, - and the support has been done for some chipsets. - - Uses dynamic relocation information records to make itself PIC - instead of requiring 2 copies of memtest86 in the binary. - - The serial console code does not do redundant writes to the serial port - Very little slow down at 9600 baud. - - You can press ^l or just l to get a screen refresh, when you are - connecting and unconnecting a serial cable. - - Netbooting is working again - - LinuxBIOS support (To get the memory size) - - Many bugfixes and code cleanup. - -Enhancements in v2.9 (29/Feb/2002) - - The memory sizing code has been completely rewritten. By default - Memtest86 gets a memory map from the BIOS that is now used to find - available memory. A new online configuration option provides three - choices for how memory will be sized, including the old "probe" method. - The default mode generally will not test all of memory, but should be more - stable. See the "Memory Sizing" section for details. - - Testing of more than 2gb of memory should now work. A number of bugs - were found and corrected that prevented testing above 2gb. Testing - with more than 2gb has been limited and there could be problems with a - full 4gb of memory. - - Memory is divided into segments for testing. This allow for frequent - progress updates and responsiveness to interactive commands. The - memory segment size has been increased from 8 to 32mb. This should - improve testing effectivness but progress reports will be less frequent. - - Minor bug fixes. - -Enhancements in v2.8 (18/Oct/2001) - Eric Biederman reworked the build process making it far simpler and also - to produce a network bootable ELF image. - - Re-wrote the memory and cache speed detection code. Previously the - reported numbers were inaccurate for intel CPU's and completely wrong - for Athlon/Duron CPU's. - - By default the serial console is disabled since this was slowing - down testing. - - Added CPU detection for Pentium 4. - - -Enhancements in v2.7 (12/Jul/2001) - Expanded workaround for errors caused by BIOS USB keyboard support to - include test #5. - - Re-worked L1 / L2 cache detection code to provide clearer reporting. - - Fixed an obvious bug in the computation of cache and memory speeds. - - Changed on-line menu to stay in the menu between option selections. - - Fixed bugs in the test restart and redraw code. - - Adjusted code size to fix compilation problems with RedHat 7.1. - - Misc updates to the documentation. - -Enhancements in v2.6 (25/May/2001) - Added workaround for errors caused by BIOS USB keyboard support. - - Fixed problems with reporting of 1 GHZ + processor speeds. - - Fixed Duron cache detection. - - Added screen buffer so that menus will work correctly from a serial - console. - - The Memtest86 image is now built in ELF format. - -Enhancements in v2.5 (14/Dec/00) - Enhanced CPU and cache detection to correctly identify Duron CPU - and K6-III 1MB cache. - - Added code to report cache-able memory size. - - Added limited support for parity memory. - - Support was added to allow use of on-line commands from a serial - port. - - Dropped option for changing refresh rates. This was not useful - and did not work on newer motherboards. - - Improved fatal exception reporting to include a register and stack - dump. - - The pass number is now displayed in the error report. - - Fixed a bug that crashed the test when selecting one of the extended - tests. - -Enhancements in v2.4 - The error report format was reworked for better clarity and now - includes a decimal address in megabytes. - - A new memory move test was added (from Robert Redelmeier's CPU-Burn) - - The test sequence and iterations were modified. - - Fixed scrolling problems with the BadRAM patterns. - - -Enhancements in v2.3 - A progress meter was added to replace the spinner and dots. - - Measurement and reporting of memory and cache performance - was added. - - Support for creating BadRAM patterns was added. - - All of the test routines were rewritten in assembler to - improve both test performance and speed. - - The screen layout was reworked to hopefully be more readable. - - An error summary option was added to the online commands. - - -Enhancements in v2.2 - Added two new address tests - - Added an on-line command for setting test address range - - Optimized test code for faster execution (-O3, -funroll-loops and - -fomit-frame-pointer) - - Added and elapsed time counter. - - Adjusted menu options for better consistency - - -Enhancements in v2.1 - Fixed a bug in the CPU detection that caused the test to - hang or crash with some 486 and Cryrix CPU's - - Added CPU detection for Cyrix CPU's - - Extended and improved CPU detection for Intel and AMD CPU's - - Added a compile time option (BIOS_MEMSZ) for obtaining the last - memory address from the BIOS. This should fix problems with memory - sizing on certain motherboards. This option is not enabled by default. - It may be enabled be default in a future release. - -Enhancements in v2.0 - Added new Modulo-20 test algorithm. - - Added a 32 bit shifting pattern to the moving inversions algorithm. - - Created test sections to specify algorithm, pattern and caching. - - Improved test progress indicators. - - Created popup menus for configuration. - - Added menu for test selection. - - Added CPU and cache identification. - - Added a "bail out" feature to quit the current test when it does not - fit the test selection parameters. - - Re-arranged the screen layout and colors. - - Created local include files for I/O and serial interface definitions - rather than using the sometimes incompatible system include files. - - Broke up the "C" source code into four separate source modules. - -Enhancements in v1.5 - Some additional changes were made to fix obscure memory sizing - problems. - - The 4 bit wide data pattern was increased to 8 bits since 8 bit - wide memory chips are becoming more common. - - A new test algorithm was added to improve detection of data - pattern sensitive errors. - - -Enhancements in v1.4 - Changes to the memory sizing code to avoid problems with some - motherboards where memtest would find more memory than actually - exists. - - Added support for a console serial port. (thanks to Doug Sisk) - - On-line commands are now available for configuring Memtest86 on - the fly (see On-line Commands). - - -Enhancements in v1.3 - Scrolling of memory errors is now provided. Previously, only one screen - of error information was displayed. - - Memtest86 can now be booted from any disk via lilo. - - Testing of up to 4gb of memory has been fixed is now enabled by default. - This capability was clearly broken in v1.2a and should work correctly - now but has not been fully tested (4gb PC's are a bit rare). - - The maximum memory size supported by the motherboard is now being - calculated correctly. In previous versions there were cases where not - all of memory would be tested and the maximum memory size supported - was incorrect. - - For some types of failures the good and bad values were reported to be - same with an Xor value of 0. This has been fixed by retaining the data - read from memory and not re-reading the bad data in the error reporting - routine. - - APM (advanced power management) is now disabled by Memtest86. This - keeps the screen from blanking while the test is running. - - Problems with enabling & disabling cache on some motherboards have been - corrected. - -17) Acknowledgments -=================== -The initial versions of the source files bootsect.S, setup.S, head.S and -build.c are from the Linux 1.2.1 kernel and have been heavily modified. - -Doug Sisk provided code to support a console connected via a serial port. - -Code to create BadRAM patterns was provided by Rick van Rein. - -Tests 5 and 8 are based on Robert Redelmeier's burnBX test. - -Screen buffer code was provided by Jani Averbach. - -Eric Biederman provided all of the feature content for version 3.0 -plus many bugfixes and significant code cleanup. + ==================== + = MemTest-86 v3.2 = + = Nov 11, 2004 = + = Chris Brady = + ==================== + +Table of Contents +================= + 1) Introduction + 2) Licensing + 3) Installation + 4) Serial Port Console + 5) Online Commands + 6) Memory Sizing + 7) Error Display + 8) Trouble-shooting Memory Errors + 9) Execution Time + 10) Memory Testing Philosophy + 11) Memtest86 Test Algorithms + 12) Individual Test Descriptions + 13) Problem Reporting - Contact Information + 14) Known Problems + 15) Planned Features List + 16) Change Log + 17) Donations + 18) Acknowledgments + + +1) Introduction +=============== +Memtest86 is thorough, stand alone memory test for Intel/AMD x86 architecture +systems. BIOS based memory tests are only a quick check and often miss +failures that are detected by Memtest86. + +For updates go to the Memtest86 web page: + + http://www.memtest86.com + + +2) Licensing +============ +Memtest86 is released under the terms of the Gnu Public License (GPL). Other +than the provisions of the GPL there are no restrictions for use, private or +commercial. See: http://www.gnu.org/licenses/gpl.html for details. +Explicit permission for inclusion of Memtest86 in software compilations and +publications is hereby granted. + + +3) Installation (Linux Only) +============================ +Memtest86 is a stand alone program and can be loaded from either a disk +partition or from a floppy disk. + +To build Memtest86: + 1) Review the Makefile and adjust options as needed. + 2) Type "make" + +This creates a file named "memtest.bin" which is a bootable image. This +image file may be copied to a floppy disk or lilo may be used to boot this +image from a hard disk partition. + +To create a Memtest86 bootdisk + 1) Insert a blank write enabled floppy disk. + 2) As root, Type "make install" + +To boot from a disk partition via lilo + 1) Copy the image file to a permanent location (ie. /memtest). + 2) Add an entry in the lilo config file (usually /etc/lilo.conf) to boot + memtest86. Only the image and label fields need to be specified. + The following is a sample lilo entry for booting memtest86: + + image = /memtest + label = memtest + + 3) As root, type "lilo" + + At the lilo prompt enter memtest to boot memtest86. + +If you encounter build problems a binary image has been included (precomp.bin). +To create a boot-disk with this pre-built image do the following: + 1) Insert a blank write enabled floppy disk. + 2) Type "make install-precomp" + + +4) Serial Console +================= +Memtest86 can be used on PC's equipped with a serial port for the console. +By default serial port console support is not enabled since it slows +down testing. To enable change the SERIAL_CONSOLE_DEFAULT define in +config.h from a zero to a one. The serial console baud rate may also +be set in config.h with the SERIAL_BAUD_RATE define. The other serial +port settings are no parity, 8 data bits, 1 stop bit. All of the features +used by memtest86 are accessible via the serial console. However, the +screen sometimes is garbled when the online commands are used. + + +5) Online Commands +================== +Memtest86 has a limited number of online commands. Online commands +provide control over caching, test selection, address range and error +scrolling. A help bar is displayed at the bottom of the screen listing +the available on-line commands. + + Command Description + + ESC Exits the test and does a warm restart via the BIOS. + + c Enters test configuration menu + Menu options are: + 1) Cache mode + 2) Test selection + 3) Address Range + 4) Memory Sizing + 5) Error Summary + 6) Error Report Mode + 7) ECC Mode + 8) Restart + 9) Adv. Options + + SP Set scroll lock (Stops scrolling of error messages) + Note: Testing is stalled when the scroll lock is + set and the scroll region is full. + + CR Clear scroll lock (Enables error message scrolling) + + +6) Memory Sizing +================ +The BIOS in modern PC's will often reserve several sections of memory for +it's use and also to communicate information to the operating system (ie. +ACPI tables). It is just as important to test these reserved memory blocks +as it is for the remainder of memory. For proper operation all of memory +needs to function properly regardless of what the eventual use is. For +this reason Memtest86 has been designed to test as much memory as is +possible. + +However, safely and reliably detecting all of the available memory has been +problematic. Versions of Memtest86 prior to v2.9 would probe to find where +memory is. This works for the vast majority of motherboards but is not 100% +reliable. Sometimes the memory size is incorrect and worse probing the wrong +places can in some cases cause the test to hang or crash. + +Starting in version 2.9 alternative methods are available for determining the +memory size. By default the test attempts to get the memory size from the +BIOS using the "e820" method. With "e820" the BIOS provides a table of memory +segments and identifies what they will be used for. By default Memtest86 +will test all of the ram marked as available and also the area reserved for +the ACPI tables. This is safe since the test does not use the ACPI tables +and the "e820" specifications state that this memory may be reused after the +tables have been copied. Although this is a safe default some memory will +not be tested. + +Two additional options are available through online configuration options. +The first option (BIOS-All) also uses the "e820" method to obtain a memory +map. However, when this option is selected all of the reserved memory +segments are tested, regardless of what their intended use is. The only +exception is memory segments that begin above 3gb. Testing has shown that +these segments are typically not safe to test. The BIOS-All option is more +thorough but could be unstable with some motherboards. + +The second option for memory sizing is the traditional "Probe" method. +This is a very thorough but not entirely safe method. In the majority of +cases the BIOS-All and Probe methods will return the same memory map. + +For older BIOS's that do not support the "e820" method there are two +additional methods (e801 and e88) for getting the memory size from the +BIOS. These methods only provide the amount of extended memory that is +available, not a memory table. When the e801 and e88 methods are used +the BIOS-All option will not be available. + +The MemMap field on the display shows what memory size method is in use. +Also the RsvdMem field shows how much memory is reserved and is not being +tested. + + +7) Error Information +====================== +Memtest has two options for reporting errors. The default is to report +individual errors. In BadRAM Patterns mode patterns are created for +use with the Linux BadRAM feature. This slick feature allows Linux to +avoid bad memory pages. Details about the BadRAM feature can be found at: + + http://home.zonnet.nl/vanrein/badram + +For individual errors the following information is displayed when a memory +error is detected. An error message is only displayed for errors with a +different address or failing bit pattern. All displayed values are in +hexadecimal. + + Tst: Test number + Failing Address : Failing memory address + Good: Expected data pattern + Bad: Failing data pattern + Err-Bits: Exclusive or of good and bad data (this shows the + position of the failing bit(s)) + Count: Number of consecutive errors with the same address + and failing bits + +In BadRAM Patterns mode, Lines are printed in a form badram=F1,M1,F2,M2. +In each F/M pair, the F represents a fault address, and the corresponding M +is a bitmask for that address. These patterns state that faults have +occurred in addresses that equal F on all "1" bits in M. Such a pattern may +capture more errors that actually exist, but at least all the errors are +captured. These patterns have been designed to capture regular patterns of +errors caused by the hardware structure in a terse syntax. + +The BadRAM patterns are `grown' increment-ally rather than `designed' from an +overview of all errors. The number of pairs is constrained to five for a +number of practical reasons. As a result, handcrafting patterns from the +output in address printing mode may, in exceptional cases, yield better +results. + + +8) Trouble-shooting Memory Errors +================================ +Please be aware that not all errors reported by Memtest86 are due to +bad memory. The test implicitly tests the CPU, L1 and L2 caches as well as +the motherboard. It is impossible for the test to determine what causes +the failure to occur. Most failures will be due to a problem with memory. +When it is not, the only option is to replace parts until the failure is +corrected. + +Once a memory error has been detected, determining the failing +module is not a clear cut procedure. With the large number of motherboard +vendors and possible combinations of simm slots it would be difficult if +not impossible to assemble complete information about how a particular +error would map to a failing memory module. However, there are steps +that may be taken to determine the failing module. Here are three +techniques that you may wish to use: + +1) Removing modules +This is simplest method for isolating a failing modules, but may only be +employed when one or more modules can be removed from the system. By +selectively removing modules from the system and then running the test +you will be able to find the bad module(s). Be sure to note exactly which +modules are in the system when the test passes and when the test fails. + +2) Rotating modules +When none of the modules can be removed then you may wish to rotate modules +to find the failing one. This technique can only be used if there are +three or more modules in the system. Change the location of two modules +at a time. For example put the module from slot 1 into slot 2 and put +the module from slot 2 in slot 1. Run the test and if either the failing +bit or address changes then you know that the failing module is one of the +ones just moved. By using several combinations of module movement you +should be able to determine which module is failing. + +3) Replacing modules +If you are unable to use either of the previous techniques then you are +left to selective replacement of modules to find the failure. + +4) Avoiding allocation +The printing mode for BadRAM patterns is intended to construct boot time +parameters for a Linux kernel that is compiled with BadRAM support. This +work-around makes it possible for Linux to reliably run on defective +RAM. For more information on BadRAM support +for Linux, sail to + + http://home.zonnet.nl/vanrein/badram + +Sometimes memory errors show up due to component incompatibility. A memory +module may work fine in one system and not in another. This is not +uncommon and is a source of confusion. The components are not necessarily +bad but certain combinations may need to be avoided. + +I am often asked about the reliability of errors reported by Mestest86. +In the vast majority of cases errors reported by the test are valid. +There are some systems that cause Memtest86 to be confused about the size of +memory and it will try to test non-existent memory. This will cause a large +number of consecutive addresses to be reported as bad and generally there +will be many bits in error. If you have a relatively small number of +failing addresses and only one or two bits in error you can be certain +that the errors are valid. Also intermittent errors are always valid. + +All valid memory errors should be corrected. It is possible that a +particular error will never show up in normal operation. However, operating +with marginal memory is risky and can result in data loss and even +disk corruption. You can be sure that Murphy will get you if you know +about a memory error and ignore it. + +Memtest86 can not diagnose many types of PC failures. For example a +faulty CPU that causes Windows to crash will most likely just cause +Memtest86 to crash in the same way. + + +9) Execution Time +================== +The time required for a complete pass of Memtest86 will vary greatly +depending on CPU speed, memory speed and memory size. Memtest86 executes +indefinitely. The pass counter increments each time that all of the +selected tests have been run. Generally a single pass is sufficient to +catch all but the most obscure errors. However, for complete confidence +when intermittent errors are suspected testing for a longer period is advised. + +10) Memory Testing Philosophy +============================= +There are many good approaches for testing memory. However, many tests +simply throw some patterns at memory without much thought or knowledge +of memory architecture or how errors can best be detected. This +works fine for hard memory failures but does little to find intermittent +errors. BIOS based memory tests are useless for finding intermittent +memory errors. + +Memory chips consist of a large array of tightly packed memory cells, +one for each bit of data. The vast majority of the intermittent failures +are a result of interaction between these memory cells. Often writing a +memory cell can cause one of the adjacent cells to be written with the +same data. An effective memory test attempts to test for this +condition. Therefore, an ideal strategy for testing memory would be +the following: + + 1) write a cell with a zero + 2) write all of the adjacent cells with a one, one or more times + 3) check that the first cell still has a zero + +It should be obvious that this strategy requires an exact knowledge +of how the memory cells are laid out on the chip. In addition there is a +never ending number of possible chip layouts for different chip types +and manufacturers making this strategy impractical. However, there +are testing algorithms that can approximate this ideal strategy. + + +11) Memtest86 Test Algorithms +============================= +Memtest86 uses two algorithms that provide a reasonable approximation +of the ideal test strategy above. The first of these strategies is called +moving inversions. The moving inversion test works as follows: + + 1) Fill memory with a pattern + 2) Starting at the lowest address + 2a check that the pattern has not changed + 2b write the patterns complement + 2c increment the address + repeat 2a - 2c + 3) Starting at the highest address + 3a check that the pattern has not changed + 3b write the patterns complement + 3c decrement the address + repeat 3a - 3c + +This algorithm is a good approximation of an ideal memory test but +there are some limitations. Most high density chips today store data +4 to 16 bits wide. With chips that are more than one bit wide it +is impossible to selectively read or write just one bit. This means +that we cannot guarantee that all adjacent cells have been tested +for interaction. In this case the best we can do is to use some +patterns to insure that all adjacent cells have at least been written +with all possible one and zero combinations. + +It can also be seen that caching, buffering and out of order execution +will interfere with the moving inversions algorithm and make less effective. +It is possible to turn off cache but the memory buffering in new high +performance chips can not be disabled. To address this limitation a new +algorithm I call Modulo-X was created. This algorithm is not affected by +cache or buffering. The algorithm works as follows: + 1) For starting offsets of 0 - 20 do + 1a write every 20th location with a pattern + 1b write all other locations with the patterns complement + repeat 1b one or more times + 1c check every 20th location for the pattern + +This algorithm accomplishes nearly the same level of adjacency testing +as moving inversions but is not affected by caching or buffering. Since +separate write passes (1a, 1b) and the read pass (1c) are done for all of +memory we can be assured that all of the buffers and cache have been +flushed between passes. The selection of 20 as the stride size was somewhat +arbitrary. Larger strides may be more effective but would take longer to +execute. The choice of 20 seemed to be a reasonable compromise between +speed and thoroughness. + + +12) Individual Test Descriptions +================================ +Memtest86 executes a series of numbered test sections to check for +errors. These test sections consist of a combination of test +algorithm, data pattern and caching. The execution order for these tests +were arranged so that errors will be detected as rapidly as possible. +A description of each of the test sections follows: + +Test 0 [Address test, walking ones, no cache] + Tests all address bits in all memory banks by using a walking ones + address pattern. Errors from this test are not used to calculate + BadRAM patterns. + +Test 1 [Address test, own address] + Each address is written with its own address and then is checked + for consistency. In theory previous tests should have caught any + memory addressing problems. This test should catch any addressing + errors that somehow were not previously detected. + +Test 2 [Moving inversions, ones&zeros] + This test uses the moving inversions algorithm with patterns of all + ones and zeros. Cache is enabled even though it interferes to some + degree with the test algorithm. With cache enabled this test does not + take long and should quickly find all "hard" errors and some more + subtle errors. This section is only a quick check. + +Test 3 [Moving inversions, 8 bit pat] + This is the same as test 1 but uses a 8 bit wide pattern of + "walking" ones and zeros. This test will better detect subtle errors + in "wide" memory chips. A total of 20 data patterns are used. + +Test 4 [Moving inversions, random pattern] + Test 4 uses the same algorithm as test 1 but the data pattern is a + random number and it's complement. This test is particularly effective + in finding difficult to detect data sensitive errors. A total of 60 + patterns are used. The random number sequence is different with each pass + so multiple passes increase effectiveness. + +Test 5 [Block move, 64 moves] + This test stresses memory by using block move (movsl) instructions + and is based on Robert Redelmeier's burnBX test. Memory is initialized + with shifting patterns that are inverted every 8 bytes. Then 4MB blocks + of memory are moved around using the movsl instruction. After the moves + are completed the data patterns are checked. Because the data is checked + only after the memory moves are completed it is not possible to know + where the error occurred. The addresses reported are only for where the + bad pattern was found. Since the moves are constrained to a 8MB segment + of memory the failing address will always be lest than 8MB away from the + reported address. Errors from this test are not used to calculate + BadRAM patterns. + +Test 6 [Moving inversions, 32 bit pat] + This is a variation of the moving inversions algorithm that shifts the data + pattern left one bit for each successive address. The starting bit position + is shifted left for each pass. To use all possible data patterns 32 passes + are required. This test is quite effective at detecting data sensitive + errors but the execution time is long. + +Test 7 [Random number sequence] + This test writes a series of random numbers into memory. By resetting the + seed for the random number the same sequence of number can be created for + a reference. The initial pattern is checked and then complemented and + checked again on the next pass. However, unlike the moving inversions test + writing and checking can only be done in the forward direction. + +Test 8 [Modulo 20, ones&zeros] + Using the Modulo-X algorithm should uncover errors that are not + detected by moving inversions due to cache and buffering interference + with the the algorithm. All ones and zeros are used for data patterns. + +Test 9 [Bit fade test, 90 min, 2 patterns] + The bit fade test initializes all of memory with a pattern and then + sleeps for 90 minutes. Then memory is examined to see if any memory bits + have changed. All ones and all zero patterns are used. This test takes + 3 hours to complete. The Bit Fade test is not included in the normal test + sequence and must be run manually via the runtime configuration menu. + + +13) Problem Reporting - Contact Information +=========================================== +Due to the growing popularity of Memtest86 (more than 200,000 downloads per +month) I have been inundated by, questions, feedback, problem reports and +requests for enhancements. I simply do not have time to repond to ANY Memtest86 +emails. Bug reports and suggestions are welcome but will typically not be +responded to. + +*** NOTE: *** The Keyword MEM86 must appear in the subject of all emails or +the message will be automaticly deleted before it gets to me. This thanks to +spam and viruses! + +Problems/Bugs: +Before submitting a problem report please check the Known Problems section +to see if this problem has already been reported. Be sure to include the +version number and also any details that may be relevant. + +Chris Brady, Email: bugs@memtest86.com + +With some PC's Memtest86 will just die with no hints as to what went wrong. +Without any details it is impossible to fix these failures. Fixing these +problems will require debugging on your part. There is no point in reporting +these failures unless you have a Linux system and would be willing to debug +the failure. + +Enhancements: +If you would like to request an enhancement please see if is already on +the Planned Features List before sending your request. All requests will +be considered, but not all can be implemented. If you are be interested in +contributing code please contact me so that the integration can be +co-ordinated. + +Chris Brady, Email: enhance@memtest86.com + +Questions: +Unfortunately, I do not have time to respond to any questions or provide +assistance with troubleshooting problems. Please read the Troubleshooting +and Known Problems sections for assistance with problems. These sections have +the answers for the questions that I have answers to. If there is not an +answer for your problem in these sections it is probably not something I can +help you with. + + + +14) Known Problems +================== +Sometimes when booting from a floppy disk the following messages scroll up +on the screen: + X:8000 + AX:0212 + BX:8600 + CX:0201 + DX:0000 +This the BIOS reporting floppy disk read errors. Either re-write or toss +the floppy disk. + +Memtest86 has no support for multiple CPUs. Memtest86 should run +without problems, but it will only use one CPU. + +Memtest86 can not diagnose many types of PC failures. For example a +faulty CPU that causes Windows to crash will most likely just cause +Memtest86 to crash in the same way. + +There have been numerous reports of errors in only tests 5 and 8 on Athlon +systems. Often the memory works in a different system or the vendor insists +that it is good. In these cases the memory is not necessarily bad but is +not able to operate reliably at Athlon speeds. Sometimes more conservative +memory timings on the motherboard will correct these errors. In other +cases the only option is to replace the memory with better quality, higher +speed memory. Don't buy cheap memory and expect it to work with an Athlon! + +Memtest86 supports all types of memory. If fact the test has absolutely +no knowledge of the memory type nor does it need to. This not a problem +or bug but is listed here due to the many questions I get about this issue. + +Changes in the compiler and loader have caused problems with +Memtest86 resulting in both build failures and errors in execution. A +binary image (precomp.bin) of the test is included and may be used if +problems are encountered. + +15) Planned Features List +========================= +This is a list of enhancements planned for future releases of Memtest86. +There is no timetable for when these will be implemented, if ever. + + - Option to allow printing of error information on an attached printer. + - Option to write error information to a floppy disk. + - Supply Memtest in RPM format. + - Read and display RAM SPD information. + + +16) Change Log +============== +Enhancements in v3.2 (11/Nov/2004) + + Added two new, highly effective tests that use random number patterns + (tests 4 and 6). + + Reworked the online commands: + - Changed wording for better clarity + - Dropped Cache Mode menu + + Updated CPU detection for newer AMD, Intel and Cyrix CPUs. + + Reworked test sequence: + - Dropped ineffective non cached tests (Numbers 7-11) + - Changed cache mode to cached for test 2 + - Fixed bug that did not allow tsome tests to be skipped + - Added bailout for Bit fade test + + Error reports are highlighted in red to provide a more vivid error + indication. + + Added support for a large number of additional chipsets. (from Memtest86+ + v1.30) + + Added an advanced setup feature that with new chiset allows memory timings + to be altered from inside Memtest86. (from Memtest86+ v1.30) + + +Enhancements in v3.1 (11/Mar/2004) + + Added processor detection for newer AMD processors. + + Added new "Bit Fade" extended test. + + Fixed a complile time bug with gcc version 3.x. + + E7500 memory controller ECC support + + Added support for 16bit ECC syndromes + + Option to keep the serial port baud rate of the boot loader + + +Enhancements in v3.0 (22/May/2002) Provided by Eric Biederman + + Testing of more than 2gb of memory is at last fixed (tested with 6Gb) + + The infrastructure is to poll ecc error reporting chipset regisets, + and the support has been done for some chipsets. + + Uses dynamic relocation information records to make itself PIC + instead of requiring 2 copies of memtest86 in the binary. + + The serial console code does not do redundant writes to the serial port + Very little slow down at 9600 baud. + + You can press ^l or just l to get a screen refresh, when you are + connecting and unconnecting a serial cable. + + Netbooting is working again + + LinuxBIOS support (To get the memory size) + + Many bugfixes and code cleanup. + +Enhancements in v2.9 (29/Feb/2002) + + The memory sizing code has been completely rewritten. By default + Memtest86 gets a memory map from the BIOS that is now used to find + available memory. A new online configuration option provides three + choices for how memory will be sized, including the old "probe" method. + The default mode generally will not test all of memory, but should be more + stable. See the "Memory Sizing" section for details. + + Testing of more than 2gb of memory should now work. A number of bugs + were found and corrected that prevented testing above 2gb. Testing + with more than 2gb has been limited and there could be problems with a + full 4gb of memory. + + Memory is divided into segments for testing. This allow for frequent + progress updates and responsiveness to interactive commands. The + memory segment size has been increased from 8 to 32mb. This should + improve testing effectivness but progress reports will be less frequent. + + Minor bug fixes. + +Enhancements in v2.8 (18/Oct/2001) + Eric Biederman reworked the build process making it far simpler and also + to produce a network bootable ELF image. + + Re-wrote the memory and cache speed detection code. Previously the + reported numbers were inaccurate for intel CPU's and completely wrong + for Athlon/Duron CPU's. + + By default the serial console is disabled since this was slowing + down testing. + + Added CPU detection for Pentium 4. + + +Enhancements in v2.7 (12/Jul/2001) + Expanded workaround for errors caused by BIOS USB keyboard support to + include test #5. + + Re-worked L1 / L2 cache detection code to provide clearer reporting. + + Fixed an obvious bug in the computation of cache and memory speeds. + + Changed on-line menu to stay in the menu between option selections. + + Fixed bugs in the test restart and redraw code. + + Adjusted code size to fix compilation problems with RedHat 7.1. + + Misc updates to the documentation. + +Enhancements in v2.6 (25/May/2001) + Added workaround for errors caused by BIOS USB keyboard support. + + Fixed problems with reporting of 1 GHZ + processor speeds. + + Fixed Duron cache detection. + + Added screen buffer so that menus will work correctly from a serial + console. + + The Memtest86 image is now built in ELF format. + +Enhancements in v2.5 (14/Dec/00) + Enhanced CPU and cache detection to correctly identify Duron CPU + and K6-III 1MB cache. + + Added code to report cache-able memory size. + + Added limited support for parity memory. + + Support was added to allow use of on-line commands from a serial + port. + + Dropped option for changing refresh rates. This was not useful + and did not work on newer motherboards. + + Improved fatal exception reporting to include a register and stack + dump. + + The pass number is now displayed in the error report. + + Fixed a bug that crashed the test when selecting one of the extended + tests. + +Enhancements in v2.4 + The error report format was reworked for better clarity and now + includes a decimal address in megabytes. + + A new memory move test was added (from Robert Redelmeier's CPU-Burn) + + The test sequence and iterations were modified. + + Fixed scrolling problems with the BadRAM patterns. + + +Enhancements in v2.3 + A progress meter was added to replace the spinner and dots. + + Measurement and reporting of memory and cache performance + was added. + + Support for creating BadRAM patterns was added. + + All of the test routines were rewritten in assembler to + improve both test performance and speed. + + The screen layout was reworked to hopefully be more readable. + + An error summary option was added to the online commands. + + +Enhancements in v2.2 + Added two new address tests + + Added an on-line command for setting test address range + + Optimized test code for faster execution (-O3, -funroll-loops and + -fomit-frame-pointer) + + Added and elapsed time counter. + + Adjusted menu options for better consistency + + +Enhancements in v2.1 + Fixed a bug in the CPU detection that caused the test to + hang or crash with some 486 and Cryrix CPU's + + Added CPU detection for Cyrix CPU's + + Extended and improved CPU detection for Intel and AMD CPU's + + Added a compile time option (BIOS_MEMSZ) for obtaining the last + memory address from the BIOS. This should fix problems with memory + sizing on certain motherboards. This option is not enabled by default. + It may be enabled be default in a future release. + +Enhancements in v2.0 + Added new Modulo-20 test algorithm. + + Added a 32 bit shifting pattern to the moving inversions algorithm. + + Created test sections to specify algorithm, pattern and caching. + + Improved test progress indicators. + + Created popup menus for configuration. + + Added menu for test selection. + + Added CPU and cache identification. + + Added a "bail out" feature to quit the current test when it does not + fit the test selection parameters. + + Re-arranged the screen layout and colors. + + Created local include files for I/O and serial interface definitions + rather than using the sometimes incompatible system include files. + + Broke up the "C" source code into four separate source modules. + +Enhancements in v1.5 + Some additional changes were made to fix obscure memory sizing + problems. + + The 4 bit wide data pattern was increased to 8 bits since 8 bit + wide memory chips are becoming more common. + + A new test algorithm was added to improve detection of data + pattern sensitive errors. + + +Enhancements in v1.4 + Changes to the memory sizing code to avoid problems with some + motherboards where memtest would find more memory than actually + exists. + + Added support for a console serial port. (thanks to Doug Sisk) + + On-line commands are now available for configuring Memtest86 on + the fly (see On-line Commands). + + +Enhancements in v1.3 + Scrolling of memory errors is now provided. Previously, only one screen + of error information was displayed. + + Memtest86 can now be booted from any disk via lilo. + + Testing of up to 4gb of memory has been fixed is now enabled by default. + This capability was clearly broken in v1.2a and should work correctly + now but has not been fully tested (4gb PC's are a bit rare). + + The maximum memory size supported by the motherboard is now being + calculated correctly. In previous versions there were cases where not + all of memory would be tested and the maximum memory size supported + was incorrect. + + For some types of failures the good and bad values were reported to be + same with an Xor value of 0. This has been fixed by retaining the data + read from memory and not re-reading the bad data in the error reporting + routine. + + APM (advanced power management) is now disabled by Memtest86. This + keeps the screen from blanking while the test is running. + + Problems with enabling & disabling cache on some motherboards have been + corrected. + + +17) Donations +============= +With considerable reluctance I am resorting to a low key solicitation for +donations. It never has been my intent to profit from this program and I am +pleased that Memtest86 has been helpful. However, the time required to +support this program has grown significantly. I also have the modest +cost of hosting this web-site that I would like to recover. So if you find +Memtest86 useful and you feel inclined to make a small PayPal donation please +do so. Use "cbrady@memtest86.com" for the recipient. + + +18) Acknowledgments +=================== +Memtest86 was developed by Chris Brady with the resources and assistance +listed below: + +- The initial versions of the source files bootsect.S, setup.S, head.S and + build.c are from the Linux 1.2.1 kernel and have been heavily modified. + +- Doug Sisk provided code to support a console connected via a serial port. + +- Code to create BadRAM patterns was provided by Rick van Rein. + +- Tests 5 and 8 are based on Robert Redelmeier's burnBX test. + +- Screen buffer code was provided by Jani Averbach. + +- Eric Biederman provided all of the feature content for version 3.0 + plus many bugfixes and significant code cleanup. + +- Major enhancements to hardware detection and reporting in version 3.2 + provided by Samuel Demeulemeester (from Memtest86+ v1.11). diff --git a/README.build-process b/README.build-process index 19edfcf..37ca48a 100644 --- a/README.build-process +++ b/README.build-process @@ -1,39 +1,39 @@ -During memory testing memtest86 relocates itself in memory so it can test the -memory it was previously running from. memtest86 is compiled as position mostly -independent code. Some relocations records must be processed to achieve the -affect of position independent code. A 16 bit loader is prepended to memtest86 -so it can be loaded from a floppy, or from lilo. - -In restructuring the build process I had several goals. Maintainability and -comprehsibility of the build process. Simplicity of the toolset. And the -ability to build images bootable by both the legacy x86 bootloader, -and images bootable by bootloaders that directly load static ELF images. - -With the ability to proecess relocation records, memtest.bin has been -reduced in size from 84480 bytes to 49308 bytes. And now only requires one copy -of memtest86. A reduction in size of 35K. And the build process can now ignore -the size of memtest86. - -BIOS calls have been moved from setup.S to head.S making bootsect.S and -setup.S exclusively for booting. - -memtest86 is built in three stages. In the first stage the relocatable object -files are built as with any program. In the second stage the relocatable object -files are linked together into memtest_shared, a shared library version -of memtest86. In the third stage a raw memory image of memtest_shared is formed -and linked into memtest.bin, and memtest. - -memtest.bin is the floppy/lilo bootable target. - -memtest is the ELF bootable target. - -Another major change is now data in the bss segment is also preserved -when memtest86 is relocated, and memtest86 can be relocated to any address. - -The one thing to watch out for is pointers to data inside of memtest86. Except -for constant pointers to static data there is not enough information to generate -relocation records for pointers so they will not change when memtest86 is -relocated, which might lead to nasty surpises. - -Eric Biederman - +During memory testing memtest86 relocates itself in memory so it can test the +memory it was previously running from. memtest86 is compiled as position mostly +independent code. Some relocations records must be processed to achieve the +affect of position independent code. A 16 bit loader is prepended to memtest86 +so it can be loaded from a floppy, or from lilo. + +In restructuring the build process I had several goals. Maintainability and +comprehsibility of the build process. Simplicity of the toolset. And the +ability to build images bootable by both the legacy x86 bootloader, +and images bootable by bootloaders that directly load static ELF images. + +With the ability to proecess relocation records, memtest.bin has been +reduced in size from 84480 bytes to 49308 bytes. And now only requires one copy +of memtest86. A reduction in size of 35K. And the build process can now ignore +the size of memtest86. + +BIOS calls have been moved from setup.S to head.S making bootsect.S and +setup.S exclusively for booting. + +memtest86 is built in three stages. In the first stage the relocatable object +files are built as with any program. In the second stage the relocatable object +files are linked together into memtest_shared, a shared library version +of memtest86. In the third stage a raw memory image of memtest_shared is formed +and linked into memtest.bin, and memtest. + +memtest.bin is the floppy/lilo bootable target. + +memtest is the ELF bootable target. + +Another major change is now data in the bss segment is also preserved +when memtest86 is relocated, and memtest86 can be relocated to any address. + +The one thing to watch out for is pointers to data inside of memtest86. Except +for constant pointers to static data there is not enough information to generate +relocation records for pointers so they will not change when memtest86 is +relocated, which might lead to nasty surpises. + +Eric Biederman + diff --git a/bootsect.S b/bootsect.S index ee3bd90..982775d 100644 --- a/bootsect.S +++ b/bootsect.S @@ -1,375 +1,375 @@ -/* - * bootsect.s Copyright (C) 1991, 1992 Linus Torvalds - * - * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves - * itself out of the way to address 0x90000, and jumps there. - * - * It then loads 'setup' directly after itself (0x90200), and the system - * at 0x10000, using BIOS interrupts. - * - * The loader has been made as simple as possible, and continuos - * read errors will result in a unbreakable loop. Reboot by hand. It - * loads pretty fast by getting whole tracks at a time whenever possible. - * - * 1-Jan-96 Modified by Chris Brady for use as a boot loader for MemTest-86. - */ - -#include "defs.h" - -ROOT_DEV = 0 - -.code16 -.section ".bootsect", "ax", @progbits -_boot: - - -# ld86 requires an entry symbol. This may as well be the usual one. -.globl _main -_main: - movw $BOOTSEG, %ax - movw %ax, %ds - movw $INITSEG, %ax - movw %ax, %es - movw $256, %cx - subw %si, %si - subw %di, %di - cld - rep - movsw - ljmp $INITSEG, $go - _boot - -go: - movw %cs, %ax - movw $(0x4000-12), %dx # 0x4000 is arbitrary value >= length of - # bootsect + length of setup + room for stack - # 12 is disk parm size - -# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We -# wouldn't have to worry about this if we checked the top of memory. Also -# my BIOS can be configured to put the wini drive tables in high memory -# instead of in the vector table. The old stack might have clobbered the -# drive table. - - movw %ax, %ds - movw %ax, %es - movw %ax, %ss # put stack at INITSEG:0x4000-12. - movw %dx, %sp - -/* - * Many BIOS's default disk parameter tables will not - * recognize multi-sector reads beyond the maximum sector number - * specified in the default diskette parameter tables - this may - * mean 7 sectors in some cases. - * - * Since single sector reads are slow and out of the question, - * we must take care of this by creating new parameter tables - * (for the first disk) in RAM. We will set the maximum sector - * count to 18 - the most we will encounter on an HD 1.44. - * - * High doesn't hurt. Low does. - * - * Segments are as follows: ds=es=ss=cs - INITSEG, - * fs = 0, gs = parameter table segment - */ - pushw $0 - popw %fs - movw $0x78, %bx # fs:bx is parameter table address - lgs %fs:(%bx),%si # gs:si is source - - movw %dx, %di # es:di is destination - movw $6, %cx # copy 12 bytes - cld - - rep movsw %gs:(%si), (%di) - - movw %dx, %di - movb $18, 4(%di) # patch sector count - - movw %di, %fs:(%bx) - movw %es, %fs:2(%bx) - - movw %cs, %ax - movw %ax, %fs - movw %ax, %gs - - xorb %ah, %ah # reset FDC - xorb %dl, %dl - int $0x13 - -# load the setup-sectors directly after the bootblock. -# Note that 'es' is already set up. - -load_setup: - xorw %dx, %dx # drive 0, head 0 - movw $0x0002, %cx # sector 2, track 0 - movw $0x0200, %bx # address = 512, in INITSEG - movw $(0x0200 + SETUPSECS), %ax # service 2, nr of sectors - # (assume all on head 0, track 0) - int $0x13 # read it - jnc ok_load_setup # ok - continue - - pushw %ax # dump error code - call print_nl - movw %sp, %bp - call print_hex - popw %ax - - xorb %dl, %dl # reset FDC - xorb %ah, %ah - int $0x13 - jmp load_setup - -ok_load_setup: - -# Get disk drive parameters, specifically nr of sectors/track - - -/* It seems that there is no BIOS call to get the number of sectors. Guess - * 18 sectors if sector 18 can be read, 15 if sector 15 can be read. - * Otherwise guess 9 - */ - - xorw %dx, %dx # drive 0, head 0 - movw $0x0012, %cx # sector 18, track 0 - movw $(0x200+(SETUPSECS*0x200)), %bx # address after setup (es = cs) - movw $0x0201, %ax # service 2, 1 sector - int $0x13 - jnc got_sectors - movb $0x0f, %cl # sector 15 - movw $0x0201, %ax # service 2, 1 sector - int $0x13 - jnc got_sectors - movb $0x09, %cl - -got_sectors: - movw %cx, %cs:sectors - _boot - movw $INITSEG, %ax - movw %ax, %es - -# Print some inane message - - movb $0x03, %ah # read cursor pos - xorb %bh, %bh - int $0x10 - - movw $9, %cx - movw $0x0007, %bx # page 0, attribute 7 (normal) - movw $msg1 - _boot, %bp - movw $0x1301, %ax # write string, move cursor - int $0x10 - -# ok, we've written the message, now -# we want to load the system (at 0x10000) - - movw $TSTLOAD, %ax - movw %ax, %es # segment of 0x010000 - call read_it - call kill_motor - call print_nl - -# after that (everyting loaded), we jump to -# the setup-routine loaded directly after -# the bootblock: - - ljmp $SETUPSEG,$0 - -# This routine loads the system at address 0x10000, making sure -# no 64kB boundaries are crossed. We try to load it as fast as -# possible, loading whole tracks whenever we can. -# -# in: es - starting address segment (normally 0x1000) -# -sread: .word 1+SETUPSECS # sectors read of current track -head: .word 0 # current head -track: .word 0 # current track - -read_it: - movw %es, %ax - testw $0x0fff, %ax -die: - jne die # es must be at 64kB boundary - xorw %bx,%bx # bx is starting address within segment -rp_read: - movw %es, %ax - subw $TSTLOAD, %ax # have we loaded all yet? - cmpw syssize - _boot, %ax - jbe ok1_read - ret -ok1_read: - movw %cs:sectors - _boot, %ax - subw sread - _boot, %ax - movw %ax, %cx - shlw $9, %cx - addw %bx, %cx - jnc ok2_read - je ok2_read - xorw %ax, %ax - subw %bx, %ax - shrw $9, %ax -ok2_read: - call read_track - movw %ax, %cx - add sread - _boot, %ax - cmpw %cs:sectors - _boot, %ax - jne ok3_read - movw $1, %ax - subw head - _boot, %ax - jne ok4_read - incw track - _boot -ok4_read: - movw %ax, head - _boot - xorw %ax, %ax -ok3_read: - movw %ax, sread - _boot - shlw $9, %cx - addw %cx, %bx - jnc rp_read - movw %es, %ax - addb $0x10, %ah - movw %ax, %es - xorw %bx, %bx - jmp rp_read - -read_track: - pusha - pusha - movw $0xe2e, %ax # loading... message 2e = . - movw $7, %bx - int $0x10 - popa - - movw track - _boot, %dx - movw sread - _boot, %cx - incw %cx - movb %dl, %ch - movw head - _boot, %dx - movb %dl, %dh - andw $0x0100, %dx - movb $2, %ah - - pushw %dx # save for error dump - pushw %cx - pushw %bx - pushw %ax - - int $0x13 - jc bad_rt - addw $8, %sp - popa - ret - -bad_rt: - pushw %ax # save error code - call print_all # ah = error, al = read - - xorb %ah, %ah - xorb %dl, %dl - int $0x13 - - addw $10, %sp - popa - jmp read_track - -/* - * print_all is for debugging purposes. - * It will print out all of the registers. The assumption is that this is - * called from a routine, with a stack frame like - * dx - * cx - * bx - * ax - * error - * ret <- sp - * -*/ - -print_all: - movw $5, %cx # error code + 4 registers - movw %sp, %bp - -print_loop: - pushw %cx # save count left - call print_nl # nl for readability - - cmpb 5, %cl # see if register name is needed - jae no_reg - - movw $(0xe05 + 'A' - 1), %ax - subb %cl, %al - int $0x10 - movb $'X', %al - int $0x10 - movb $':', %al - int $0x10 - -no_reg: - addw $2, %bp # next register - call print_hex # print it - popw %cx - loop print_loop - ret - -print_nl: - movw $0xe0d, %ax # CR - int $0x10 - movb $0x0a, %al # LF - int $0x10 - ret - -/* - * print_hex is for debugging purposes, and prints the word - * pointed to by ss:bp in hexadecmial. -*/ - -print_hex: - movw $4, %cx # 4 hex digits - movw (%bp), %dx # load word into dx - -print_digit: - rolw $4, %dx # rotate so that lowest 4 bits are used - movb $0xe, %ah - movb %dl, %al # mask off so we have only next nibble - andb $0xf, %al - addb $'0', %al # convert to 0-based digit - cmpb $'9', %al # check for overflow - jbe good_digit - addb $('A' - '0' - 10), %al - -good_digit: - int $0x10 - loop print_digit - ret - - -/* - * This procedure turns off the floppy drive motor, so - * that we enter the kernel in a known state, and - * don't have to worry about it later. - */ -kill_motor: - pushw %dx - movw $0x3f2, %dx - xorb %al, %al - outb %al, %dx - popw %dx - ret - -sectors: - .word 0 - -msg1: - .byte 13,10 - .ascii "Loading" - -.org 497 -setup_sects: - .byte SETUPSECS -.org 500 -syssize: - .word _syssize -.org 508 -root_dev: - .word ROOT_DEV -boot_flag: - .word 0xAA55 -_eboot: +/* + * bootsect.s Copyright (C) 1991, 1992 Linus Torvalds + * + * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves + * itself out of the way to address 0x90000, and jumps there. + * + * It then loads 'setup' directly after itself (0x90200), and the system + * at 0x10000, using BIOS interrupts. + * + * The loader has been made as simple as possible, and continuos + * read errors will result in a unbreakable loop. Reboot by hand. It + * loads pretty fast by getting whole tracks at a time whenever possible. + * + * 1-Jan-96 Modified by Chris Brady for use as a boot loader for MemTest-86. + */ + +#include "defs.h" + +ROOT_DEV = 0 + +.code16 +.section ".bootsect", "ax", @progbits +_boot: + + +# ld86 requires an entry symbol. This may as well be the usual one. +.globl _main +_main: + movw $BOOTSEG, %ax + movw %ax, %ds + movw $INITSEG, %ax + movw %ax, %es + movw $256, %cx + subw %si, %si + subw %di, %di + cld + rep + movsw + ljmp $INITSEG, $go - _boot + +go: + movw %cs, %ax + movw $(0x4000-12), %dx # 0x4000 is arbitrary value >= length of + # bootsect + length of setup + room for stack + # 12 is disk parm size + +# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We +# wouldn't have to worry about this if we checked the top of memory. Also +# my BIOS can be configured to put the wini drive tables in high memory +# instead of in the vector table. The old stack might have clobbered the +# drive table. + + movw %ax, %ds + movw %ax, %es + movw %ax, %ss # put stack at INITSEG:0x4000-12. + movw %dx, %sp + +/* + * Many BIOS's default disk parameter tables will not + * recognize multi-sector reads beyond the maximum sector number + * specified in the default diskette parameter tables - this may + * mean 7 sectors in some cases. + * + * Since single sector reads are slow and out of the question, + * we must take care of this by creating new parameter tables + * (for the first disk) in RAM. We will set the maximum sector + * count to 18 - the most we will encounter on an HD 1.44. + * + * High doesn't hurt. Low does. + * + * Segments are as follows: ds=es=ss=cs - INITSEG, + * fs = 0, gs = parameter table segment + */ + pushw $0 + popw %fs + movw $0x78, %bx # fs:bx is parameter table address + lgs %fs:(%bx),%si # gs:si is source + + movw %dx, %di # es:di is destination + movw $6, %cx # copy 12 bytes + cld + + rep movsw %gs:(%si), (%di) + + movw %dx, %di + movb $18, 4(%di) # patch sector count + + movw %di, %fs:(%bx) + movw %es, %fs:2(%bx) + + movw %cs, %ax + movw %ax, %fs + movw %ax, %gs + + xorb %ah, %ah # reset FDC + xorb %dl, %dl + int $0x13 + +# load the setup-sectors directly after the bootblock. +# Note that 'es' is already set up. + +load_setup: + xorw %dx, %dx # drive 0, head 0 + movw $0x0002, %cx # sector 2, track 0 + movw $0x0200, %bx # address = 512, in INITSEG + movw $(0x0200 + SETUPSECS), %ax # service 2, nr of sectors + # (assume all on head 0, track 0) + int $0x13 # read it + jnc ok_load_setup # ok - continue + + pushw %ax # dump error code + call print_nl + movw %sp, %bp + call print_hex + popw %ax + + xorb %dl, %dl # reset FDC + xorb %ah, %ah + int $0x13 + jmp load_setup + +ok_load_setup: + +# Get disk drive parameters, specifically nr of sectors/track + + +/* It seems that there is no BIOS call to get the number of sectors. Guess + * 18 sectors if sector 18 can be read, 15 if sector 15 can be read. + * Otherwise guess 9 + */ + + xorw %dx, %dx # drive 0, head 0 + movw $0x0012, %cx # sector 18, track 0 + movw $(0x200+(SETUPSECS*0x200)), %bx # address after setup (es = cs) + movw $0x0201, %ax # service 2, 1 sector + int $0x13 + jnc got_sectors + movb $0x0f, %cl # sector 15 + movw $0x0201, %ax # service 2, 1 sector + int $0x13 + jnc got_sectors + movb $0x09, %cl + +got_sectors: + movw %cx, %cs:sectors - _boot + movw $INITSEG, %ax + movw %ax, %es + +# Print some inane message + + movb $0x03, %ah # read cursor pos + xorb %bh, %bh + int $0x10 + + movw $9, %cx + movw $0x0007, %bx # page 0, attribute 7 (normal) + movw $msg1 - _boot, %bp + movw $0x1301, %ax # write string, move cursor + int $0x10 + +# ok, we've written the message, now +# we want to load the system (at 0x10000) + + movw $TSTLOAD, %ax + movw %ax, %es # segment of 0x010000 + call read_it + call kill_motor + call print_nl + +# after that (everyting loaded), we jump to +# the setup-routine loaded directly after +# the bootblock: + + ljmp $SETUPSEG,$0 + +# This routine loads the system at address 0x10000, making sure +# no 64kB boundaries are crossed. We try to load it as fast as +# possible, loading whole tracks whenever we can. +# +# in: es - starting address segment (normally 0x1000) +# +sread: .word 1+SETUPSECS # sectors read of current track +head: .word 0 # current head +track: .word 0 # current track + +read_it: + movw %es, %ax + testw $0x0fff, %ax +die: + jne die # es must be at 64kB boundary + xorw %bx,%bx # bx is starting address within segment +rp_read: + movw %es, %ax + subw $TSTLOAD, %ax # have we loaded all yet? + cmpw syssize - _boot, %ax + jbe ok1_read + ret +ok1_read: + movw %cs:sectors - _boot, %ax + subw sread - _boot, %ax + movw %ax, %cx + shlw $9, %cx + addw %bx, %cx + jnc ok2_read + je ok2_read + xorw %ax, %ax + subw %bx, %ax + shrw $9, %ax +ok2_read: + call read_track + movw %ax, %cx + add sread - _boot, %ax + cmpw %cs:sectors - _boot, %ax + jne ok3_read + movw $1, %ax + subw head - _boot, %ax + jne ok4_read + incw track - _boot +ok4_read: + movw %ax, head - _boot + xorw %ax, %ax +ok3_read: + movw %ax, sread - _boot + shlw $9, %cx + addw %cx, %bx + jnc rp_read + movw %es, %ax + addb $0x10, %ah + movw %ax, %es + xorw %bx, %bx + jmp rp_read + +read_track: + pusha + pusha + movw $0xe2e, %ax # loading... message 2e = . + movw $7, %bx + int $0x10 + popa + + movw track - _boot, %dx + movw sread - _boot, %cx + incw %cx + movb %dl, %ch + movw head - _boot, %dx + movb %dl, %dh + andw $0x0100, %dx + movb $2, %ah + + pushw %dx # save for error dump + pushw %cx + pushw %bx + pushw %ax + + int $0x13 + jc bad_rt + addw $8, %sp + popa + ret + +bad_rt: + pushw %ax # save error code + call print_all # ah = error, al = read + + xorb %ah, %ah + xorb %dl, %dl + int $0x13 + + addw $10, %sp + popa + jmp read_track + +/* + * print_all is for debugging purposes. + * It will print out all of the registers. The assumption is that this is + * called from a routine, with a stack frame like + * dx + * cx + * bx + * ax + * error + * ret <- sp + * +*/ + +print_all: + movw $5, %cx # error code + 4 registers + movw %sp, %bp + +print_loop: + pushw %cx # save count left + call print_nl # nl for readability + + cmpb 5, %cl # see if register name is needed + jae no_reg + + movw $(0xe05 + 'A' - 1), %ax + subb %cl, %al + int $0x10 + movb $'X', %al + int $0x10 + movb $':', %al + int $0x10 + +no_reg: + addw $2, %bp # next register + call print_hex # print it + popw %cx + loop print_loop + ret + +print_nl: + movw $0xe0d, %ax # CR + int $0x10 + movb $0x0a, %al # LF + int $0x10 + ret + +/* + * print_hex is for debugging purposes, and prints the word + * pointed to by ss:bp in hexadecmial. +*/ + +print_hex: + movw $4, %cx # 4 hex digits + movw (%bp), %dx # load word into dx + +print_digit: + rolw $4, %dx # rotate so that lowest 4 bits are used + movb $0xe, %ah + movb %dl, %al # mask off so we have only next nibble + andb $0xf, %al + addb $'0', %al # convert to 0-based digit + cmpb $'9', %al # check for overflow + jbe good_digit + addb $('A' - '0' - 10), %al + +good_digit: + int $0x10 + loop print_digit + ret + + +/* + * This procedure turns off the floppy drive motor, so + * that we enter the kernel in a known state, and + * don't have to worry about it later. + */ +kill_motor: + pushw %dx + movw $0x3f2, %dx + xorb %al, %al + outb %al, %dx + popw %dx + ret + +sectors: + .word 0 + +msg1: + .byte 13,10 + .ascii "Loading" + +.org 497 +setup_sects: + .byte SETUPSECS +.org 500 +syssize: + .word _syssize +.org 508 +root_dev: + .word ROOT_DEV +boot_flag: + .word 0xAA55 +_eboot: diff --git a/changelog b/changelog deleted file mode 100644 index 86e7dca..0000000 --- a/changelog +++ /dev/null @@ -1,7 +0,0 @@ -- Added on-fly timings change on some chipsets - (Thanks to Eric and Wee for this part) -- Added i852/855 on-fly timing change -- Added support for VIA K8T890 -- Added a "Fast" Mode (with MTRR & L1/L2 Caches) -- Correct a bug (Disable MTRR for stronger test) -- Some bug fixes \ No newline at end of file diff --git a/config.c b/config.c index 97c81da..1435d6f 100644 --- a/config.c +++ b/config.c @@ -1,28 +1,23 @@ -/* config.c - MemTest-86 Version 3.0 +/* config.c - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. - * By Chris Brady, cbrady@sgi.com + * By Chris Brady * ---------------------------------------------------- - * MemTest86+ V1.30 Specific code (GPL V2.0) + * MemTest86+ V2.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */ - #include "test.h" #include "screen_buffer.h" #include "controller.h" -#include "extra.h" #define ITER 20 extern int bail, beepmode; extern struct tseq tseq[]; -/* extern struct vars *v; */ extern short e820_nr; extern char memsz_mode; -int fast_mode; - -char save[POP_H][POP_W]; +char save[2][POP_H][POP_W]; void get_config() { @@ -34,170 +29,86 @@ void get_config() wait_keyup(); while(!flag) { cprint(POP_Y+1, POP_X+2, "Configuration:"); - cprint(POP_Y+3, POP_X+6, "(1) Cache Mode"); - cprint(POP_Y+4, POP_X+6, "(2) Test Selection"); - cprint(POP_Y+5, POP_X+6, "(3) Address Range"); - cprint(POP_Y+6, POP_X+6, "(4) Memory Sizing"); - cprint(POP_Y+7, POP_X+6, "(5) Error Summary"); - cprint(POP_Y+8, POP_X+6, "(6) Error Report Mode"); - cprint(POP_Y+9, POP_X+6, "(7) ECC Mode"); - cprint(POP_Y+10, POP_X+6, "(8) Restart Test"); + cprint(POP_Y+3, POP_X+6, "(1) Test Selection"); + cprint(POP_Y+4, POP_X+6, "(2) Address Range"); + cprint(POP_Y+5, POP_X+6, "(3) Memory Sizing"); + cprint(POP_Y+6, POP_X+6, "(4) Error Summary"); + cprint(POP_Y+7, POP_X+6, "(5) Error Report Mode"); + cprint(POP_Y+8, POP_X+6, "(6) ECC Mode"); + cprint(POP_Y+9, POP_X+6, "(7) Restart"); + cprint(POP_Y+10, POP_X+6, "(8) Refresh Screen"); cprint(POP_Y+11, POP_X+6, "(9) Adv. Options"); - cprint(POP_Y+12, POP_X+6, "(0) Exit"); + cprint(POP_Y+12,POP_X+6,"(0) Continue"); /* Wait for key release */ /* Fooey! This nuts'es up the serial input. */ sflag = 0; switch(get_key()) { case 2: - /* 1 - Set cache mode */ - popclear(); - cprint(POP_Y+1, POP_X+2, "Cache Mode:"); - cprint(POP_Y+3, POP_X+6, "(1) Test Controlled"); - cprint(POP_Y+4, POP_X+6, "(2) Always On"); - cprint(POP_Y+5, POP_X+6, "(3) Always Off"); - cprint(POP_Y+6, POP_X+6, "(0) Cancel"); - cprint(POP_Y+3+v->cache_flag, POP_X+5, ">"); - wait_keyup(); - while (!sflag) { - switch(get_key()) { - case 2: - /* test controled */ - v->cache_flag = 0; - set_cache(tseq[v->test].cache); - find_ticks(); - sflag++; - break; - case 3: - /* Cache on */ - v->cache_flag = 1; - if (tseq[v->test].cache == 0) { - bail++; - } - set_cache(1); - find_ticks(); - sflag++; - break; - case 4: - /* Cache off */ - v->cache_flag = 2; - if (tseq[v->test].cache == 1) { - bail++; - } - find_ticks(); - sflag++; - break; - case 11: - case 57: - sflag++; - break; - } - } - popclear(); - break; - case 3: - /* 2 - Test Selection */ + /* 1 - Test Selection */ popclear(); cprint(POP_Y+1, POP_X+2, "Test Selection:"); cprint(POP_Y+3, POP_X+6, "(1) Default Tests"); - cprint(POP_Y+4, POP_X+6, "(2) Quick Tests"); - cprint(POP_Y+5, POP_X+6, "(3) Extended Tests"); - cprint(POP_Y+6, POP_X+6, "(4) All Tests"); - cprint(POP_Y+7, POP_X+6, "(5) Skip Current Test"); - cprint(POP_Y+8, POP_X+6, "(6) Select Test"); - cprint(POP_Y+9, POP_X+6, "(7) Print mode"); - cprint(POP_Y+10, POP_X+6, "(0) Cancel"); + cprint(POP_Y+4, POP_X+6, "(2) Skip Current Test"); + cprint(POP_Y+5, POP_X+6, "(3) Select Test"); + cprint(POP_Y+6, POP_X+6, "(4) Select Bit Fade Test"); + cprint(POP_Y+7, POP_X+6, "(0) Continue"); if (v->testsel < 0) { - if (fast_mode == 1) { - cprint(POP_Y+4, POP_X+5, ">"); - } else { - if (v->xtst_flag == 0) { - cprint(POP_Y+3, POP_X+5, ">"); - } else { - cprint(POP_Y+4+v->xtst_flag, POP_X+5, ">"); - } - } + cprint(POP_Y+3, POP_X+5, ">"); } else { - cprint(POP_Y+8, POP_X+5, ">"); + cprint(POP_Y+5, POP_X+5, ">"); } wait_keyup(); while (!sflag) { switch(get_key()) { case 2: /* Default */ - v->xtst_flag = 0; - fast_mode = 0; - if (v->test > DEFTESTS) { + if (v->testsel == 9) { bail++; } v->testsel = -1; find_ticks(); sflag++; - cprint(LINE_INFO, COL_TST, " Std"); + cprint(LINE_INFO, COL_TST, "Std"); break; case 3: - /* Fast */ - v->xtst_flag = 0; - fast_mode = 1; - if (v->test > DEFTESTS) { - bail++; - } - v->testsel = -1; - v->pass = 0; - v->ecount = 0; - find_ticks(); - sflag++; - cprint(LINE_INFO, COL_TST, "Fast"); - break; - case 4: - /* Extended */ - v->xtst_flag = 1; - fast_mode = 0; - if (v->test <= DEFTESTS) { - bail++; - } - v->testsel = -1; - find_ticks(); - sflag++; - cprint(LINE_INFO, COL_TST, " Ext"); - break; - case 5: - /* All */ - fast_mode = 0; - v->xtst_flag = 2; - v->testsel = -1; - find_ticks(); - sflag++; - cprint(LINE_INFO, COL_TST, " All"); - break; - case 6: /* Skip test */ bail++; sflag++; break; - case 7: + case 4: /* Select test */ popclear(); - cprint(POP_Y+1, POP_X+2, + cprint(POP_Y+1, POP_X+3, "Test Selection:"); - cprint(POP_Y+3, POP_X+4, - "Test Number [0-12]: "); - i = getval(POP_Y+3, POP_X+24, 0); - if (i <= 12) { + cprint(POP_Y+4, POP_X+5, + "Test Number [0-9]: "); + i = getval(POP_Y+4, POP_X+24, 0); + if (i <= 9) { if (i != v->testsel) { - v->pass = 0; - v->ecount = 0; + v->pass = -1; + v->test = -1; } v->testsel = i; } - v->test = -1; - v->pass = -1; find_ticks(); sflag++; bail++; - cprint(LINE_INFO, COL_TST, " #"); + cprint(LINE_INFO, COL_TST, "#"); dprint(LINE_INFO, COL_TST+1, i, 2, 1); break; + case 5: + if (v->testsel != 9) { + v->pass = -1; + v->test = -1; + } + v->testsel = 9; + find_ticks(); + sflag++; + bail++; + cprint(LINE_INFO, COL_TST, "#"); + dprint(LINE_INFO, COL_TST+1, 9, 2, 1); + break; case 11: case 57: sflag++; @@ -206,14 +117,14 @@ void get_config() } popclear(); break; - case 4: - /* 3 - Address Range */ + case 3: + /* 2 - Address Range */ popclear(); cprint(POP_Y+1, POP_X+2, "Test Address Range:"); cprint(POP_Y+3, POP_X+6, "(1) Set Lower Limit"); cprint(POP_Y+4, POP_X+6, "(2) Set Upper Limit"); cprint(POP_Y+5, POP_X+6, "(3) Test All Memory"); - cprint(POP_Y+6, POP_X+6, "(0) Cancel"); + cprint(POP_Y+6, POP_X+6, "(0) Continue"); wait_keyup(); while (!sflag) { switch(get_key()) { @@ -266,26 +177,26 @@ void get_config() break; case 11: case 57: - /* 0/CR - Cancel */ + /* 0/CR - Continue */ sflag++; break; } } popclear(); break; - case 5: - /* 4 - Memory Sizing */ + case 4: + /* 3 - Memory Sizing */ popclear(); cprint(POP_Y+1, POP_X+2, "Memory Sizing:"); cprint(POP_Y+3, POP_X+6, "(1) BIOS - Std"); if (e820_nr) { cprint(POP_Y+4, POP_X+6, "(2) BIOS - All"); cprint(POP_Y+5, POP_X+6, "(3) Probe"); - cprint(POP_Y+6, POP_X+6, "(0) Cancel"); + cprint(POP_Y+6, POP_X+6, "(0) Continue"); cprint(POP_Y+2+memsz_mode, POP_X+5, ">"); } else { cprint(POP_Y+4, POP_X+6, "(3) Probe"); - cprint(POP_Y+5, POP_X+6, "(0) Cancel"); + cprint(POP_Y+5, POP_X+6, "(0) Continue"); if (memsz_mode == SZ_MODE_BIOS) { cprint(POP_Y+3, POP_X+5, ">"); } else { @@ -336,15 +247,15 @@ void get_config() break; case 11: case 57: - /* 0/CR - Cancel */ + /* 0/CR - Continue */ sflag++; break; } } popclear(); break; - case 6: - /* 5 - Show error summary */ + case 5: + /* 4 - Show error summary */ popclear(); for (i=0; tseq[i].msg != NULL; i++) { cprint(POP_Y+1+i, POP_X+2, "Test:"); @@ -357,8 +268,8 @@ void get_config() while (get_key() == 0); popclear(); break; - case 7: - /* 6 - Printing Mode */ + case 6: + /* 5 - Printing Mode */ popclear(); cprint(POP_Y+1, POP_X+2, "Printing Mode:"); cprint(POP_Y+3, POP_X+6, "(1) Individual Errors"); @@ -392,24 +303,24 @@ void get_config() /* Set Beep On Error mode */ beepmode = !beepmode; sflag++; - break; + break; case 11: case 57: - /* 0/CR - Cancel */ + /* 0/CR - Continue */ sflag++; break; } } popclear(); break; - case 8: - /* 7 - ECC Polling Mode */ + case 7: + /* 6 - ECC Polling Mode */ popclear(); cprint(POP_Y+1, POP_X+2, "ECC Polling Mode:"); cprint(POP_Y+3, POP_X+6, "(1) Recommended"); cprint(POP_Y+4, POP_X+6, "(2) On"); cprint(POP_Y+5, POP_X+6, "(3) Off"); - cprint(POP_Y+6, POP_X+6, "(0) Cancel"); + cprint(POP_Y+6, POP_X+6, "(0) Continue"); wait_keyup(); while(!sflag) { switch(get_key()) { @@ -427,52 +338,28 @@ void get_config() break; case 11: case 57: - /* 0/CR - Cancel */ + /* 0/CR - Continue */ sflag++; break; } } popclear(); break; - case 9: + case 8: wait_keyup(); restart(); break; - case 10: // experimental extra options - popclear(); - cprint(POP_Y+1, POP_X+2, "Adv. Options :"); - cprint(POP_Y+3, POP_X+5, "(1) Modify Timing "); - cprint(POP_Y+4, POP_X+5, "(2) Reprint Screen"); - cprint(POP_Y+5, POP_X+5, "(0) Cancel "); - wait_keyup(); - while(!sflag) - { - switch(get_key()) - { - case 2: - popclear(); - get_menu(); - case 3: - reprint_screen = 1; - sflag++; - flag++; - break; - //prime(); - case 4: - break; - case 11: - case 57: - /* 0/CR - Cancel */ - sflag++; - break; - } - } - popclear(); + case 9: + reprint_screen = 1; + flag++; + break; + case 10: + get_menu(); break; case 11: case 57: case 28: - /* 0/CR/SP - Cancel */ + /* 0/CR/SP - Continue */ flag++; break; } @@ -495,10 +382,11 @@ void popup() for (i=POP_Y; i>20)&1)?ECC_CORRECT:ECC_NONE; + +} +*/ static void setup_amd76x(void) { @@ -873,9 +884,9 @@ static void poll_fsb_i925(void) { int coef = getP4PMmultiplier(); long *ptr; - /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + dev0 = dev0 & 0xFFFFC000; ptr=(long*)(dev0+0xC00); mchcfg = *ptr & 0xFFFF; dramratio = 1; @@ -899,7 +910,7 @@ static void poll_fsb_i925(void) { } // Compute RAM Frequency - fsb = ((extclock /1000) / coef); + fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio; // Print DRAM Freq @@ -1625,7 +1636,7 @@ static struct pci_memory_controller controllers[] = { { 0x8086, 0x254C, "Intel E7501", 1, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_iE7xxx }, { 0x8086, 0x255d, "Intel E7205", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx }, { 0x8086, 0x2570, "Intel i848/i865", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing }, - { 0x8086, 0x2578, "Intel i875P", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_i875 }, + { 0x8086, 0x2578, "Intel i875P", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_i875 }, { 0x8086, 0x2550, "Intel E7505", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx }, { 0x8086, 0x3580, "Intel ", 0, poll_fsb_i855, poll_timings_i852, setup_nothing, poll_nothing }, { 0x8086, 0x3340, "Intel i855PM", 0, poll_fsb_i855, poll_timings_i855, setup_nothing, poll_nothing }, diff --git a/head.S b/head.S index 28772c3..49a3e3d 100644 --- a/head.S +++ b/head.S @@ -329,6 +329,20 @@ have_cpuid: movl $1, %eax # Use the CPUID instruction to get CPU type cpuid + + # + # CDH start + # Check FPU, initialize if present + # + testl $1, %edx # FPU available? + jz no_fpu + finit + + no_fpu: + # + # CDH end + # + movb %al, %cl # save reg for future use andb $0x0f, %ah # mask processor family movb %ah, X86(%esi) diff --git a/init.c b/init.c old mode 100755 new mode 100644 index 6a61c76..28000fc --- a/init.c +++ b/init.c @@ -3,7 +3,7 @@ * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com * ---------------------------------------------------- - * MemTest86+ V1.30 Specific code (GPL V2.0) + * MemTest86+ V1.40 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */ @@ -52,7 +52,7 @@ static void display_init(void) for(i=0, pp=(char *)(SCREEN_ADR+1); iclks_msec = end_low/48; + v->clks_msec = end_low/50; return(v->clks_msec); } diff --git a/lib.c b/lib.c index 148f932..05b8371 100644 --- a/lib.c +++ b/lib.c @@ -403,22 +403,12 @@ void set_cache(int val) } switch(val) { case 0: - if (fast_mode != 1) { - cache_off(); - if (v->cache_flag) { - cprint(LINE_INFO, COL_CACHE, "OFF"); - } else { - cprint(LINE_INFO, COL_CACHE, "off"); - } - } + cache_off(); + cprint(LINE_INFO, COL_CACHE, "off"); break; case 1: cache_on(); - if (v->cache_flag) { - cprint(LINE_INFO, COL_CACHE, " ON"); - } else { - cprint(LINE_INFO, COL_CACHE, " on"); - } + cprint(LINE_INFO, COL_CACHE, " on"); break; } } diff --git a/main.c b/main.c index 77182a9..ac970bc 100644 --- a/main.c +++ b/main.c @@ -1,30 +1,27 @@ -/* main.c - MemTest-86 Version 3.0 +/* main.c - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. - * By Chris Brady, cbrady@sgi.com + * By Chris Brady */ + #include "test.h" #include "defs.h" #undef TEST_TIMES +#define DEFTESTS 9 extern void bzero(); -extern int fast_mode; const struct tseq tseq[] = { {0, 5, 3, 0, 0, "[Address test, walking ones, no cache]"}, - {1, 0, 3, 14, 0, "[Moving inv, ones & zeros, cached] "}, - {0, 6, 3, 2, 0, "[Address test, own address, no cache] "}, - {1, 1, 2, 80, 0, "[Moving inv, 8 bit pattern, cached] "}, - {1, 2, 2, 320, 0, "[Moving inv, 32 bit pattern, cached] "}, - {1, 7, 64, 66, 0, "[Block move, 64 moves, cached] "}, - {1, 3, 4, 240, 0, "[Modulo 20, ones & zeros, cached] "}, - {0, 0, 2, 10, 0, "[Moving inv, ones & zeros, no cache] "}, - - {1, 7, 512, 514, 0,"[Block move, 512 moves, cached] "}, - {0, 1, 2, 80, 0, "[Moving inv, 8 bit pattern, no cache] "}, - {1, 4, 2, 1280, 0, "[Modulo 20, 8 bit pattern , cached] "}, - {0, 2, 2, 320, 0, "[Moving inv, 32 bit pattern, no cache]"}, - {1, 8, 1, 1, 0, "[Bit fade test, 90 min, 2 patterns] "}, + {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, 0, 0, 0, 0, NULL} }; @@ -208,32 +205,7 @@ void do_test(void) #endif /* Now setup the test parameters based on the current test number */ /* Figure out the next test to run */ - if (v->testsel < 0) { - switch(v->xtst_flag) { - case 0: /* Default tests */ - if (v->test > DEFTESTS) { - goto skip_test; - } - break; - case 1: /* Extended tests */ - if ((v->test <= DEFTESTS) || (v->test > DEFTESTS2)) { - goto skip_test; - } - break; - case 2: /* All tests */ - if (v->test > DEFTESTS2) { - goto skip_test; - } - break; - } - - /* May skip this test if the cache settings have been */ - /* overridden */ - if ((v->cache_flag == 1 && tseq[v->test].cache == 0) || - (v->cache_flag == 2 && tseq[v->test].cache == 1)) { - goto skip_test; - } - } else { + if (v->testsel >= 0) { v->test = v->testsel; } dprint(LINE_TST, COL_MID+6, v->test, 2, 1); @@ -265,6 +237,7 @@ void do_test(void) p2 = p1; p1 = ~p2; movinv1(tseq[v->test].iter,p1,p2); + BAILOUT; break; case 1: /* Moving inversions, 8 bit wide walking ones and zeros. */ @@ -323,23 +296,41 @@ void do_test(void) modtst(i, tseq[v->test].iter, p1, p2); BAILOUT } - 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(); } + 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: @@ -394,7 +385,7 @@ void do_test(void) window = 0; cprint(LINE_PAT, COL_PAT-3, " "); /* If this was the last test then we finished a pass */ - if (tseq[v->test].msg == NULL || v->testsel >= 0) { + if (v->test >= DEFTESTS || v->testsel >= 0) { v->pass++; dprint(LINE_INFO, COL_PASS, v->pass, 5, 0); v->test = 0; @@ -414,12 +405,13 @@ void restart() int i; volatile char *pp; - /* clear all of the variables */ + /* clear variables */ firsttime = 0; - fast_mode = 0; - for (i=0, pp=(char *)v; itest = 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) { @@ -448,24 +440,13 @@ void find_ticks(void) } compute_segments(window); window = 0; - for (v->pass_ticks=0, i=0; tseq[i].msg != NULL; i++) { + for (v->pass_ticks=0, i=0; itestsel >= 0) { if (i != v->testsel) { continue; } - } else { - if (v->xtst_flag == 0 && i > DEFTESTS) { - break; - } - if (v->xtst_flag == 1 && i <= DEFTESTS) { - continue; - } - if ((v->cache_flag == 1 && tseq[i].cache == 0) || - (v->cache_flag == 2 && tseq[i].cache == 1)) { - continue; - } } v->pass_ticks += find_ticks_for_test(chunks, i); } @@ -566,5 +547,3 @@ static void compute_segments(int win) } } } - - diff --git a/makeiso.sh b/makeiso.sh new file mode 100755 index 0000000..580df07 --- /dev/null +++ b/makeiso.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# check to see if the correct tools are installed +for X in wc mkisofs +do + if [ "$(which $X)" = "" ]; then + echo "makeiso.sh error: $X is not in your path." >&2 + exit 1 + elif [ ! -x $(which $X) ]; then + echo "makeiso.sh error: $X is not executable." >&2 + exit 1 + fi +done + +#check to see if memtest.bin is present +if [ ! -w memtest.bin ]; then + echo "makeiso.sh error: cannot find memtest.bin, did you compile it?" >&2 + exit 1 +fi + +# enlarge the size of memtest.bin +SIZE=$(wc -c memtest.bin | awk '{print $1}') +FILL=$((1474560 - $SIZE)) +dd if=/dev/zero of=fill.tmp bs=$FILL count=1 +cat memtest.bin fill.tmp >memtest.img +rm -f fill.tmp + +echo "generating iso image ..." + +mkdir "cd" +mkdir "cd/boot" +mv memtest.img cd/boot +cd cd +mkisofs -b boot/memtest.img -c boot/boot.catalog -o memtest.iso . +mv memtest.iso .. +cd .. +rm -rf cd + +echo "done" diff --git a/memsize.c b/memsize.c index a0947b0..2447a29 100644 --- a/memsize.c +++ b/memsize.c @@ -1,7 +1,7 @@ -/* memsize.c - MemTest-86 Version 3.0 +/* memsize.c - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. - * By Chris Brady, cbrady@sgi.com + * By Chris Brady */ #include "test.h" @@ -20,7 +20,6 @@ extern ulong p1, p2; extern volatile ulong *p; static void sort_pmap(void); -static void sanitize_pmap(void); static int check_ram(void); static void memsize_bios(int res); static void memsize_820(int res); @@ -71,7 +70,6 @@ void mem_size(void) } /* Guarantee that pmap entries are in ascending order */ sort_pmap(); - sanitize_pmap(); v->plim_lower = 0; v->plim_upper = v->pmap[v->msegs-1].end; @@ -113,62 +111,6 @@ static void sort_pmap(void) } } } - -static void remove_pmap_region(unsigned long res_start, unsigned long res_end) -{ - /* Ensure a range of addresses is absent from the pmap */ - int i; - for(i = 0; i < v->msegs; i++) { - unsigned long start, end; - start = v->pmap[i].start; - end = v->pmap[i].end; - if ((start < res_start) && (end > res_start)) { - /* If the tail of the range overlaps the region, truncate it */ - v->pmap[i].end = res_start; - if ((end > res_end) && (v->msegs < MAX_MEM_SEGMENTS)) { - /* If the tail extends past the end of the region - * insert a new pmap entry for the tail. - */ - memmove(&v->pmap[i+2], &v->pmap[i + 1], - ((v->msegs - 1) - i) *sizeof(v->pmap[0])); - v->msegs += 1; - i += 1; - start = res_start; - v->pmap[i].start = start; - v->pmap[i].end = end; - } - else { - end = res_start; - } - } - if ((start >= res_start) && (end <= res_end)) { - /* If the range is completely contained in the region remove it */ - memmove(&v->pmap[i], &v->pmap[i+1], - ((v->msegs - 1) - i) * sizeof(v->pmap[0])); - v->msegs -= 1; - i -= 1; - } - else if ((start < res_end) && (end > res_end)) { - /* If the start is in the middle of the region increment it */ - start = res_end; - v->pmap[i].start = start; - } - } -} - -static void sanitize_pmap(void) -{ - /* Remove any questionable addresses from the memory map */ - /* Unless we really trust the BIOS don't test 640-1M */ - if (firmware != FIRMWARE_LINUXBIOS) { - remove_pmap_region(RES_START >> 12 , (RES_END + 4095) >> 12); - } - /* Never test where our video buffer lives */ - remove_pmap_region(SCREEN_ADR >> 12, (SCREEN_END_ADR + 4095) >> 12); -} - - - static void memsize_linuxbios(void) { int i, n; @@ -213,6 +155,16 @@ static void memsize_820(int res) start = nm[i].addr; end = start + nm[i].size; + /* Don't ever use memory between 640 and 1024k */ + if (start > RES_START && start < RES_END) { + if (end < RES_END) { + continue; + } + start = RES_END; + } + if (end > RES_START && end < RES_END) { + end = RES_START; + } v->pmap[n].start = (start + 4095) >> 12; v->pmap[n].end = end >> 12; v->test_pages += v->pmap[n].end - v->pmap[n].start; diff --git a/memtest.bin.lds b/memtest.bin.lds index 702cdb1..699d2aa 100644 --- a/memtest.bin.lds +++ b/memtest.bin.lds @@ -1,15 +1,15 @@ -OUTPUT_FORMAT("binary") -OUTPUT_ARCH("i386") - -ENTRY(_main); -SECTIONS { - . = 0; - .bootsect : { *(.bootsect) } - .setup : { *(.setup) } - .memtest : { - _start = . ; - *(.data) - _end = . ; - } - _syssize = (_end - _start + 15) >> 4; -} +OUTPUT_FORMAT("binary") +OUTPUT_ARCH("i386") + +ENTRY(_main); +SECTIONS { + . = 0; + .bootsect : { *(.bootsect) } + .setup : { *(.setup) } + .memtest : { + _start = . ; + *(.data) + _end = . ; + } + _syssize = (_end - _start + 15) >> 4; +} diff --git a/memtest.lds b/memtest.lds index bbb190a..1d661b3 100644 --- a/memtest.lds +++ b/memtest.lds @@ -1,11 +1,11 @@ -OUTPUT_FORMAT("elf32-i386"); -OUTPUT_ARCH(i386); - -ENTRY(_start); -SECTIONS { - . = 0x10000; - _start = . ; - .data : { - *(.data) - } -} +OUTPUT_FORMAT("elf32-i386"); +OUTPUT_ARCH(i386); + +ENTRY(_start); +SECTIONS { + . = 0x10000; + _start = . ; + .data : { + *(.data) + } +} diff --git a/memtest_shared.lds b/memtest_shared.lds index dc88711..d4576a2 100644 --- a/memtest_shared.lds +++ b/memtest_shared.lds @@ -1,52 +1,52 @@ -OUTPUT_FORMAT("elf32-i386"); -OUTPUT_ARCH(i386); - -ENTRY(startup_32); -SECTIONS { - . = 0; - .text : { - _start = .; - *(.text) - *(.text.*) - *(.plt) - _etext = . ; - } = 0x9090 - .rodata : { - *(.rodata) - *(.rodata.*) - } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .hash : { *(.hash) } - .dynamic : { *(.dynamic) } - - .rel.text : { *(.rel.text .rel.text.*) } - .rel.rodata : { *(.rel.rodata .rel.rodata.*) } - .rel.data : { *(.rel.data .rel.data.*) } - .rel.got : { *(.rel.got .rel.got.*) } - .rel.plt : { *(.rel.plt .rel.plt.*) } - - . = ALIGN(4); - .data : { - _data = .; - *(.data) - *(.data.*) - } - .got : { - *(.got.plt) - *(.got) - _edata = . ; - } - . = ALIGN(4); - .bss : { - _bss = .; - *(.dynbss) - *(.bss) - *(.bss.*) - *(COMMON) - /* _end must be at least 256 byte aligned */ - . = ALIGN(256); - _end = .; - } - /DISCARD/ : { *(*) } -} +OUTPUT_FORMAT("elf32-i386"); +OUTPUT_ARCH(i386); + +ENTRY(startup_32); +SECTIONS { + . = 0; + .text : { + _start = .; + *(.text) + *(.text.*) + *(.plt) + _etext = . ; + } = 0x9090 + .rodata : { + *(.rodata) + *(.rodata.*) + } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .hash : { *(.hash) } + .dynamic : { *(.dynamic) } + + .rel.text : { *(.rel.text .rel.text.*) } + .rel.rodata : { *(.rel.rodata .rel.rodata.*) } + .rel.data : { *(.rel.data .rel.data.*) } + .rel.got : { *(.rel.got .rel.got.*) } + .rel.plt : { *(.rel.plt .rel.plt.*) } + + . = ALIGN(4); + .data : { + _data = .; + *(.data) + *(.data.*) + } + .got : { + *(.got.plt) + *(.got) + _edata = . ; + } + . = ALIGN(4); + .bss : { + _bss = .; + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + /* _end must be at least 256 byte aligned */ + . = ALIGN(256); + _end = .; + } + /DISCARD/ : { *(*) } +} diff --git a/mt86+_loader.asm b/mt86+_loader.asm index 4eab61e..be83381 100644 --- a/mt86+_loader.asm +++ b/mt86+_loader.asm @@ -12,8 +12,8 @@ ; The good thing is that you get a single file which can be ; compressed, for example with http://upx.sf.net/ (UPX). -%define fullsize (99516 + buffer - exeh) - ; 995126 is the size of memtest86+ V1.30, adjust as needed! +%define fullsize (95352 + buffer - exeh) + ; 95352 is the size of memtest86+ V1.40, adjust as needed! %define stacksize 2048 %define stackpara ((stacksize + 15) / 16) diff --git a/mt86+_loader.bin b/mt86+_loader.bin index 6dc11aa..1725ec7 100644 Binary files a/mt86+_loader.bin and b/mt86+_loader.bin differ diff --git a/precomp.bin b/precomp.bin index 8838740..052eff0 100755 Binary files a/precomp.bin and b/precomp.bin differ diff --git a/random.c b/random.c new file mode 100644 index 0000000..a0a19c7 --- /dev/null +++ b/random.c @@ -0,0 +1,31 @@ +/* concatenation of following two 16-bit multiply with carry generators */ +/* x(n)=a*x(n-1)+carry mod 2^16 and y(n)=b*y(n-1)+carry mod 2^16, */ +/* number and carry packed within the same 32 bit integer. */ +/******************************************************************/ + +unsigned int rand( void ); /* returns a random 32-bit integer */ +void rand_seed( unsigned int, unsigned int ); /* seed the generator */ + +/* return a random float >= 0 and < 1 */ +#define rand_float ((double)rand() / 4294967296.0) + +static unsigned int SEED_X = 521288629; +static unsigned int SEED_Y = 362436069; + + +unsigned int rand () + { + static unsigned int a = 18000, b = 30903; + + SEED_X = a*(SEED_X&65535) + (SEED_X>>16); + SEED_Y = b*(SEED_Y&65535) + (SEED_Y>>16); + + return ((SEED_X<<16) + (SEED_Y&65535)); + } + + +void rand_seed( unsigned int seed1, unsigned int seed2 ) + { + if (seed1) SEED_X = seed1; /* use default seeds if parameter is 0 */ + if (seed2) SEED_Y = seed2; + } diff --git a/setup.S b/setup.S index 9a3450f..2e1cfa6 100644 --- a/setup.S +++ b/setup.S @@ -1,115 +1,115 @@ -/* - * setup.s is responsible for getting the system data from the BIOS, - * and putting them into the appropriate places in system memory. - * both setup.s and system has been loaded by the bootblock. - * - * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86. - */ - -#define __ASSEMBLY__ -#include "defs.h" - -.code16 -.section ".setup", "ax", @progbits -.globl start -start: -# ok, the read went well -# now we want to move to protected mode ... - - - cli # no interrupts allowed # - movb $0x80, %al # disable NMI for the bootup sequence - outb %al, $0x70 - -# The system will move itself to its rightful place. - - push %cs - pop %ds - lidt idt_48 - start # load idt with 0,0 - lgdt gdt_48 - start # load gdt with whatever appropriate - -# that was painless, now we enable A20 - - call empty_8042 - - movb $0xD1, %al # command write - outb %al, $0x64 - call empty_8042 - - movb $0xDF, %al # A20 on - outb %al, $0x60 - call empty_8042 - -/* - * Note that the short jump isn't strictly needed, althought there are - * reasons why it might be a good idea. It won't hurt in any case. - */ - movw $0x0001, %ax # protected mode (PE) bit - lmsw %ax # This is it# - jmp flush_instr -flush_instr: - movw $KERNEL_DS, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - movw %ax, %fs - movw %ax, %gs - -data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs) - -/* - * This routine checks that the keyboard command queue is empty - * (after emptying the output buffers) - * - * No timeout is used - if this hangs there is something wrong with - * the machine, and we probably couldn't proceed anyway. - */ -empty_8042: - call delay - inb $0x64, %al # 8042 status port - testb $1, %al # output buffer? - jz no_output - call delay - inb $0x60, %al # read it - jmp empty_8042 - -no_output: - testb $2, %al # is input buffer full? - jnz empty_8042 # yes - loop - ret -# -# Delay is needed after doing i/o -# -delay: - .word 0x00eb # jmp $+2 - ret - -gdt: - .word 0,0,0,0 # dummy - - .word 0,0,0,0 # unused - - .word 0x7FFF # limit 128mb - .word 0x0000 # base address=0 - .word 0x9A00 # code read/exec - .word 0x00C0 # granularity=4096, 386 - - .word 0x7FFF # limit 128mb - .word 0x0000 # base address=0 - .word 0x9200 # data read/write - .word 0x00C0 # granularity=4096, 386 - -idt_48: - .word 0 # idt limit=0 - .long 0 # idt base=0L - -gdt_48: - .word 0x800 # gdt limit=2048, 256 GDT entries - .word 512+gdt - start,0x9 # gdt base = 0X9xxxx - -msg1: - .asciz "Setup.S\r\n" - - /* Pad setup to the proper size */ - .org (SETUPSECS*512) - +/* + * setup.s is responsible for getting the system data from the BIOS, + * and putting them into the appropriate places in system memory. + * both setup.s and system has been loaded by the bootblock. + * + * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86. + */ + +#define __ASSEMBLY__ +#include "defs.h" + +.code16 +.section ".setup", "ax", @progbits +.globl start +start: +# ok, the read went well +# now we want to move to protected mode ... + + + cli # no interrupts allowed # + movb $0x80, %al # disable NMI for the bootup sequence + outb %al, $0x70 + +# The system will move itself to its rightful place. + + push %cs + pop %ds + lidt idt_48 - start # load idt with 0,0 + lgdt gdt_48 - start # load gdt with whatever appropriate + +# that was painless, now we enable A20 + + call empty_8042 + + movb $0xD1, %al # command write + outb %al, $0x64 + call empty_8042 + + movb $0xDF, %al # A20 on + outb %al, $0x60 + call empty_8042 + +/* + * Note that the short jump isn't strictly needed, althought there are + * reasons why it might be a good idea. It won't hurt in any case. + */ + movw $0x0001, %ax # protected mode (PE) bit + lmsw %ax # This is it# + jmp flush_instr +flush_instr: + movw $KERNEL_DS, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + +data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs) + +/* + * This routine checks that the keyboard command queue is empty + * (after emptying the output buffers) + * + * No timeout is used - if this hangs there is something wrong with + * the machine, and we probably couldn't proceed anyway. + */ +empty_8042: + call delay + inb $0x64, %al # 8042 status port + testb $1, %al # output buffer? + jz no_output + call delay + inb $0x60, %al # read it + jmp empty_8042 + +no_output: + testb $2, %al # is input buffer full? + jnz empty_8042 # yes - loop + ret +# +# Delay is needed after doing i/o +# +delay: + .word 0x00eb # jmp $+2 + ret + +gdt: + .word 0,0,0,0 # dummy + + .word 0,0,0,0 # unused + + .word 0x7FFF # limit 128mb + .word 0x0000 # base address=0 + .word 0x9A00 # code read/exec + .word 0x00C0 # granularity=4096, 386 + + .word 0x7FFF # limit 128mb + .word 0x0000 # base address=0 + .word 0x9200 # data read/write + .word 0x00C0 # granularity=4096, 386 + +idt_48: + .word 0 # idt limit=0 + .long 0 # idt base=0L + +gdt_48: + .word 0x800 # gdt limit=2048, 256 GDT entries + .word 512+gdt - start,0x9 # gdt base = 0X9xxxx + +msg1: + .asciz "Setup.S\r\n" + + /* Pad setup to the proper size */ + .org (SETUPSECS*512) + diff --git a/stdin.h b/stdin.h deleted file mode 100644 index e3a08e1..0000000 --- a/stdin.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef I386_STDINT_H -#define I386_STDINT_H - -/* Exact integral types */ -typedef unsigned char uint8_t; -typedef signed char int8_t; - -typedef unsigned short uint16_t; -typedef signed short int16_t; - -typedef unsigned int uint32_t; -typedef signed int int32_t; - -typedef unsigned long long uint64_t; -typedef signed long long int64_t; - -/* Small types */ -typedef unsigned char uint_least8_t; -typedef signed char int_least8_t; - -typedef unsigned short uint_least16_t; -typedef signed short int_least16_t; - -typedef unsigned int uint_least32_t; -typedef signed int int_least32_t; - -typedef unsigned long long uint_least64_t; -typedef signed long long int_least64_t; - -/* Fast Types */ -typedef unsigned char uint_fast8_t; -typedef signed char int_fast8_t; - -typedef unsigned int uint_fast16_t; -typedef signed int int_fast16_t; - -typedef unsigned int uint_fast32_t; -typedef signed int int_fast32_t; - -typedef unsigned long long uint_fast64_t; -typedef signed long long int_fast64_t; - -/* Types for `void *' pointers. */ -typedef int intptr_t; -typedef unsigned int uintptr_t; - -/* Largest integral types */ -typedef long long int intmax_t; -typedef unsigned long long uintmax_t; - - -#endif /* I386_STDINT_H */ \ No newline at end of file diff --git a/stdint.h b/stdint.h new file mode 100644 index 0000000..58d7519 --- /dev/null +++ b/stdint.h @@ -0,0 +1,52 @@ +#ifndef I386_STDINT_H +#define I386_STDINT_H + +/* Exact integral types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +/* Small types */ +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; + +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; + +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +typedef unsigned long long uint_least64_t; +typedef signed long long int_least64_t; + +/* Fast Types */ +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; + +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; + +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +typedef unsigned long long uint_fast64_t; +typedef signed long long int_fast64_t; + +/* Types for `void *' pointers. */ +typedef int intptr_t; +typedef unsigned int uintptr_t; + +/* Largest integral types */ +typedef long long int intmax_t; +typedef unsigned long long uintmax_t; + + +#endif /* I386_STDINT_H */ diff --git a/test.c b/test.c index f5075b8..1da798c 100644 --- a/test.c +++ b/test.c @@ -1,8 +1,14 @@ -/* test.c - MemTest-86 Version 3.0 + +/* test.c - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com + * ---------------------------------------------------- + * MemTest86+ V2.00 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 @@ -111,8 +117,8 @@ void addr_tst1() mask = mask << 1; } while(mask); } - if (p + bank > p) { - p += bank; + if (p + bank/4 > p) { + p += bank/4; } else { p = end; } @@ -243,6 +249,162 @@ void addr_tst2() } } +/* + * 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; jmap[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; jmap[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. @@ -438,10 +600,10 @@ void movinv1(int iter, ulong p1, ulong p2) void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) { - int i, j, k=0, n = 0, done; + int i, j, k=0, done; volatile ulong *pe; volatile ulong *start, *end; - ulong pat, p3; + ulong pat = 0, p3; p3 = sval << 31; @@ -616,13 +778,12 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) /* Since we already adjusted k and the pattern this * code backs both up one step */ - if (--k < 0) { - k = 31; - } - for (pat = lb, n = 0; n < k; n++) { - pat = pat << 1; - pat |= sval; - } + pat = lb; + if ( 0 != (k = (k-1) & 31) ) { + pat = (pat << k); + if ( sval ) + pat |= ((sval << k) - 1); + } k++; for (j=segs-1; j>=0; j--) { start = v->map[j].start; @@ -731,9 +892,9 @@ void modtst(int offset, int iter, ulong p1, ulong p2) volatile ulong *start, *end; /* Display the current pattern */ - hprint(LINE_PAT, COL_PAT-2, p1); + hprint(LINE_PAT, COL_PAT-2, p1); cprint(LINE_PAT, COL_PAT+6, "-"); - dprint(LINE_PAT, COL_PAT+7, offset, 2, 1); + dprint(LINE_PAT, COL_PAT+7, offset, 2, 1); /* Write every nth location with pattern */ for (j=0; jpass_ticks += (STIME * 2); + /* Do -1 and 0 patterns */ p1 = 0; while (1) { @@ -1147,7 +1315,7 @@ void bit_fade() BAILR } /* Snooze for 90 minutes */ - sleep (5400, 0); + sleep (STIME, 0); /* Make sure that nothing changed while sleeping */ for (j=0; jeadr && xor == v->exor) { print_err_counts(); - dprint(v->msg_line, 62, ++ecount, 5, 0); + dprint(v->msg_line, 66, ++ecount, 5, 0); return; } print_err(adr, good, bad, xor); @@ -1272,11 +1441,9 @@ void ad_err2(ulong *adr, ulong bad) } void print_hdr(void) { - static int header = -1; - if (header == 1) { + if ((v->ecount)>1) { return; } - header = 1; cprint(LINE_HEADER, 0, "Tst Pass Failing Address Good Bad Err-Bits Count Chan"); cprint(LINE_HEADER+1, 0,"--- ---- ----------------------- -------- -------- -------- ----- ----"); } @@ -1295,8 +1462,22 @@ static void update_err_counts(void) static void print_err_counts(void) { + int i; + char *pp; + dprint(LINE_INFO, COL_ERR, v->ecount, 6, 0); dprint(LINE_INFO, COL_ECC_ERR, v->ecc_ecount, 6, 0); + + /* Paint the error messages on the screen red to provide a vivid */ + /* indicator that an error has occured */ + if (v->msg_line < 24) { + for(i=0, pp=(char *)((SCREEN_ADR+v->msg_line*160+1)); + i<76; i++, pp+=2) { + *pp = 0x47; + } + } + + } static void common_err(ulong page, ulong offset) @@ -1304,13 +1485,11 @@ static void common_err(ulong page, ulong offset) ulong mb; /* Check for keyboard input */ + print_hdr(); check_input(); - + scroll(); print_err_counts(); - print_hdr(); - - scroll(); mb = page >> 8; dprint(v->msg_line, 0, v->test, 3, 0); dprint(v->msg_line, 4, v->pass, 5, 0); @@ -1428,8 +1607,10 @@ void do_tick(void) ulong h, l, t; /* FIXME only print serial error messages from the tick handler */ + if (v->ecount) { print_err_counts(); - + } + nticks++; v->total_ticks++; diff --git a/test.h b/test.h index bdc9378..a09fb1f 100644 --- a/test.h +++ b/test.h @@ -1,13 +1,14 @@ -/* test.h - MemTest-86 Version 3.0 +/* test.h - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. - * By Chris Brady, cbrady@sgi.com + * By Chris Brady * ---------------------------------------------------- - * MemTest86+ V1.30 Specific code (GPL V2.0) + * MemTest86+ V2.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */ + #define E88 0x00 #define E801 0x04 #define E820NR 0x08 /* # entries in E820MAP */ @@ -39,8 +40,6 @@ struct mem_info_t { typedef unsigned long ulong; #define SPINSZ 0x800000 -#define DEFTESTS 7 -#define DEFTESTS2 11 #define MOD_SZ 20 #define BAILOUT if (bail) goto skip_test; #define BAILR if (bail) return; @@ -70,14 +69,13 @@ typedef unsigned long ulong; #define COL_ERR 63 #define COL_ECC_ERR 72 #define LINE_HEADER 12 -#define LINE_SCROLL 14 +#define LINE_SCROLL 14 #define BAR_SIZE (78-COL_MID-9) #define POP_W 30 -#define POP_H 13 -#define POP_X 16 -// #define POP_X (80-POP_W-2)/2 -#define POP_Y 10 +#define POP_H 15 +#define POP_X 16 +#define POP_Y 8 #define NULL 0 /* memspeed operations */ @@ -111,12 +109,15 @@ void xprint(int y,int x,ulong val); void aprint(int y,int x,ulong page); void dprint(int y,int x,ulong val,int len, int right); void movinv1(int iter, ulong p1, ulong p2); +void movinvr(); void movinv32(int iter, ulong p1, ulong lb, ulong mb, int sval, int off); void modtst(int off, int iter, ulong p1, ulong p2); void error(ulong* adr, ulong good, ulong bad); void ad_err1(ulong *adr1, ulong *adr2, ulong good, ulong bad); void ad_err2(ulong *adr, ulong bad); void do_tick(void); +void rand_seed(int seed1, int seed2); +ulong rand(); void init(void); struct eregs; void inter(struct eregs *trap_regs); @@ -128,6 +129,7 @@ void popup(void); void popdown(void); void popclear(void); void get_config(void); +void get_menu(void); void get_printmode(void); void addr_tst1(void); void addr_tst2(void); @@ -170,52 +172,32 @@ struct pair { static inline void cache_off(void) { - asm( - "pusha\n\t" + asm( + "push %eax\n\t" "movl %cr0,%eax\n\t" - "orl $0x40000000,%eax\n\t" /* Set CD */ - "andl $0x6FFFFFFF,%eax\n\t" /* Clear NW */ - "movl %eax,%cr0\n\t" /* Set CR0 */ - "wbinvd\n\t" /* Invalidate Cache */ - "movl $0x01, %eax\n\t" /* Put 1 in eax */ - "cpuid\n\t" /* cpuid */ - "andl $0x01000, %edx\n\t" /* MTRR available ? */ - "jz CB1\n\t" /* No, go to end */ - "movl $0x02FF, %ecx\n\t" /* Yes, disable it */ - "rdmsr\n\t" - "andl $0xFFFFF3FF,%eax\n\t" - "wrmsr\n\t" + "orl $0x40000000,%eax\n\t" /* Set CD */ + "movl %eax,%cr0\n\t" "wbinvd\n\t" - "CB1:\n\t" - "popa\n\t"); + "pop %eax\n\t"); } static inline void cache_on(void) { - asm( - "pusha\n\t" + asm( + "push %eax\n\t" "movl %cr0,%eax\n\t" - "andl $0x9fffffff,%eax\n\t" /* Clear CD and NW */ - "movl %eax,%cr0\n\t" - "movl $0x01, %eax\n\t" /* Put 1 in eax */ - "cpuid\n\t" /* cpuid */ - "andl $0x01000, %edx\n\t" /* MTRR available ? */ - "jz CB2\n\t" /* No, go to end */ - "movl $0x02FF, %ecx\n\t" /* Yes, enable it */ - "rdmsr\n\t" - "orl $0x0C00,%eax\n\t" - "wrmsr\n\t" - "CB2:\n\t" - "popa\n\t"); + "andl $0x9fffffff,%eax\n\t" /* Clear CD and NW */ + "movl %eax,%cr0\n\t" + "pop %eax\n\t"); } static inline void reboot(void) { asm( "movl %cr0,%eax\n\t" - "andl $0x00000011,%eax\n\t" - "orl $0x60000000,%eax\n\t" - "movl %eax,%cr0\n\t" - "movl %eax,%cr3\n\t" + "andl $0x00000011,%eax\n\t" + "orl $0x60000000,%eax\n\t" + "movl %eax,%cr0\n\t" + "movl %eax,%cr3\n\t" "movl %cr0,%ebx\n\t" "andl $0x60000000,%ebx\n\t" "jz f\n\t" @@ -276,8 +258,6 @@ struct vars { int ecount; int ecc_ecount; int msegs; - int cache_flag; - int xtst_flag; int testsel; int scroll_start; int rdtsc; @@ -286,7 +266,7 @@ struct vars { int total_ticks; int pptr; int tptr; - int beepmode; + int beepmode; struct pmap pmap[MAX_MEM_SEGMENTS]; struct mmap map[MAX_MEM_SEGMENTS]; ulong plim_lower; @@ -296,7 +276,7 @@ struct vars { ulong startl; ulong snaph; ulong snapl; - ulong extclock; + ulong extclock; int printmode; int numpatn; struct pair patn [BADRAM_MAXPATNS]; -- cgit v1.2.3-55-g7522