Messages in this thread |  | | | Date | Mon, 1 Nov 1999 16:45:54 -0500 (EST) | | From | "Richard B. Johnson" <> | | Subject | RE: Perform minimal RAM test at boot |
| |
On Mon, 1 Nov 1999 nathan.zook@amd.com wrote:
> Two things. First, you don't want to detect memory this way. I'm told some > systems crash if you address memory which is not present. Note also that > the only way to test for memory's presence is to write to it & try to read > back. This destroys any data which might have been put there by the > bios......... > [SNIPPED]
There is no 'bus error' on any ix86 machines. Reading nonexistant memory will not hurt anything. Once in protected mode, all ix86 machines can access memory as 'pages'. There will never be a partial page. A page in ix86-land is 0x1000 bytes. Since the bad BIOSes are in ix86 machines, a memory-check that is ix86-specific can be readily made.
To find the memory limit, you need to set a data selector to map 1:1 physical memory. Then, with the interrupts disabled, save the last longword in each page into a register. Invert it, then write it back. Exercise the bus by pushing, then poping any register, then read the longword. If it is what you wrote, memory exists. Put the original longword back, then go to the next page. You do this until the test fails. The memory is thus determined. This will work even if you end up modifying your own code because what you execute has already been prefetched. To assure success, with modifying code, you need to do the modification at a 2-byte boundary which keeps you off the end of a cache- line, i.e.:
This is Intel syntax dest <-- source
push ds ; Save segment mov ds, _linear_selector xor ebx, ebx ; Start with zero chkm: mov eax [ebx] ; Get memory DWORD mov ecx, eax ; Save not eax ; Invert nop align 2 ; Get off DWORD boundary not [ebx] ; Invert memory byte push eax ; Exercise the bus pop eax cmp eax, [ebx] ; See if it took mov [ebx], ecx ; Put original back jz end_of_mem ; No memory here add ebx,1000h ; Ready next page jmp short chkm
end_of_mem: pop ds ; Restore segment ; EBX = 1000h past last good memory
This code is "swiped" from something working that I did for one of our scanners which has no BIOS, etc. With Linux, you can assume that your code (which is executing) must be in RAM, therefore you can start above your code if you don't like the idea of modifying your own instruction-stream. But, if the code is written as shown, by the time the cache is refetched (because of the detected write), it will have been changed back to the original.
This takes only 2-3 seconds to execute on a 128 megabyte 400 MHz machine.
Cheers, Dick Johnson
Penguin : Linux version 2.3.13 on an i686 machine (400.59 BogoMips). Warning : It's hard to remain at the trailing edge of technology.
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
|  |