Espanish wrote:My Multiboot kernel is booted by Grub Legacy.
Using the memory map provided by Grub, I can't access RAM beyond the first 3 GB.
From what I read on the [
Wiki], I must enable paging and PAE.
Now I have some questions:
- does this mean that I have to manually probe the remaining memory?
- is there a way to have Grub (or Grub2) enable paging itself and give a proper memory map?
Maybe and no. How much memory do you have installed?
Some of your hardware maps itself to memory (your graphics card is a good example), and most will try to do this under the 4GB mark so it's addressable from regular old protected mode. Unfortunately, when you have 4GB of RAM, this means you can't access it all your RAM.
GRUB doesn't enable paging, but even if it could enable it for you, it'd be useless (it wouldn't know how you'd want it set up). Your pointers are still 32-bit values, so they can't point above 4GB of virtual address space. What PAE does is allow you to map >4GB of physical memory to the 0GB-4GB virtual address space. In a typical multitasking 32-bit operating system, each process has a 4GB virtual addresss space, and PAE allows you to touch all of your RAM, even if each process individually can't touch more than 4GB at once (the size of a 32-bit pointer).
If you have a 'hole' between 3GB-4GB caused by memory mapped hardware, your physical RAM (if you have more than 3GB installed) would be pushed up above the >4GB address space. You'll have to use paging (and PAE) to map the physical range 4GB-5GB to the virtual range 3GB-4GB.
But the job isn't that easy. There are 'holes' all over the place. The BIOS puts plenty of holes <1MB. ISA cards like to map themselves in the 15MB-16MB range. A RAM chip could be bad (the BIOS could flag this during POST diagnostics) - your OS can just treat this as another hole (wiki reference:
Memory Map (x86)).
Without a bootloader like GRUB, the BIOS (which has been specifically programmed per your chipset to detect hardware and memory) is probably the only reliable way to ask the system for a layout (wiki reference:
Detecting Memory (x86)) - which you have to call in real mode. GRUB takes a lot of this effort away from you.
I'm not sure about GRUB legacy, I'm using GRUB 2, and it gives me 64-bit offsets and lengths when you ask it for a memory map.
First - I request the memory map in
my multiboot header, and then I
iterate through the memory map - I dice each chunk of memory GRUB finds into 4KB pages, then I add it to a linked list (by writing the address of the next free page at the start of the page). Very fast to grab the next free page, or to free a page by adding it to the list. (You might wonder - how do you touch an arbitrary address that isn't mapped into virtual memory - such as >4GB - to build this linked list? When I build my page table, I reserve a few page table slots that I can map arbitrary pages into for kernel jobs like this.)
But, this assumes you have paging. Even if you want a flat memory layout (everything in one linear address space), you can use paging to fill in the 'holes' to make everything seem like one continuous chunk of RAM from 0 to 4GB.
But still, you can only see 4 GB of this at once. So if you dedicate it all to usable RAM, you'll have nowhere to map your hardware! In modern operating systems, this isn't that much of an issue, because each program is usually given it's own (~3GB) address space (with the top 1GB always used by the kernel). In a microkernel, where everything including drivers have their own address space, each program can have nearly the entire 4GB virtual address space to itself.
Or you can use long mode (64-bit), use paging to map everything (RAM and hardware) into one huge flat memory space, and worry again once computers have exabytes of memory.