Memory layout

The memory layout constants and code is defined in memory_layout

This is the structure of the memory for any process running in the system.

Layout

0000_0000_0000_0000 .. FFFF_FF7F_FFFF_FFFF - User   (15.99~ EB)
FFFF_FF80_0000_0000 .. FFFF_FFFF_7FFF_FFFF - Process specific kernel (510 GB)
FFFF_FFFF_8000_0000 .. FFFF_FFFF_FFFF_FFFF - Kernel (2 GB)

Kernel layout

FFFF_FFFF_8000_0000..FFFF_FFFF_8010_0000          nothing
FFFF_FFFF_8010_0000..FFFF_FFFF_8XXX_XXXX          kernel elf (text, rodata, data, bss)
FFFF_FFFF_8XXX_XXXX..FFFF_FFFF_8800_0000          (kernel end) physical allocator low (until 128MB mark pre-mapped in `boot`)
FFFF_FFFF_8800_0000..FFFF_FFFF_8900_0000          kernel heap (16MB)
FFFF_FFFF_8900_0000..FFFF_FFFF_890E_7000          interrupt stacks
    FFFF_FFFF_8900_0000..FFFF_FFFF_8900_1000      interrupt stack 0 guard page (4KB) *not mapped by purpose*
    FFFF_FFFF_8900_1000..FFFF_FFFF_8902_1000      interrupt stack 0 (32 * 4KB = 128KB)
    ... *repeat for 6 more stacks*
FFFF_FFFF_890E_7000..FFFF_FFFF_FFFF_F000          Kernel extra (virtual space, free virtual space to use)

The kernel is loaded by the bootloader at physical address 0x10_0000, and then it will perform virtual mapping for physical 0x0 into 0xFFFF_FFFF_8000_0000 for 128MB i.e. until the end of the initial physical page allocator. See more details in the boot chapter.

Look at virtual space for more info on it.

Virtual space

Virtual space is a I'm using (not sure what other OSes call), that solves the issue of "I have a physical address of an object, but I don't have virtual space to map it to". This is useful for reading structures that are in specific location in physical memory, such as ACPI tables, PCI configuration space, memory mapped IO, etc.

Its very simple, it will take memory from the kernel extra space, and map it to the physical address.

Process specific kernel layout

FFFF_FF80_0000_0000..FFFF_FF80_0000_1000          process kernel stack guard page (4KB) *not mapped by purpose*
FFFF_FF80_0000_1000..FFFF_FF80_0004_1000          process kernel stack (64 * 4KB = 256KB)

This is a space specific to each process, but reside in kernel space.

The idea is to have structures that are specific to processes here, that others won't have access and thus reduce the need to setup a lock around them.

We use it currently for kernel stack, which is where the kernel will store the stack when an interrupt happens while we are in user space.

It solves the issue where having a single kernel stack for all processes can't work, as if two processes gets interrupted while the first one is still in the kernel, the second one will overwrite the first one's stack.

As you might have expect, the previous paragraph was a source of a crazy bug that introduced this kernel stack. Fixed in 0dc04f8

User layout

Not much to talk about here, as this will depend on the process itself and where to load the ELF file, currently we load at the address specified in the ELF file. This is of course not safe, as we don't do extra checks for that value.

But anyway, the other parts of the userspace are as follows:

XXXX_XXXX_XXXX_XXXX .. YYYY_YYYY_YYYY_YYYY - ELF file
YYYY_YYYY_YYYY_YYYY .. ZZZZ_ZZZZ_ZZZZ_ZZZZ - Heap. From the end of the ELF and grows up
ZZZZ_ZZZZ_ZZZZ_ZZZZ .. FFFF_FF7F_FFFF_D000 - Stack. From the top and grows down
FFFF_FF7F_FFFF_D000 .. FFFF_FF7F_FFFF_E000 - Stack guard page. *not mapped, just for reference*
FFFF_FF7F_FFFF_E000 .. FFFF_FF7F_FFFF_F000 - Process Metadata structure

A lot of symbols XD. But in general, the stack is at the top of the user space, and the elf file is at the bottom, and the heap is in the middle starts after the elf file.