HappyEggOS is a bit simpler as it doesn't support extended addressing (apart from the Pentium 4MB extensions) or NUMA.
Physical memory
Either the first 4 or 8 Mbytes is allocated to the kernel depending on the amount of actual RAM in the system. All other physical memory is set aside for paging.
Logical memory
The kernel is mapped at 0xC0010000 for 4 meg with 640k of pre allocated pages (reused real mode memory) from 0xC0000000 to 0xC00A0000. These pages are used for directories/pagetables or ISA compatible DMA if necessary.
Up to the 8 Mbytes of memory above the kernel is used for the page 'stack' (push and pop page addresses) and for extra page directories/tables if needed. That leaves everything above 0xC0800000 for paged kernel data device drivers etc.
All drivers run in kernel space above 0xC0000000 and there are only 5 drivers built into the kernel - the rest will be loaded dynamically (once the dynamic linker thing has been degubbed).
Some things above 0xC0800000 can be swapped out (when swapping is implemented) other things are locked (needed device drivers for example).
Most device drivers are only about 4k in size so that's ok. All the complicated stuff is moved into big user task services.
All tasks are User Mode tasks running below 0xC0000000. This includes all system services. Everything communicates via shared memory/messaging. (See example below)
So in texatgraphical form
Logical Memory Map :-
0x00000000 - 0x000001000 Page for page faults - unallocated to catch null pointers
0x00001000 - 0xC00000000 User mode task memory
0xC0000000 - 0xC08000000 Kernel critical memory
0xC0800000 - 0xE00000000 Kernel paged data
0xE0000000 - 0xF00000000 Memory mapped I/O
0xF0000000 - 0xFFFFFFFFFF 4 meg page directory self mapping / anything else that can be recovered from it (not a priority at the moment)
Example User Task Memory Map :- (A simple task like this would have this much shared memory)
0x00000000 - 0x000001000 Page for page faults - unallocated to catch null pointers
0x00001000 - 0x00002000 4k of code for tiny example task - "Hello World!" etc.
0x00002000 - 0x00008000 6k of data for tiny example task
0x00010000 - 0x00020000 64k frame buffer - shared memory with video manager
0x00030000 - 0x00040000 64k file buffer - shared memory with storage manager
0x00040000 - 0x00050000 64k network buffer - shared memory with network manager
0x00050000 - 0xB0000000 User mode heap
0xB0000000 - 0xBFFFF000 User mode Task stack
0xBFFFF000 - 0xC0000000 Page for page faults - unallocated to catch stack underruns
On the subject of stacks and 'heaps'.
Each User mode task has it's own stack (below 0xC0000000) and a kernel stack (4k) above 0xC0000000. Only 4k is needed as the kernel uses only this space for swapping. It's actually shared with the tasks' process table. Device drivers have their stacks above 0xC0000000 and can be of any size required. The addresses of all the device driver stacks are unfixed.
The same goes for 'heaps', they start at the end of the uninitialised data section (BSS sgment of a file) and finish at the end of the address space (the start address of the stack is good).
0x10000000 - For user code USER LEVEL
0x20000000 - For user stack USER LEVEL
0x30000000 - For user heap USER LEVEL
One thing I can see from the memory map above is that the the tasks' stack is
below the 'heap'. I recommend putting the stack
above the 'heap' and set as high in user space as possible (ie at 0xBFFFFFC - 1 DWORD below 0xC0000000) going down. This gives the stack as much room to extend down as possible, and will give applications a huge 'heap' until allocations of 'heap' data collide with the stack data (classic crash scenario), but that's OK. Massive amounts of data and a function that uses megabytes of stack space would be needed to effect this though!
Even if tasks are only using 4Mbytes of address space, I'll bet that 'heaps' more data will be needed (on the 'heap') for tasks than memory is needed for a tasks' stack.