Hi,
I'd recommend seperating things properly. For example, write a "physical memory manager", then write a "linear memory manager" and then write any heap management code after that (malloc/free) if you want.
Also, make sure that your physical memory manager can handle 64 bit physical addresses - I've seen too many OS's that would crash horribly if you run them on a computer with over 4 GB of memory. I'd suggest splitting physical memory management into a least 2 seperate memory managers, one for 32 bit physical addresses and another for 64 bit addresses (even if the 64 bit physical memory manager never does anything).
This makes it much easier to add support for PAE later on, because with PAE you need 32 bit physical addresses for CR2 (even though everything else can use 64 bit physical addresses).
For example, use several seperate sub-directories in your source code:
- memory detection
- 32 bit physical memory manager
- 64 bit physical memory manager (possibly just a stub)
- normal linear memory manager
- optional PAE linear memory manager
- optional heap management
I use a seperate memory manager for memory below 16 MB due to ISA DMA constraints, with a bitmap for memory < 16 MB, sets of free page stacks for memory between 16 MB and 4 GB and seperate sets of free page stacks for memory above 4 Gb. Each "set of free page stacks" consists of a pair of stacks for clean pages and dirty pages, for each "page colour" (and/or NUMA memory range). For physical memory management I can have up to 1024 individual free page stacks in addition to the bit map for memory below 16 MB
.
This gives me:
- memory detection
- low memory physical memory manager
- middle memory physical memory manager
- high memory physical memory manager
- normal linear memory manager
- PAE linear memory manager
- heap management
Note: "page colouring" is a technique for optimizing cache usage - use google if you're interested.
The general idea is to build a list of RAM areas within the memory detection code, then loop through each page in each RAM area in the list. For each page you'd check if it's actually in use, and if not call the appropriate physical memory manager's "freePage()" function.
You'd also need to be careful when doing this, as some areas may not start or end on a page boundary. For example, you could have RAM from 0x00000000 to 0x0009F800 - the last page (from 0009F000 to 0009FFFF) can't be used.
Cheers,
Brendan