diff options
author | Michael Brown | 2009-09-18 05:37:36 +0200 |
---|---|---|
committer | Michael Brown | 2012-07-09 16:41:25 +0200 |
commit | 87e047292b0d563504fe4162596b11be132cbf1a (patch) | |
tree | b824296717675ecfcd825cb5229dcedd2269b7e8 | |
parent | [import] Import version 1.30 (diff) | |
download | memtest86-87e047292b0d563504fe4162596b11be132cbf1a.tar.gz memtest86-87e047292b0d563504fe4162596b11be132cbf1a.tar.xz memtest86-87e047292b0d563504fe4162596b11be132cbf1a.zip |
[import] Import version 1.40
http://www.memtest.org/download/1.40/memtest86+-1.40.tar.gz
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | README | 1663 | ||||
-rw-r--r-- | README.build-process | 78 | ||||
-rw-r--r-- | bootsect.S | 750 | ||||
-rw-r--r-- | changelog | 7 | ||||
-rw-r--r-- | config.c | 264 | ||||
-rw-r--r-- | controller.c | 19 | ||||
-rw-r--r-- | head.S | 14 | ||||
-rw-r--r--[-rwxr-xr-x] | init.c | 12 | ||||
-rw-r--r-- | lib.c | 16 | ||||
-rw-r--r-- | main.c | 109 | ||||
-rwxr-xr-x | makeiso.sh | 39 | ||||
-rw-r--r-- | memsize.c | 72 | ||||
-rw-r--r-- | memtest.bin.lds | 30 | ||||
-rw-r--r-- | memtest.lds | 22 | ||||
-rw-r--r-- | memtest_shared.lds | 104 | ||||
-rw-r--r-- | mt86+_loader.asm | 4 | ||||
-rw-r--r-- | mt86+_loader.bin | bin | 784 -> 784 bytes | |||
-rwxr-xr-x | precomp.bin | bin | 99516 -> 95352 bytes | |||
-rw-r--r-- | random.c | 31 | ||||
-rw-r--r-- | setup.S | 230 | ||||
-rw-r--r-- | stdint.h (renamed from stdin.h) | 2 | ||||
-rw-r--r-- | test.c | 231 | ||||
-rw-r--r-- | test.h | 76 |
24 files changed, 1939 insertions, 1839 deletions
@@ -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 @@ -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 <ebiederman@lnxi.com> - +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 <ebiederman@lnxi.com>
+
@@ -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 @@ -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<POP_Y + POP_H; i++) { for (j=POP_X; j<POP_X + POP_W; j++) { pp = (char *)(SCREEN_ADR + (i * 160) + (j * 2)); - save[i-POP_Y][j-POP_X] = get_scrn_buf(i, j); /* Save screen */ + save[0][i-POP_Y][j-POP_X] = *pp; /* Save screen */ set_scrn_buf(i, j, ' '); *pp = ' '; /* Clear */ pp++; + save[1][i-POP_Y][j-POP_X] = *pp; *pp = 0x07; /* Change Background to black */ } } @@ -513,10 +401,10 @@ void popdown() for (i=POP_Y; i<POP_Y + POP_H; i++) { for (j=POP_X; j<POP_X + POP_W; j++) { pp = (char *)(SCREEN_ADR + (i * 160) + (j * 2)); - *pp = save[i-POP_Y][j-POP_X]; /* Restore screen */ - set_scrn_buf(i, j, save[i-POP_Y][j-POP_X]); + *pp = save[0][i-POP_Y][j-POP_X]; /* Restore screen */ + set_scrn_buf(i, j, save[0][i-POP_Y][j-POP_X]); pp++; - *pp = 0x17; /* Reset background color */ + *pp = save[1][i-POP_Y][j-POP_X]; /* Restore color */ } } tty_print_region(POP_Y, POP_X, POP_Y+POP_H, POP_X+POP_W); @@ -530,7 +418,7 @@ void popclear() for (i=POP_Y; i<POP_Y + POP_H; i++) { for (j=POP_X; j<POP_X + POP_W; j++) { pp = (char *)(SCREEN_ADR + (i * 160) + (j * 2)); - *pp = ' '; /* Clear screen */ + *pp = ' '; /* Clear popup */ set_scrn_buf(i, j, ' '); pp++; } diff --git a/controller.c b/controller.c index 81fdf6b..ed38e12 100644 --- a/controller.c +++ b/controller.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 */ @@ -279,6 +279,17 @@ static void poll_amd751(void) } } +/* Still waiting for the CORRECT intel datasheet +static void setup_i85x(void) +{ + ctrl.cap = ECC_CORRECT; + unsigned long drc; + + pci_conf_read(ctrl.bus, ctrl.dev, 1, 0x70, 4, &drc); + ctrl.mode = ((drc>>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 }, @@ -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) @@ -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); i<TITLE_WIDTH; i++, pp+=2) { *pp = 0x20; } - cprint(0, 0, " Memtest86 v1.30 "); + cprint(0, 0, " Memtest86 v1.40 "); for(i=0, pp=(char *)(SCREEN_ADR+1); i<2; i++, pp+=30) { *pp = 0xA4; @@ -78,7 +78,7 @@ void init(void) /* Turn on cache */ set_cache(1); - + /* Setup the display */ display_init(); @@ -702,6 +702,7 @@ void cpu_type(void) break; case 3: case 4: + case 5: if (l2_cache == 256) { cprint(LINE_CPU, 0, "Celeron (0.09)"); off = 14; @@ -896,7 +897,8 @@ static void cacheable(void) /* #define TICKS 5 * 11832 (count = 6376)*/ /* #define TICKS (65536 - 12752) */ -#define TICKS (65536 - 8271) +/* #define TICKS (65536 - 8271) */ +#define TICKS 59659 /* Returns CPU clock in khz */ static int cpuspeed(void) @@ -927,7 +929,7 @@ static int cpuspeed(void) if (loops < 4 || end_low < 50000) { return(-1); } - v->clks_msec = end_low/48; + v->clks_msec = end_low/50; return(v->clks_msec); } @@ -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; } } @@ -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; i<sizeof(struct vars); i++, pp++) { - *pp = 0; - } + v->test = 0; + v->pass = 0; + v->msg_line = 0; + v->ecount = 0; + v->ecc_ecount = 0; /* Clear the screen */ for(i=0, pp=(char *)(SCREEN_ADR+0); i<80*24; i++, pp+=2) { @@ -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; i<DEFTESTS != NULL; i++) { /* Test to see if this test is selected for execution */ if (v->testsel >= 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" @@ -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 Binary files differindex 6dc11aa..1725ec7 100644 --- a/mt86+_loader.bin +++ b/mt86+_loader.bin diff --git a/precomp.bin b/precomp.bin Binary files differindex 8838740..052eff0 100755 --- a/precomp.bin +++ b/precomp.bin 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; + } @@ -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)
+
@@ -49,4 +49,4 @@ typedef long long int intmax_t; typedef unsigned long long uintmax_t; -#endif /* I386_STDINT_H */
\ No newline at end of file +#endif /* I386_STDINT_H */ @@ -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 <sys/io.h> @@ -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; } @@ -244,6 +250,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; j<segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + p = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (p == pe ) { + break; + } +/* Original C code replaced with hand tuned assembly code */ +/* + for (; p < pe; p++) { + *p = rand(); + } + */ + + asm __volatile__ ( + "jmp L200\n\t" + ".p2align 4,,7\n\t" + "L200:\n\t" + "call rand\n\t" + "movl %%eax,(%%edi)\n\t" + "addl $4,%%edi\n\t" + "cmpl %%ebx,%%edi\n\t" + "jb L200\n\t" + : "=D" (p) + : "D" (p), "b" (pe) + : "eax" + ); + + do_tick(); + BAILR + } while (!done); + } + + /* Do moving inversions test. Check for initial pattern and then + * write the complement for each memory location. Test from bottom + * up and then from the top down. */ + for (i=0; i<2; i++) { + rand_seed(seed1, seed2); + for (j=0; j<segs; j++) { + start = v->map[j].start; + end = v->map[j].end; + pe = start; + p = start; + done = 0; + do { + /* Check for overflow */ + if (pe + SPINSZ > pe) { + pe += SPINSZ; + } else { + pe = end; + } + if (pe >= end) { + pe = end; + done++; + } + if (p == pe ) { + break; + } +/* Original C code replaced with hand tuned assembly code */ +/* + for (; p < pe; p++) { + num = rand(); + if (i) { + num = ~num; + } + if ((bad=*p) != num) { + error((ulong*)p, num, bad); + } + *p = ~num; + } +*/ + if (i) { + num = 0xffffffff; + } else { + num = 0; + } + asm __volatile__ ( + "jmp L26\n\t" \ + + ".p2align 4,,7\n\t" \ + "L26:\n\t" \ + "call rand\n\t" + "xorl %%ebx,%%eax\n\t" \ + "movl (%%edi),%%ecx\n\t" \ + "cmpl %%eax,%%ecx\n\t" \ + "jne L23\n\t" \ + "L25:\n\t" \ + "movl $0xffffffff,%%edx\n\t" \ + "xorl %%edx,%%eax\n\t" \ + "movl %%eax,(%%edi)\n\t" \ + "addl $4,%%edi\n\t" \ + "cmpl %%esi,%%edi\n\t" \ + "jb L26\n\t" \ + "jmp L24\n" \ + + "L23:\n\t" \ + "pushl %%esi\n\t" \ + "pushl %%ecx\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%edi\n\t" \ + "call error\n\t" \ + "popl %%edi\n\t" \ + "popl %%eax\n\t" \ + "popl %%ecx\n\t" \ + "popl %%esi\n\t" \ + "jmp L25\n" \ + + "L24:\n\t" \ + : "=D" (p) + : "D" (p), "S" (pe), "b" (num) + : "eax", "ecx", "edx" + ); + do_tick(); + BAILR + } while (!done); + } + } +} + +/* * Test all of memory using a "moving inversions" algorithm using the * pattern in p1 and it's complement in p2. */ @@ -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; j<segs; j++) { @@ -901,8 +1062,11 @@ void modtst(int offset, int iter, ulong p1, ulong p2) BAILR } while (!done); } + cprint(LINE_PAT, COL_PAT, " "); } + + /* * Test memory using block moves * Adapted from Robert Redelmeier's burnBX test @@ -1120,6 +1284,7 @@ void block_move(int iter) /* * Test memory for bit fade. */ +#define STIME 5400 void bit_fade() { int j; @@ -1127,6 +1292,9 @@ void bit_fade() volatile ulong bad; volatile ulong *start,*end; + test_ticks += (STIME * 2); + v->pass_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; j<segs; j++) { @@ -1184,7 +1352,8 @@ void error(ulong *adr, ulong good, ulong bad) #ifdef USB_WAR /* Skip any errrors that appear to be due to the BIOS using location * 0x4e0 for USB keyboard support. This often happens with Intel - * 810, 815 and 820 chipsets. It is possible that we will skip + dir + * 810, 815 and 820 chipsets. It is possible that we will skip * a real error but the odds are very low. */ if ((ulong)adr == 0x4e0 || (ulong)adr == 0x410) { @@ -1201,7 +1370,7 @@ void error(ulong *adr, ulong good, ulong bad) /* Don't display duplicate errors */ if ((ulong)adr == (ulong)v->eadr && 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++; @@ -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]; |