|
|
|
# Virtual Memory Layout on amd64
|
|
|
|
|
|
|
|
GayBSD's virtual memory map is based on the one from FreeBSD.
|
|
|
|
The only difference is that areas for features which aren't implemented (yet)
|
|
|
|
are unused.
|
|
|
|
We do this because even though GayBSD is supposed to be an OS written mostly
|
|
|
|
from scratch, my gut feeling somehow tells me it's better that way.
|
|
|
|
Also, i trust the FreeBSD people have put way more thought into this than i
|
|
|
|
probably could have ever done with my limited knowledge about the x86.
|
|
|
|
|
|
|
|
The size specifiers here are powers of two (1 KB = 1024 B).
|
|
|
|
|
|
|
|
start address | offset | end address | size | description
|
|
|
|
:------------------:|-------------:|:-------------------:|-----------:|:----------------------------
|
|
|
|
`00000000 00000000` | +0 | `00007fff ffffffff` | 128 TB | userland area
|
|
|
|
`00008000 00000000` | +128 TB | `ffff7fff ffffffff` | ~ 1.6M TB | **huge ass hole**
|
|
|
|
`ffff8000 00000000` | -128 TB | `ffff8040 20100fff` | ~ 0.25 TB | recursive page table
|
|
|
|
`ffff8040 20101000` | ~ -127.75 TB | `fffff7ff ffffffff` | ~ 119 TB | unused
|
|
|
|
`fffff800 00000000` | -8 TB | `fffffbff ffffffff` | 4 TB | linear physical memory
|
|
|
|
`fffffc00 00000000` | -4 TB | `fffffdff ffffffff` | 2 TB | unused
|
|
|
|
`fffffe00 00000000` | -2 TB | `ffffffff ffffffff` | 2 TB | kernel area
|
|
|
|
|
|
|
|
Kernel address space starts counting from the end of virtual memory space
|
|
|
|
downwards, therefore the offsets are negative.
|
|
|
|
Likewise, user space starts from the beginning, meaning positive offsets.
|
|
|
|
|
|
|
|
The **huge ass hole** between user and kernel space is specified in _million TB_
|
|
|
|
because i think it gives a better overview of the size ratios between these
|
|
|
|
individual areas than just writing EB.
|
|
|
|
It also kind of makes you appreciate the sheer vastness of 64-bit address space.
|
|
|
|
|
|
|
|
Kernel space addresses start at `0xffff800000000000` because the MMU "only"
|
|
|
|
supports 48-bit linear addresses.
|
|
|
|
The way i've understood it, the Intel spec says bits 63:48 of virtual
|
|
|
|
addresses must be copies of bit 47, but other than that are ignored.
|
|
|
|
So, as far as the MMU is concerned, the huge hole doesn't even exist:
|
|
|
|
Userspace ranges from `0x000000000000~0x7fffffffffff`,
|
|
|
|
and everything belonging to the kernel from `0x800000000000~0xffffffffffff`
|
|
|
|
(note how the leading 0's/f's are missing, these are 48-bit values).
|
|
|
|
|
|
|
|
The linear physical memory is a direct mapping of physical RAM, which is
|
|
|
|
required because `kmalloc()` and friends need to be able to allocate
|
|
|
|
*physically* contiguous memory for DMA transfers and i don't have the energy
|
|
|
|
to update kernel page maps every time the kernel needs a new page.
|
|
|
|
|
|
|
|
The kernel image itself is loaded into physical memory at `0x00400000` by
|
|
|
|
default, and the entire low 2 GB of physical memory are statically mapped to
|
|
|
|
the end of virtual memory (-2 GB). That way, we can use `-mcmodel=kernel`,
|
|
|
|
which prevents the compiler from emitting raw address loads and absolute jumps
|
|
|
|
(this is significantly faster).
|
|
|
|
All kernel code resides within the -2 GB region.
|
|
|
|
|
|
|
|
The `vm_page_array`, which keeps track of what each individual page is used for,
|
|
|
|
starts directly at the beginning of the kernel area at -2 TB.
|