Re: Breaking the 64MB barrier

Riley Williams (rhw@bigfoot.com)
Sun, 18 Oct 1998 18:29:27 +0100 (GMT)


Hi Alan.

On Sun, 18 Oct 1998, Alan Cox wrote:

>> We could check memory by writing some bytes ( hexadecimal values
>> FF, AA, 55, 00 ) into each byte at addresses above 64MB RAM and
>> then reading and comparing. If these addresses contain memory,
>> these bytes will be stored and the comparison will be successfull.

>> If we enter adresses without memory the values written will be
>> lost and we will read some garbage, so the comparison will fail.
>> Thus we can detect the right memory_end.

>> Maybe there are some difficulties as the processor uses cache so
>> we have to prevent that we read back only from processor-cache.

> That is an understatement. You have to deal with mirroring of
> devices, two devices decoding at the same invalid address, bus
> capacitance making you read back what you wrote, devices that
> partially mirror or misdecode in high space and more.

> The x86 bios fixed the problem a long time ago. 2.0.x in the 36
> series has caught up.

There's still the problem of what to do with machines where the BIOS
doesnae support the extended call in question...

One method I have seen used with success in a different x86-based
environment is as follows:

1. Check the memory returned value. If it's saying less than 16M
then execute the following instruction, then go to step 3:

MAX = VALUE - 1

2. Execute the following pseudo-code:

ADDR = 64G - 1M
while ADDR > 1M do
VALUE = (ADDR / 1M) % 65536
poke word ADDR-2, VALUE
ADDR -= 1M
done
TOP = 1M
while ADDR < 64G do
VALUE = (ADDR / 1M) % 65536
if (peek word ADDR-2) == VALUE then
TOP = ADDR
ADDR = 64G
fi
ADDR += 1M
done
MAX = TOP - 1

3. Assume that the value in MAX is the highest valid memory
address for physical memory.

This method has the advantage that a DIFFERENT word is written in the
top word of each megabyte, and as they're written in descending order,
the problem with memory mirroring is dealt with since it's the one
that gets written at the lowest mirrored address that will be read
back for all mirrored addresses.

As far as I'm aware, the problems with this approach are as follows:

a. Caching may cause problems. However, if my understanding of
how caching works is correct, the fact that the addresses being
written to all have the same pattern in their bottom 10 bits
means that the same set of cache locations will be used for all
of the addresses concerned, with the result that only the lowest
addresses will still be in the cache when it comes time to read
them.

b. It can only detect memory in the first 64G of the address range.
However, if it detects 64G of memory, the entire routine could
trivially be repeated, but offset upwards by 64G to search the
64G to 128G range, recursing upwards as required...

Come to that, I could use a machine with 64G of RAM...

c. Some systems reserve a block at the top of memory for their own
use. If this block is mapped to be immediately above the valid
memory without a break, then it will be included in the above
returned value.

Systems in question include those with the video system on the
motherboard, since they generally grab video memory from the
system RAM, but I have met other systems which grab chunks off
the top of standard RAM for themselves.

In this respect, I can report an Intel P166 based system I have,
with 128M of RAM, where a setting of "MEM=131068" happily boots
up, but ANY higher setting causes it to lock up solid. I've no
idea what that top 4k of RAM is being used for though...

d. If the memory is such that it doesn't finish on a 1M boundary,
the extra beyond the highest valid 1M boundary will not be
used. However, this is trivially solved by stepping through
the next megabyte in 4k steps with a repeat of the above.

Comments?

Best wishes from Riley.

-
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/