Architecture

Design Goals

  • Bare-metal execution — boot from firmware directly into EL2 with no Linux dependency at runtime.

  • Multi-guest support — run two or more guest VMs with independent virtual address spaces and device assignments.

  • Hardware-assisted virtualization — leverage Armv8-A VHE and Stage-2 translation for memory isolation.

  • Minimal trusted code base — keep the hypervisor small and auditable; push complexity into guests.

  • Educational clarity — serve as a readable reference for Arm virtualization on real hardware.

Exception Level Layout

┌──────────────────────────────────────────────────┐
│                   Guest OS (EL1)                 │
│              Linux / RTOS / bare-metal           │
├──────────────────────────────────────────────────┤
│               HyperBerry (EL2)                   │
│  ┌───────────┬───────────┬──────────┬──────────┐ │
│  │  vCPU     │  Stage-2  │  vGIC    │  vTimer  │ │
│  │  Sched    │  MMU      │          │          │ │
│  └───────────┴───────────┴──────────┴──────────┘ │
├──────────────────────────────────────────────────┤
│               Hardware (EL3 / TF-A)              │
└──────────────────────────────────────────────────┘

HyperBerry occupies EL2. Guests run at EL1 and are isolated via Stage-2 address translation. Virtual interrupts and timers are managed by the hypervisor.

Boot Sequence

The AArch64 assembly entry point (boot.S) runs before any C++ code:

  1. Park all non-zero cores in a wfe spin loop.

  2. Verify EL2 via CurrentEL — park core 0 if not at EL2.

  3. Configure HCR_EL2: set RW bit to force AArch64 guests.

  4. Configure SCTLR_EL2: disable MMU, D-cache, I-cache until page tables are ready.

  5. Configure CNTHCTL_EL2: grant guests access to the physical counter and timer.

  6. Shadow MIDR/MPIDR into VPIDR/VMPIDR.

  7. Zero the .bss section using linker-exported symbols.

  8. Set SP_EL2 to __stack_end and branch to hmain().

Development Roadmap

Phase 0 — Bootstrap (current)
  • [x] Enter EL2, initialize BSS, set up EL2 stack

  • [x] PL011 UART driver for early debug output

  • [ ] Exception vector table and synchronous exception handling

Phase 1 — Memory Management
  • [ ] Physical page allocator (buddy or bitmap)

  • [ ] EL2 Stage-1 page tables

  • [ ] Stage-2 page tables (guest IPA → PA translation)

Phase 2 — Single Guest
  • [ ] Load a flat binary guest image into isolated memory

  • [ ] Context switch: save/restore EL1 system registers

  • [ ] Trap and emulate essential system registers

Phase 3 — Interrupt Virtualization
  • [ ] GIC-400 distributor and CPU interface initialization

  • [ ] Virtual interrupt injection via List Registers

  • [ ] Route physical interrupts to the correct guest

Phase 4 — Multi-Guest
  • [ ] vCPU scheduler (round-robin or fixed time-slice)

  • [ ] Per-VM Stage-2 address spaces with VMID tagging

Phase 5 — Device Passthrough & Virtio
  • [ ] MMIO trap-and-emulate for shared devices

  • [ ] Virtio-mmio transport for virtual block/network devices