PactorOS Architecture
PactorOS is a minimal operating system built from scratch for embedded applications. The kernel is written in C and assembly, compiled with LLVM/Clang, and targets both x86-64 (desktop/QEMU) and ARM64 (Raspberry Pi 5).
System Overview
+------------------------------------------------------------------+ | USERSPACE (EL0 / Ring 3) | | +-----------+ +-----------+ +-----------+ +-----------+ | | | fibonacci | | primes | | sort | | hello | ... | | +-----------+ +-----------+ +-----------+ +-----------+ | | +----------------------------------------------------------+ | | | libc (printf, malloc, strings) | | | +----------------------------------------------------------+ | |─────────────────── SYSCALL / SVC ────────────────────────────────| | KERNEL (EL1 / Ring 0) | | +----------------------------------------------------------+ | | | syscall dispatch | | | | read(0) write(1) exit(93) brk(214) | | | +----------------------------------------------------------+ | | +----------+ +----------+ +----------+ +----------+ | | | shell | | ELF64 | | ext2 | | PMM | | | | (CLI) | | loader | | fs | | (pages) | | | +----------+ +----------+ +----------+ +----------+ | | +----------+ +----------+ +----------+ +----------+ | | | ATA | | VGA | | keyboard | | timer | | | | (disk) | | (video) | | (PS/2) | | (100Hz) | | | +----------+ +----------+ +----------+ +----------+ | | +----------------------------------------------------------+ | | | interrupt controller (PIC / GIC) | | | +----------------------------------------------------------+ | |──────────────────────────────────────────────────────────────────| | HARDWARE | | +----------+ +----------+ +----------+ +----------+ | | | CPU | | RAM | | Disk | | UART | | | | x86/ARM | | 512MB+ | | ATA/SD | | serial | | | +----------+ +----------+ +----------+ +----------+ | +------------------------------------------------------------------+
Memory Layout — x86-64
0x0000000000000000 +------------------------+
| Interrupt Vector Table | (IDT, 256 entries)
0x0000000000001000 +------------------------+
| GDT + TSS | (kernel/user segments)
0x0000000000002000 +------------------------+
| Page Tables (PML4) | (identity map 0-1GB)
0x0000000000100000 +------------------------+
| Kernel Code + Data | (1MB, .text .rodata .data .bss)
| entry.asm / main.c |
| shell / ext2 / ELF |
| kernel_stack (16KB) |
0x0000000000120000 +------------------------+
| syscall_stack (8KB) |
0x0000000000130000 +------------------------+
| Physical Memory Map | (510 MB free)
| ... |
0x0000000004000000 +------------------------+
| Userspace Programs | (ELF64 loaded at 0x400000)
| hello.elf / apps |
0x0000000010000000 +------------------------+
| Userspace Stack | (64KB, grows down)
0x0000000010010000 +------------------------+
Memory Layout — ARM64 (Raspberry Pi 5)
0x0000000000000000 +------------------------+
| GPU Firmware Reserved | (VideoCore memory)
0x0000000000080000 +------------------------+
| Kernel Code + Data | (kernel8.img loaded here)
| entry.S / main.c |
| vector table (VBAR_EL1)|
| kernel_stack (16KB) |
0x0000000000090000 +------------------------+
| Translation Tables | (MMU page tables)
0x0000000000100000 +------------------------+
| Kernel Heap |
| ... |
0x0000000001000000 +------------------------+
| Userspace Stack (EL0) | (16MB)
0x000000003BFFFFFF +------------------------+
| End of RAM (~1GB) |
0x00000000FE000000 +------------------------+
| Peripheral MMIO |
| GPIO / UART / EMMC2 |
0x00000000FF840000 +------------------------+
| GIC-400 (interrupts) |
0x00000000FFFFFFFF +------------------------+
Boot Sequence
x86-64 (GRUB2 Multiboot2)
BIOS/UEFI
|
v
GRUB2 bootloader
| loads kernel.elf at 0x100000
| enables A20 line
| enters protected mode
v
entry.asm: long_mode_entry
| reload GDT (kernel + user + TSS segments)
| set up IDT (256 entries)
| identity-map first 1GB (2MB pages)
| enable PIC, remap IRQs to 0x20-0x2F
| configure SYSCALL/SYSRET MSRs
| set up TSS (RSP0 for ring transitions)
v
kernel_main()
| serial_init() -- PL011/8250 UART
| idt_init() -- install exception handlers
| pmm_init() -- parse multiboot2 memory map
| heap_init() -- kernel malloc
| syscall_init() -- SYSCALL dispatch table
| vga_init() -- VGA text console
| shell_run() -- interactive CLI
v
pactor64> _
ARM64 (Raspberry Pi 5)
Power On
|
v
GPU firmware (start4.elf)
| loads kernel8.img to 0x80000
| CPU starts in EL2 (Hypervisor)
v
entry.S: _start
| check CurrentEL register
| if EL2: configure HCR_EL2, drop to EL1 via ERET
| set up stack pointer (16KB kernel stack)
| zero BSS section
| init PL011 UART (115200 baud, 8N1)
v
kernel_main()
| print boot banner
| [Phase 2] GIC-400 init, timer setup
| [Phase 3] MMU init, translation tables
| [Phase 4] SVC handler, userspace (EL0)
| [Phase 5] EMMC2 SD card, ext2 filesystem
| shell_run() -- interactive CLI
v
pactor64> _
Syscall Flow
x86-64: SYSCALL / SYSRET
Userspace (Ring 3) Kernel (Ring 0)
================ ================
mov rax, 1 (sys_write) syscall_entry:
mov rdi, 1 (fd=stdout) save user RSP to [user_rsp]
lea rsi, [msg] (buffer) switch to syscall_stack
mov rdx, 13 (count) save all registers
syscall read syscall number from RAX
| dispatch: syscall_table[rax]
| ──── CPU transitions ────> sys_write(rdi, rsi, rdx)
| STAR/LSTAR MSRs return value in RAX
| CS=0x08, SS=0x10 restore all registers
| restore user RSP
| SYSRET
| <─── CPU transitions ──── RCX=user_rip, R11=user_rflags
v back to ring 3
continue execution
ARM64: SVC / ERET
Userspace (EL0) Kernel (EL1)
================ ================
mov x8, #64 (sys_write) vector_table[0x400]:
mov x0, #1 (fd=stdout) save x0-x30, sp_el0, elr_el1
ldr x1, =msg (buffer) switch to kernel stack
mov x2, #13 (count) read syscall number from x8
svc #0 dispatch: syscall_table[x8]
| sys_write(x0, x1, x2)
| ──── CPU transitions ────> return value in x0
| VBAR_EL1 + offset 0x400 restore all registers
| EL changes from 0 to 1 ERET
| back to EL0
| <─── CPU transitions ────
v
continue execution
Interrupt Handling
x86-64 (8259 PIC)
Hardware IRQ PIC Remap IDT Entry Handler
============ ========= ========= =======
IRQ 0 (Timer) ---> INT 0x20 ---> idt[32] ---> isr_timer()
IRQ 1 (Keyboard) ---> INT 0x21 ---> idt[33] ---> isr_keyboard()
IRQ 14 (ATA) ---> INT 0x2E ---> idt[46] ---> isr_ata()
...
IRQ 7 (Spurious) ---> INT 0x27 ---> idt[39] ---> (ignored)
Exceptions:
INT 0x00 (Div0) idt[0] ---> exception_handler(0)
INT 0x06 (InvOp) idt[6] ---> exception_handler(6)
INT 0x0D (GPF) idt[13] ---> exception_handler(13)
INT 0x0E (PageFault) idt[14] ---> exception_handler(14)
ARM64 (GIC-400)
Source GIC IRQ Vector Offset Handler ====== ======= ============= ======= CNTP (Timer/PPI14) IRQ 30 ---> 0x280 (EL1 IRQ) ---> irq_handler() UART0 (PL011) IRQ 33 ---> 0x280 (EL1 IRQ) ---> uart_irq() SVC #0 (sync) ---> 0x400 (EL0 sync) ---> svc_handler() Exception Vector Table (VBAR_EL1): 0x000 EL1 SP0 sync 0x400 EL0 AArch64 sync (SVC, faults) 0x080 EL1 SP0 IRQ 0x480 EL0 AArch64 IRQ (timer, peripherals) 0x100 EL1 SP0 FIQ 0x500 EL0 AArch64 FIQ 0x180 EL1 SP0 SError 0x580 EL0 AArch64 SError 0x200 EL1 SPx sync 0x600 EL0 AArch32 sync 0x280 EL1 SPx IRQ 0x680 EL0 AArch32 IRQ 0x300 EL1 SPx FIQ 0x700 EL0 AArch32 FIQ 0x380 EL1 SPx SError 0x780 EL0 AArch32 SError
Userspace Execution
"execute fibonacci"
|
v
shell.c: cmd_execute("fibonacci")
|
v
app_binaries.h: find_app("fibonacci")
| returns embedded ELF64 binary
v
elf.c: elf64_load(binary, size)
| validate ELF magic/class/machine
| load PT_LOAD segments to 0x400000
| set up user page tables (U/S bit)
| allocate user stack at 0x10000000
v
enter_userspace(entry_point, user_stack_top)
| save kernel RSP
| build IRETQ frame (or SYSRET registers)
v
┌─────────────────────────────────────────┐
│ Ring 3 / EL0 │
│ _start -> main() -> printf() -> SVC │
│ libc provides syscall wrappers │
└─────────────────────────────────────────┘
|
| exit(0) -> SVC #93 (or SYSCALL 60)
v
return_to_kernel
| restore kernel segments (CS=0x08, SS=0x10)
| restore kernel RSP
| IRETQ back to shell
v
pactor64> _
Filesystem Stack
+--------------------------------------------------+ | shell (commands) | | mount / ls / cat / execute | +--------------------------------------------------+ | ext2 filesystem | | superblock | block groups | inodes | dir | | read-only driver, traverses inode tree | +--------------------------------------------------+ | block device (ATA PIO) | | LBA28 read, ports 0x1F0-0x1F7 | | primary/secondary, master/slave detection | +--------------------------------------------------+ | disk hardware | +--------------------------------------------------+ ARM64 equivalent: ext2 -> EMMC2 SD card driver (BCM2712)
Build Toolchain
Source Files Toolchain Output
============ ========= ======
*.c (C code) ──-> clang-21 ──-> *.o ─┐
├──-> ld.lld-21 ──-> kernel.elf
*.S (ASM) ──-> clang-21 ──-> *.o ─┘ │
v
llvm-objcopy-21
│
x86-64: ARM64:
kernel.elf kernel.elf
| |
GRUB2 mkrescue objcopy -O binary
| |
pactor64.iso kernel8.img
No GNU tools used. Pure LLVM/Clang toolchain.
Technical Specifications
| Kernel Language | C + Assembly (x86-64 NASM / ARM64 GNU AS via Clang) |
|---|---|
| Compiler | LLVM/Clang 21 (no GCC, no GNU tools) |
| x86-64 Boot | GRUB2 Multiboot2, loads at 0x100000 |
| ARM64 Boot | Pi 5 GPU firmware, loads kernel8.img at 0x80000 |
| Page Size | 2MB (x86-64 huge pages), 4KB (ARM64) |
| Syscall ABI | Linux-compatible (x86-64: SYSCALL, ARM64: SVC) |
| Interrupts | x86: 8259 PIC @ 100Hz PIT | ARM64: GIC-400 + Generic Timer |
| Serial Console | x86: 8250 UART (0x3F8) | ARM64: PL011 (0xFE201000) |
| Filesystem | Read-only ext2 (ATA PIO on x86, EMMC2 on ARM64) |
| Memory | Physical page allocator, kernel heap, identity-mapped |
| Userspace | Ring 3 (x86) / EL0 (ARM64), ELF64 loader, minimal libc |
| Applications | 8 embedded: fibonacci, primes, sort, matrix, guess, ascii, hello, llc |
| LLVM Integration | LLVM 21.1.8 built from source, static binary, runs in ring 3 |
| Target Hardware | x86-64 (QEMU/desktop), ARM64 Raspberry Pi 5 (Cortex A76, BCM2712) |