Detecting all installed RAM ??? (int 0xe820)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
AndrewBuckley

Detecting all installed RAM ??? (int 0xe820)

Post by AndrewBuckley »

So where can i find informations about this ...

Thanks
crg

RE:Detecting all installed RAM ??? (int 0xe820)

Post by crg »

unsigned long int i;
unsigned char readb, writeb = 0xff;

for (i=0; ; i++) {
   flat_memory[1048576 + 1024 * i] = writeb;
   readb = flat_memory[1048576 + 1024 * i];
   ig (readb != writeb) break;
}

where flatmemory is lineary mapped memory of computer..

above "code" is correct if you dont have any important information, like kernel copied on 1mb, or something ;)
geezer

RE:Detecting all installed RAM ??? (int 0xe820)

Post by geezer »

I fleshed out your code a little to make it compile:

int main(void) {

unsigned char *flat_memory = (unsigned char *)0;

unsigned long int i;
unsigned char readb, writeb = 0xff;

for (i=0; ; i++) {
flat_memory[1048576 + 1024 * i] = writeb;
readb = flat_memory[1048576 + 1024 * i];
if (readb != writeb) break;
}

return 0; }

Then I compiled like this:

gcc -c -g -Wall -W -O2 test.c
ld     -g -Ttext=0 -o test.x test.o
objdump --source test.x >test.lst

Now look at the asm output in test.lst:

00000000 <_main>:

unsigned long int i;
unsigned char readb, writeb = 0xff;

for (i=0; ; i++) {
   0: 55                   push   %ebp
   1: 89 e5                 mov    %esp,%ebp
   3: 31 d2                 xor    %edx,%edx
flat_memory[1048576 + 1024 * i] = writeb;
   5: c6 05 00 00 10 00 ff movb   $0xff,0x100000
   c: 8d 74 26 00           lea    0x0(%esi,1),%esi
  10: 42                   inc    %edx
  11: 89 d0                 mov    %edx,%eax
  13: c1 e0 0a             shl    $0xa,%eax
  16: c6 80 00 00 10 00 ff movb   $0xff,0x100000(%eax)
readb = flat_memory[1048576 + 1024 * i];
if (readb != writeb) break;
  1d: eb f1                 jmp    10 <_main+0x10>

0000001f <.ef>:
}

return 0; }
  1f: 90                   nop    


Notice any problems?
- No asm code has been generated for the if() statement. It's an infinite loop.
- There is no RET statement in the asm output.
- The code writes to memory but doesn't read back from it.

I think this demonstrates conclusively why DIRECT PROBING OF MEMORY SIZE IS A BAD IDEA.

Get the memory sizes from the BIOS or from the bootloader.
garf

RE:Detecting all installed RAM ??? (int 0xe820)

Post by garf »

First, I don't see how the posted code "demonstrates conclusively why DIRECT PROBING OF MEMORY SIZE IS A BAD IDEA"

The code posted has a bug. Fix the bug and what is the problem? If you could tell me what the problem is with direct probing, I would apreciate it since I have not been able to find any documentation as to why it is so bad beyond "don't do it because it is bad"

The reason I am considering direct probing is because I have yet to find any new hardware that supports e820 or even e801. I know it is not my code because I have lifted code out of linux's setup.s, and it does not work either. I can use int 88, but it only reports up to 32MB on the machines I have tested. I have tried 8 different machines and all of them have BIOSs (is that a word?) that are less than 2 years old.

I would like very much to use the BIOS, but if it does not support it then what do you do?
carbonBased

RE:Detecting all installed RAM ??? (int 0xe820)

Post by carbonBased »

I have no extreme feelings either way... however, using the BIOS not only tells you how much memory you have, but also what kind of memory (I have visions of novice programmers loading binaries to 0xB8000 and wondering why their screen is corrupt...).

Granted, some BIOSs will not report valid stats, but I still think the BIOS should be used first, and _if_ it fails, use direct probing, or some other method (such as GRUB does).

The problem I see with direct probing isn't in the idea, but the implementation.  I always see code like:

loop, Location += 1MB...
  memory[Location] = 'x';
  readMem = memory[Location];
  if(memory != 'x') memTop = Location;
...endLoop

But what if memory[Location], by strange twist of fate, is already defined as 'x'?  You really haven't proven this memory address is writeable, or that it even exists.

Is there a defined value which is returned when an attempt to seek above acceptable memory is tried?

That's all I've got... :)  Perhaps others have more concerns on direct probing?

Jeff
anton

RE:Detecting all installed RAM ??? (int 0xe820)

Post by anton »

