SPEC v1.2.4b •
System Specification

PangeaOS Architecture Specification v1.2.4b

Complete System Rules With Clear Explanations: How the 48-Bit Memory Space Is Divided, How the 16 Hardware Keys Work, and How Hardware Exceptions Are Contained

1. Core Architectural Rules Explained

This specification defines the rules that every component of PangeaOS v1.2.4b must follow. Before looking at the memory tables and bitmasks, here is the reasoning behind our six foundational rules:

  1. Everything Runs in Ring 0 (CPL=0) Inside One Address Space (SASOS): To avoid the slowdown of switching processor privilege rings and swapping address maps (CR3), the kernel, drivers, and service domains all share a single 64-bit virtual address space at CPL=0.
  2. Safety Comes From Combining Hardware Keys and Code Verification: Because there is no Ring-3 boundary, PangeaOS never relies on a single mechanism for isolation. A service domain is only isolated if its machine code has been verified before launch (bincheck-core / domain-verify) and its memory access is policed at runtime by hardware Memory Protection Keys (PKRU), capability tokens (cap-core), and preemptive timers (pangea-watchdog).
  3. Never Halt the Computer for a Local Problem: An error inside a single service domain (such as a bad input, a crash, or running out of quota) must never stop the whole operating system. Full-system halts (Global Fail-Stop) are reserved strictly for situations where the core kernel (Domain 0) itself or its hardware isolation tables are damaged.
  4. Never Trust a Crashed Program's Own Memory During Recovery: When an exception happens while a service domain is running, the kernel must never read the service domain's stack or registers to figure out which domain was running or where the scheduler should resume. Instead, the kernel reads that information exclusively from its own protected per-CPU record (TrustedPerCpuState, stored in K0 memory and pointed to by the CPU's GS_BASE register).
  5. Memory Pages Are Never Reused Until Cache Flushes and Zeroing Complete: When a memory page is taken away from a service or device, it is placed into Quarantine. It cannot be given to another service until every CPU core and IOMMU device confirms it has flushed its cached address lookups, and the page has been completely overwritten with zeros (cmee).

2. How the 48-Bit Shared Memory Space Is Divided

Imagine the computer's 64-bit virtual memory space as a giant highway with clearly numbered exits. PangeaOS divides this space into dedicated zones so that looking at the upper bits of any memory address immediately tells you who owns it:

  • The Lower Half (0x0000_0000_0000_0000 to 0x0000_0CFF_FFFF_FFFF) holds the 2-Megabyte Null Guard at the very bottom, followed by twelve 1-Terabyte sandboxes for Service Domains 1 through 12.
    • How do you know if an address belongs to Domain $d$? You simply shift the address right by 40 bits (addr >> 40). If (addr >> 40) == 3, that address is inside Domain 3's 1-Terabyte sandbox (0x0000_0300_0000_0000 to 0x0000_03FF_FFFF_FFFF).
  • The Upper Half (0xFFFF_8000_0000_0000 to 0xFFFF_FFFF_FFFF_FFFF) is reserved exclusively for the core operating system (Domain 0), emergency rescue stacks (IST 1..4), the Physical Frame Database, page tables, IPC message rings, and kernel code.
Virtual Address Range Size What Lives Here Hardware Key How It Is Protected
0x0000_0000_0000_0000 .. 0x0000_0000_001F_FFFF 2 MiB Virtual NULL Guard None Left completely unmapped (P=0) so any null pointer triggers an immediate fault.
0x0000_0100_0000_0000 .. 0x0000_0CFF_FFFF_FFFF 12 TiB total
(1 TiB per Domain)
Service Domains 1–12 Sandboxes
Domain d: (va >> 40) == d
K1–K12 Each domain can only unlock its own key (K_d). Code is Read-Only; Data is Non-Executable.
0xFFFF_8000_0000_0000 .. 0xFFFF_807F_FFFF_FFFF 512 GiB Kernel Private State & Per-CPU Records (TrustedPerCpuState, k0_priv_rsp) K0 Unlocked only when running inside Domain 0 or after an exception stub resets PKRU.
0xFFFF_8080_0000_0000 .. 0xFFFF_80FF_FFFF_FFFF 512 GiB Emergency Rescue Stacks (IST 1..4) & Hardware Tables (GDT/TSS/IDT) Supervisor (U/S=0) Mapped with U/S=0 so the CPU can always push an exception frame even when PKRU is locked.
0xFFFF_8100_0000_0000 .. 0xFFFF_817F_FFFF_FFFF 512 GiB Physical Frame Database (pangea-pfndb) K0 Tracks the owner and cleanup state of every 4 KB physical RAM page.
0xFFFF_8200_0000_0000 .. 0xFFFF_827F_FFFF_FFFF 512 GiB Page-Table Hierarchy Window (pangea-mmu) K13 Kept Read-Only even for the kernel; unlocked for writing only inside the PT Update Gate.
0xFFFF_8300_0000_0000 .. 0xFFFF_837F_FFFF_FFFF 512 GiB IPC Message Ring Window (pangea-ring) K14 Service domains have Read-Only access; updated only through the kernel IPC broker.
0xFFFF_8400_0000_0000 .. 0xFFFF_847F_FFFF_FFFF 512 GiB Quarantine Zeroization Window (cmee) K15 Locked at all times except inside the memory-wiping gate when erasing quarantined pages.
0xFFFF_FFFF_8000_0000 .. 0xFFFF_FFFF_FFFF_FFFF 2 GiB Core Kernel Code (.text, gate-asm) & Constants Supervisor (U/S=0) Read-Only hardware protection (CR0.WP=1); separated onto 4 KB page boundaries by linker.ld.

3. How the 16 Hardware Keycards (PKRU) Are Encoded

On x86-64 CPUs with Protection Keys enabled (CR4.PKE = 1), the PKRU register is 32 bits wide—2 bits for each of the 16 keys (K0 through K15):

  • 0b00 (PKRU_RW): Both reading and writing are allowed.
  • 0b10 (PKRU_RO): Reading is allowed, but writing is blocked (Write Disable = 1).
  • 0b11 (PKRU_NA): All access (both reading and writing) is blocked (Access Disable = 1, Write Disable = 1).

Instead of flipping individual bits at runtime (which could leave a key unlocked by mistake), PangeaOS overwrites the entire 32-bit PKRU register with pre-calculated constants verified at compile time:

  1. PKRU_KERNEL_DEFAULT = 0xCBFF_FFFC (Normal Kernel Mode):
    • K0 (Kernel data) = RW (00)
    • K1 through K12 (All 12 service domains) = NA (11) (The kernel cannot accidentally touch domain memory!)
    • K13 (Page tables) = RO (10) (Page tables are protected against stray kernel writes)
    • K14 (IPC rings) = RW (00)
    • K15 (Quarantine shredder) = NA (11)
  2. PKRU_KERNEL_PT_UPDATE = 0xC3FF_FFFC (Inside the Page-Table Update Gate):
    • Identical to PKRU_KERNEL_DEFAULT, except K13 is temporarily unlocked to RW (00) for the single instruction that writes a verified page-table entry, and immediately locked back to 0xCBFF_FFFC afterward.
  3. pkru_for_domain_const(d) (When Service Domain $d \in {1..12}$ Is Running):
    • K_d (That specific domain's own memory) = RW (00)
    • K14 (IPC ring counters) = RO (10)
    • Every other key (K0, K13, K15, and all other domains) = NA (11).

4. Hardware Descriptor Tables & Live Crash Recovery Rules (v1.2.4b)

To make sure the Two-Stack Exception Rescue Protocol works on real x86-64 hardware (and QEMU -cpu max), v1.2.4b enforces four hardware binding rules:

  1. 10-Slot 64-Bit Global Descriptor Table (GDT): Provides PangeaOS's standard Ring-0 Code selector (0x08), Ring-0 Data selector (0x10), and 16-byte 64-bit TSS selector (0x18..0x20), while also placing valid 64-bit Ring-0 Code/Data descriptors at selectors 0x28..0x48 so UEFI firmware segment registers (CS=0x38, SS=0x30) remain valid during live descriptor table transitions.
  2. Packed 104-Byte Task State Segment (TaskStateSegment64): In the x86-64 hardware specification, the 64-bit stack pointers inside the TSS (RSP0..2 at offset +0x04 and IST1..7 at offsets +0x24..+0x5C) are misaligned by 4 bytes. PangeaOS defines TaskStateSegment64 with #[repr(C, packed)] and compile-time offset_of! assertions so compiler padding never shifts the IST 1..4 rescue stack addresses.
  3. Normalized 23-Quadword Exception Frame (TrustedExceptionFrame): Some x86-64 exceptions push a hardware error code onto the stack (#DF, #GP, #PF, #CP), while others do not (#DE, NMI, #UD, #MC, and hardware interrupts 32..255). For every vector that does not push a hardware error code, our entry stub pushes a 0 before jumping to pangea_two_stack_isr_common_stub. This guarantees that the frame copied from IST 1 to k0_priv_rsp is always exactly 23 * 8 = 184 bytes.
  4. ABI-Independent Domain Invocation (invoke_domain_live): Because UEFI binaries use the Microsoft x64 calling convention (rcx, rdx, r8, r9) while bare-metal ELF binaries use the System V AMD64 calling convention (rdi, rsi, rdx, rcx, r8, r9), invoke_domain_live binds all arguments to explicit hardware registers inside core::arch::asm!, ensuring identical behavior across all build targets.