Memory Explained

This page explains how memory works in an operating system, from the hardware level up to SaltyOS’s design.

Physical vs Virtual Memory

Your computer has physical RAM — actual hardware chips with a fixed number of bytes. A machine with 4 GB RAM has addresses from 0x0 to 0xFFFF_FFFF.

If programs used physical addresses directly, they would step on each other. Program A writes to address 0x1000, program B writes to 0x1000, and they corrupt each other’s data.

The solution: virtual memory. Each program gets its own view of memory (an address space) where address 0x1000 in program A maps to a different physical location than 0x1000 in program B.

Program A's view:         Physical RAM:         Program B's view:
0x1000 → "hello"    →    0x5A000: "hello"      0x1000 → "world"
                          0x7B000: "world"  ←

The CPU’s Memory Management Unit (MMU) translates virtual addresses to physical addresses on every memory access, using a data structure called a page table.

Pages and Page Tables

Memory is managed in fixed-size chunks called pages (4 KB = 4,096 bytes on most systems).

A page table is a lookup table stored in RAM that maps virtual page numbers to physical page numbers (called frames):

Virtual page 0  →  Physical frame 42
Virtual page 1  →  Physical frame 7
Virtual page 2  →  (not mapped -- access causes a page fault)
Virtual page 3  →  Physical frame 128

On x86_64, page tables have 4 levels (PML4 → PDPT → PD → PT), each with 512 entries. On aarch64, the structure is similar (4 levels, 512 entries each, using TTBR0/TTBR1).

The kernel manages page tables. User programs never see them — they just use virtual addresses, and the MMU translates transparently.

Page Faults

What happens when a program accesses an address that is not mapped?

The CPU raises a page fault exception. The kernel handles it:

  • If the page is supposed to exist but has not been loaded yet (demand paging), the kernel allocates a frame and maps it.

  • If the page is copy-on-write, the kernel makes a private copy.

  • If the address is invalid (segmentation fault), the kernel kills the program.

Page faults are not errors — they are a normal part of memory management. Most page allocations in SaltyOS happen via page faults, not upfront allocation.

Copy-on-Write (COW)

When a process calls fork(), the child gets a copy of the parent’s entire address space. Copying all the memory would be extremely slow.

Instead, the kernel uses copy-on-write:

  1. Both parent and child share the same physical pages.

  2. Both page tables are marked read-only.

  3. When either process writes to a shared page, a page fault occurs.

  4. The kernel copies just that one page and gives the writer its own private copy.

  5. The writer’s page table is updated to point to the new copy, now writable.

This means fork() is nearly instant, and only pages that are actually modified get copied.

Diagram

In SaltyOS, COW is handled entirely in the kernel — no IPC to any server. This is the COW fast-path.

How SaltyOS Organizes Memory

Most operating systems have a kernel memory allocator (like kmalloc in Linux) that hands out chunks of memory from a big pool.

SaltyOS does not have a kernel heap. Instead, it uses a four-tier model where each tier has a specific responsibility:

Tier 1: PMM (Physical Memory Manager)

The lowest tier. The PMM is a bitmap-based allocator that tracks every 4 KB physical frame in the system. Each frame is tagged with an owner (who is using it and why).

Think of the PMM as a warehouse clerk who tracks every box on every shelf. Nothing enters or leaves without the PMM knowing about it.

Tier 2: Untyped Memory

Raw physical memory exposed to user space through capabilities. When the system boots, most RAM is wrapped in "untyped" capabilities and given to the init process.

To create a kernel object (an endpoint, a thread, an address space), you retype untyped memory:

"Take this raw 4 KB and turn it into an Endpoint object."

After retyping, the memory is a typed kernel object. It can be un-retyped back to raw memory later (if nothing depends on it).

This is like buying raw land and building a specific structure on it. The land (untyped) exists first; the building (endpoint) is created from it.

Tier 3: MemoryObject (MO)

A MemoryObject is a named collection of pages. It is the abstraction that programs interact with (indirectly, through the memory manager server).

When a program calls mmap(), the memory manager creates a MemoryObject, commits physical frames to it, and maps it into the program’s address space.

Key features:

  • Pages are stored in a 4-level tree (like page tables, but for tracking pages within the MO).

  • Supports COW cloning (for fork()).

  • Tracks which address spaces have mapped its pages (reverse maps).

Tier 4: VSpace (Virtual Address Space)

A VSpace is the address space of a process. It wraps the hardware page tables and tracks which MO pages are mapped where.

The VSpace does not own any physical pages. It borrows views of MO pages. If the MO decommits a page, the VSpace mapping disappears.

┌─────────────────────────────────────────┐
│          Your Program                    │
│   (sees virtual addresses)               │
├─────────────────────────────────────────┤
│   VSpace                                │
│   "I map MO pages into page tables"     │
├─────────────────────────────────────────┤
│   MemoryObject                          │
│   "I manage pages and COW"              │
├─────────────────────────────────────────┤
│   Untyped Memory                        │
│   "I provide raw frames for MOs"        │
├─────────────────────────────────────────┤
│   PMM                                   │
│   "I own all physical frames"           │
└─────────────────────────────────────────┘

Why Four Tiers?

You might wonder: why not just a simple "allocate page, map page" model?

The four-tier model separates ownership from mapping from policy:

  • PMM answers: "is this frame free or used, and who owns it?"

  • Untyped answers: "where does the raw memory for kernel objects come from?"

  • MO answers: "which pages belong to this logical memory region, and who is observing them?"

  • VSpace answers: "at what virtual address does this program see this page?"

This separation enables:

  • COW without the page allocator knowing about it (MO handles cloning).

  • Multiple address spaces sharing the same physical page (MO tracks reverse maps).

  • Memory accounting and revocation through capabilities (untyped controls allocation authority).

  • Page fault handling without user-space IPC in the common case (kernel resolves COW and demand faults internally).

What to Read Next