The loop for cheking emory should be someting like
readMem = memory[Location]
readMem ^= 0xffff;
memory[Location] ^=0xffff
if( readMem != memory[Location] ) memTop=Location;
Chase

RE:Detecting all installed RAM ??? (int 0xe820)

Post by Chase »

>Perhaps others have more concerns on direct probing?

I personally like direct probing but there are a couple of valid concerns...

1) don't do something stupid like test a bios area of memory cause you'll mess up the data stored there.
2) Memory mapped IO devices......
3) APIC uses areas of memory for info..if you want to use APIC you need to use the BIOS to get
the memory size.
4) Try 2 test values to read and write on the freaky chance that you system returns your test value when reading a non-present memory location.

-Chase
Garf

RE:Detecting all installed RAM ??? (int 0xe820)

Post by Garf »

I would have to agree with you on the implementations that seem to be common. I think that a simple write, read, and compare of just one value is not the best way to do this.

I will be using four different values when testing memory, 0xAA55, 0x55AA, 0xFFFF, 0x0000, these bit patterns are often used during the BIOS memory tests during POST to find bad memory, and in essence this is what a probe of memory is trying to do.

I will also make sure I can successfully probe at 16K, 32K, 48K, and 64K boundries before I mark a 64K block as a usable block of memory. This should allow me to handle memory holes, ROM mapped into high memory, and even odd amounts of memory like 4.5 MB. These are all situations that are possible with embedded hardware (Something I would like to support)

I have not yet had a chance to implement a memory probing routine to test out what exactly happens when you read/write from non-existant memory, and these are questions I was hoping to have answered before I start.

If anyone has any info on what happens when you read/write non-existant memory or have suggestions on my planned implementation of probing memory. Let me know.
geezer

RE:Detecting all installed RAM ??? (int 0xe820)

Post by geezer »

>The code posted has a bug.

Yes. I should have used the 'volatile' keyword. But how many people reading this board knew that? This sort of memory size determination is easy to do, but surprisingly difficult to do correctly.

What about compilers (Borland C 3.1) which screw up the code, even if you use 'volatile'?

What about address "aliasing"? I have an old 486SX system for which memory repeats every 64 meg, so the memory at address 0 appears at address 64 meg, 128 meg, 192 meg, etc. If a system like this had a full 64 meg of RAM in it, the direct probing code would keep going to the end of RAM, and report that I had 4 Gig.

What about systems that have "holes" in extended memory? I haven't encountered such a system, but they exist. Direct probing would not report all available extended memory.

What about systems with memory-mapped devices in them? Maybe a PCI board, maybe some kind of 16-bit ISA board. The direct probing code doesn't know that the memory or registers on this board are not usable RAM.

What about the capacitance of a floating bus that has nothing connected to it? Does your memory probing code detect RAM which does not exist?

Does the direct probing code run from real mode? Then you have to turn on the A20 gate, which is _another_ can of worms.

Using the BIOS avoids _all_ of these problems.

>I have lifted code out of linux's setup.s

Did you use a new version? Here it is from kernel 2.4.18, nicely documented:
http://lxr.linux.no/source/arch/i386/boot/setup.S

>The reason I am considering direct probing is because I have yet to find any new hardware that supports e820 or even e801

If they're new machines, then I suspect possible BIOS bugs. Some of these bugs are described in Ralf Brown's interrupt list; others are described here:
http://marc.theaimsgroup.com/?l=linux-k ... 013363&w=2

Memory testing:
http://www.netrino.com/Articles/MemoryT ... paper.html
Garf

RE:Detecting all installed RAM ??? (int 0xe820)

Post by Garf »

Sorry to revive this topic but I just wanted to thank Geezer.

Your post got me to take a new look at my memory detection routines. I stated that I could not find a newer machine that supported e820. Well I have found that I was wrong. ALL of the machines I had tested did in fact support e820.

The problem was not with my memory detection routines, but was actualy in my CPU detection code executed earlier. I was using an invalid opcode exception handler in this routine and when the code was finished with the handler it was supposed to return the interupt vector table to its original condition. A small typo was causing me to trash the table.

The next call I made into the BIOS after that point was a call to e820. It would fail because the BIOS would try to get some data pointed to by the vector table that I had trashed.

After fixing my CPU detection code everything works fine and I feel much better now that I do not have to rely on direct probing.

This just goes to show why we need PMode OSs, They keep people like me from getting the noose to tight around our necks. From now on I will more closely examine my problems before I post them on this board ;)
netster403

RE:Detecting all installed RAM ??? (int 0xe820)

Post by netster403 »

the great amd wise geezer speaks, every one bow before him, the master of the OS!!  :)
Post Reply