moonshot

technical

jenna

jenna is moonshot's memory, who owns every physical page, how small allocations are carved out of big ones, and the page tables that decide what the addresses the kernel uses actually mean.

pages first

the bottom layer hands out physical memory in 4096-byte pages. at boot it walks the memory map the bootloader provides and claims the first usable region past the end of the kernel as its arena. allocation is a bump pointer moving through that region, freeing pushes the page onto a free list, and the clever part is where the list lives, in the freed pages themselves.a free page is by definition unused, so its own first eight bytes are free to hold the link to the next free page. an allocation pops the most recently freed page first, and only bumps the watermark when the list is empty, so freed memory really is reused rather than abandoned.

kernel heap

whole pages are too coarse the moment something wants many small, differently-sized pieces, so a heap (kmalloc and kfree) sits on top. it is a contiguous arena carved from the page allocator, laid out as a packed sequence of blocks, each a 16-byte header (size and a free flag) followed by its payload. there are no next-pointers. the next block always sits just past the current payload, so the whole heap can be walked by address. allocation is first-fit and splits oversized blocks. every free coalesces adjacent free neighbours back together,without coalescing, repeated split-and-free would grind the heap into fragments too small to ever satisfy a larger request again. which the address-order layout makes natural, adjacency is never lost. the heap's first real customers were the shell's line buffer and the scheduler's task table.

page tables of its own

the boot assembly starts the machine on a small, statically built memory map and jenna replaces it. it builds a fresh four-level page table hierarchy entirely from frames it allocated itself, mapping the memory the kernel actually runs on at 4KB granularity, and hands the result over for the switch. the point is not a different mapping, it is that from then on the kernel runs on tables it built dynamically, which is the foundation every later memory feature needs. a sentinel value is stashed in a fresh page that is also mapped at a high address only the new tables know about, and reading it back through that address after the switch proves the CPU is really walking jenna's tables.

demand paging

jenna also owns the page fault handler, and it recovers rather than panics. it aligns the faulting address down to its page, backs it with a fresh zeroed frame, maps it into the live tables, and returns, so the instruction that faulted simply runs again and succeeds.the boot sequence tests this. it touches an address far outside every mapping, takes the real page fault, and checks that the read comes back with the sentinel value the handler seeds fresh pages with. a full kernel would decide map-or-kill per address, what exists today proves the whole fault-and-recover path, which is the mechanism everything later (like real virtual memory per process) builds on.

a private table per process

every ring-3 process runs on page tables of its own. running them all on the kernel's identity-mapped tables with a few pages flipped to user-accessible would have two processes collide in the same address space, sharing memory neither one asked to share. pt_create gives each process its own page-table root, a shallow copy of the kernel's top-level entries, so the identity map, the heap, and every fixed kernel structure stay reachable without re-walking a single frame, and a private carve-out for one specific range every process maps its own code and stack into.that range has to sit below 4GB, because the address gets encoded as a 32-bit immediate in the process's own machine code, which put it inside the same 512GB top-level slot the kernel's identity map already lives in. a plain shallow copy would share that whole slot, private range included, across every process, so that one slot gets its own private second-level table too, seeded from the kernel's, with just the process's own range left blank for it to fill in. two processes calling pt_create genuinely do not share a page.