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 LanguageC + Assembly (x86-64 NASM / ARM64 GNU AS via Clang)
CompilerLLVM/Clang 21 (no GCC, no GNU tools)
x86-64 BootGRUB2 Multiboot2, loads at 0x100000
ARM64 BootPi 5 GPU firmware, loads kernel8.img at 0x80000
Page Size2MB (x86-64 huge pages), 4KB (ARM64)
Syscall ABILinux-compatible (x86-64: SYSCALL, ARM64: SVC)
Interruptsx86: 8259 PIC @ 100Hz PIT | ARM64: GIC-400 + Generic Timer
Serial Consolex86: 8250 UART (0x3F8) | ARM64: PL011 (0xFE201000)
FilesystemRead-only ext2 (ATA PIO on x86, EMMC2 on ARM64)
MemoryPhysical page allocator, kernel heap, identity-mapped
UserspaceRing 3 (x86) / EL0 (ARM64), ELF64 loader, minimal libc
Applications8 embedded: fibonacci, primes, sort, matrix, guess, ascii, hello, llc
LLVM IntegrationLLVM 21.1.8 built from source, static binary, runs in ring 3
Target Hardwarex86-64 (QEMU/desktop), ARM64 Raspberry Pi 5 (Cortex A76, BCM2712)