14 KiB
14 KiB
UniversalisOS RISC-V S-mode Paravirtualized Hypervisor — PikeOS 5.0 Parity Plan
Date: 2026-07-09
Scope: Port UniversalisOS S-mode paravirtualized hypervisor to RISC-V (RV64) on the PolarFire SoC Icicle Kit and align functionality with PikeOS 5.0, using Jailhouse, seL4, and Bao as reference implementations.
Primary reference: PikeOS 5.0 ukernel sources (ARMv7hf) under src/sources/ukernel-arm_v7hf/.
PikeOS source location: /home/fabiorafaelcoutada/portugalfuturista/universalisos/src (PikeOS 5.0 distribution).
Important: The Icicle Kit U54 cores do not implement the RISC-V H-extension. The hypervisor therefore runs in S-mode and guests run in U-mode, with privileged operations mediated by ecall hypercalls. This is a paravirtualized design, not a hardware-virtualized (type-1) design.
1. Reference Codebase Assessment
1.1 PikeOS 5.0 (universalisos/src)
- Status in source drop: ARMv7/ARMv8, PowerPC e500/e500mc/e5500, x86-64 ukernels are present.
- RISC-V status: Only toolchain/RPM target macros exist (
config/rpm/targets/riscv_rv64-linux); no ukernel source tree for RISC-V in this drop. - Hypervisor model: ARM-centric (
p4hwvirtheaders,hwvirt-linuxguest drivers, HVC protocol). - What we reuse for RISC-V (S-mode paravirtualized):
- Partition/resource model (
respart.c,sys_respart.c). - Scheduling concepts (time partitioning + preemptive priority in
sched.c,tps.c). - Memory API shape (
p4map.h,p4mm.h). - Health monitoring / safety patterns (
hm.c). - KDEV device framework shape.
- Note: PikeOS H-extension / VS-mode concepts do not apply. We map PikeOS "task" to our "partition" and PikeOS "thread" to our "task" (schedulable entity).
- Partition/resource model (
1.2 Bao Hypervisor (reference for H-extension platforms)
- Strengths: Complete RISC-V H-extension type-1 static partitioning hypervisor; clean separation of portable core and arch code.
- Mechanisms we adopt where applicable:
- Sv39 page-table allocator and TLB management.
- SBI ecall proxy for guest OS compatibility.
- PLIC interrupt handling.
- 1:1 vCPU-to-pCPU assignment with static scheduling.
- Not applicable:
hstatus,hedeleg,hideleg,hgatp,hvip, VS-mode CSRs, two-stage translation, vPLIC / APLIC / AIA, RISC-V IOMMU — the Icicle Kit lacks the H-extension.
1.3 Jailhouse
- Strengths: Static partitioning, cell abstraction, comm regions, PCI pass-through, IVSHMEM.
- RISC-V status: No RISC-V support.
- Mechanisms we adopt:
- Cell-based static partitioning config.
- Per-cell comm region / hypercall ABI.
- Device assignment and IOMMU integration patterns.
- Memory region flags and loadable region semantics.
1.4 seL4
- Strengths: Verified microkernel, RISC-V S-mode support, capability-based security.
- Hypervisor status: No RISC-V H-extension; guest virtualization would be userland VMM.
- Mechanisms we adopt:
- Capability-based access control (already present in
cap/). - ASID management and TLB invalidation patterns.
- Trap entry/exit assembly discipline.
- Capability-based access control (already present in
2. PikeOS 5.0 → RISC-V S-mode Paravirtualized Feature Parity Map
| PikeOS 5.0 Feature | UniversalisOS ARM Status | RISC-V Target | Reference Files | Priority |
|---|---|---|---|---|
| S-mode bare-metal boot | ✅ Working | M-mode trampoline → S-mode (firmware=none) | boot.S, trap.S |
P0 |
| Exception/trap handling | ✅ Framework | S-mode trap vector + U-mode ecall hypercall | trap.S, exceptions.cpp |
P0 |
| UART console (NS16550a) | ✅ PL011 | NS16550a (Icicle MMUART0) | uart.cpp |
P0 |
| MMU / page tables | ✅ Section map | Sv39 identity + per-partition page tables | page_table.cpp |
P0 |
| Address-space isolation | ✅ PoC | Per-partition SATP (no VMID/ASID needed) | vm.cpp, memory.cpp |
P0 |
| Interrupt controller | ✅ GICv2 | Physical PLIC + paravirtualized IRQ routing | plic.cpp |
P0 |
| Timer tick | ✅ Generic Timer | CLINT mtimecmp (1 MHz) | timer.cpp |
P0 |
| Context switch | ⚠️ Partial | Task trap-frame save/restore + sret to U-mode |
context_switch_asm.S |
P0 |
| Guest virtual time | ⚠️ Framework | virtual_time + virtual_timer_deadline per partition |
vm.cpp, hypercall.cpp |
P1 |
| Guest OS boot | ⚠️ Framework | Load raw image, set a0/a1, sret to U-mode |
guest_loader.cpp, vm.cpp |
P1 |
| Device pass-through | ⚠️ Framework | MMIO mapped into guest SATP (no emulation) | vm.cpp |
P1 |
| Scheduling (RMS/DMS/ARINC 653) | ⚠️ Framework | PikeOS-style time-partition + priority scheduler | task_sched.cpp |
P1 |
| Inter-partition communication | ⚠️ Stub | Shared memory + doorbell IRQ (future) | — | P2 |
| Safety monitoring / HM | ⚠️ Stub | Health monitor events/actions | hm.cpp |
P2 |
PikeOS API (p4_* / uos_*) |
⚠️ Stub | Map to RISC-V ecall hypercalls |
hypercall.cpp |
P2 |
| Tooling / XSD codegen | ⚠️ Stub | Extend manifest generator for RISC-V | PikeOS xsdgen/ |
P3 |
3. RISC-V Architecture Strategy
3.1 Privilege Mode
- Hypervisor runs in RISC-V S-mode (Supervisor mode).
- Previous boot stage is either OpenSBI in M-mode (firmware path) or direct QEMU entry in M-mode (
firmware=none). - In the M-mode case, a tiny trampoline sets PMP, delegates exceptions/interrupts to S-mode, and
srets to_start_smode. - Guests run in U-mode (User mode) with their own
satppage tables. - No H-extension: All privileged operations are mediated by
ecallhypercalls.
3.2 Required RISC-V Extensions
rv64imacbase (U54 cores do not implement F/D).- H-extension NOT available on Icicle Kit U54 cores.
Zicsr,Zifencei.- Optional:
Sstc(per-hart timer),Svpbmt(PMA in PTEs) — not present on U54.
3.3 Memory Layout (Icicle Kit)
- Hypervisor loaded at
0x8020_0000. - RAM:
0x8000_0000—0xBFFF_FFFF(1 GiB low DDR). - PLIC:
0x0C00_0000. - CLINT:
0x0200_0000. - MMUART0 (NS16550a):
0x2000_0000.
3.4 Address-Space Isolation
- Hypervisor uses
satpwith Sv39 identity map (_boot_l1_pt). - Each guest partition uses its own
satpwith a private Sv39 root page table. - No two-stage translation (no
hgatp). Guest physical = host physical for mapped regions.
4. Implementation Roadmap
Phase A — RISC-V S-mode Paravirtualized Foundation ✅ COMPLETE
- Reference analysis (PikeOS, Bao, Jailhouse, seL4).
- M-mode trampoline → S-mode boot (
arch/riscv/boot.S). - NS16550a UART driver (
arch/riscv/uart.cpp). - Sv39 page-table allocator (
arch/riscv/page_table.cpp). - S-mode trap vector (
arch/riscv/trap.S) and C handler (arch/riscv/exceptions.cpp). - CLINT timer (
arch/riscv/timer.cpp) + PLIC skeleton (arch/riscv/plic.cpp). - Task context structure (
arch/riscv/vm.h) and assembly save/restore (arch/riscv/context_switch_asm.S). - Makefile
ARCH=riscvtarget. - Per-hart kernel stack in trap frame (
kernel_spfield). - Scheduler ready-queue fix (
in_ready_queueflag). - Guest virtual time / timer hypercall.
- Paravirtualized IRQ routing (
riscv_plic_route_irq). - Console hypercall with guest-VA translation.
- Memory map/unmap hypercalls.
- Partition reset / yield / IPI hypercalls.
- Multi-partition scheduling (time-partition windows).
Phase B — PikeOS Parity Core 🔄 IN PROGRESS
- PikeOS-style scheduler with time partitions / windows (
arch/riscv/task_sched.cpp/h). - PikeOS-style memory map API (
arch/riscv/memory.cpp/h). - Health monitoring hooks (
arch/riscv/hm.cpp/h). - Guest image loading / boot (
arch/riscv/guest_loader.cpp/h). - Paravirtualized PLIC IRQ routing to guests.
- Guest device tree generation (not needed for paravirtualized guests).
- Port partition lifecycle (
partition.c) — mapped tovm.cpp. - PikeOS API syscall mapping on RISC-V
ecall— partial inhypercall.cpp.
5. Files Added / Modified in This Session
New files
kernel/src/arch/riscv/csr.hkernel/src/arch/riscv/page_table.hkernel/src/arch/riscv/page_table.cppkernel/src/arch/riscv/trap.Skernel/src/arch/riscv/cpu.hkernel/src/arch/riscv/cpu.cppkernel/src/arch/riscv/vm.hkernel/src/arch/riscv/vm.cppkernel/src/arch/riscv/context_switch_asm.Skernel/src/arch/riscv/context_switch.cppkernel/src/arch/riscv/timer.hkernel/src/arch/riscv/timer.cppkernel/src/arch/riscv/plic.hkernel/src/arch/riscv/plic.cppkernel/src/arch/riscv/sbi.hkernel/src/arch/riscv/sbi.cppkernel/src/arch/riscv/task_sched.hkernel/src/arch/riscv/task_sched.cppkernel/src/arch/riscv/memory.hkernel/src/arch/riscv/memory.cppkernel/src/arch/riscv/hm.hkernel/src/arch/riscv/hm.cppkernel/src/arch/riscv/guest_loader.hkernel/src/arch/riscv/guest_loader.cppkernel/src/arch/riscv/hypercall.hkernel/src/arch/riscv/hypercall.cppkernel/src/arch/riscv/exceptions.hkernel/src/arch/riscv/exceptions.cppkernel/src/arch/riscv/smp.hkernel/src/arch/riscv/smp.cppkernel/src/arch/riscv/boot.Skernel/src/arch/riscv/linker_polarfire.ldkernel/src/arch/riscv/uart.hkernel/src/arch/riscv/uart.cppkernel/src/arch/riscv/board_icicle.hkernel/src/arch/riscv/kernel.cpp
Renamed files (old → new)
kernel_riscv.cpp→kernel.cppsched_pikeos.cpp→task_sched.cppsched_pikeos.h→task_sched.hmem_pikeos.cpp→memory.cppmem_pikeos.h→memory.hguest_boot.cpp→guest_loader.cppguest_boot.h→guest_loader.hhcall.cpp→hypercall.cpphcall.h→hypercall.h
6. Notes & Risks
- S-mode paravirtualized design: The Icicle Kit U54 cores lack the H-extension. The hypervisor runs in S-mode, guests in U-mode, and all privileged operations are mediated by
ecall. This is a different architecture from the HS-mode / VS-mode design originally planned. - No RISC-V toolchain in current environment:
riscv64-unknown-elf-g++/qemu-system-riscv64are not installed in this environment. Code is written for cross-compilation on a host with the toolchain; syntax correctness has not been verified locally. - PikeOS RISC-V source absent: We cannot copy PikeOS RISC-V code; we implement equivalent behavior using PikeOS ARM ukernel patterns and align data structures with PikeOS semantics.
- QEMU firmware=none path: The M-mode trampoline in
boot.Shandles direct QEMU entry. When using OpenSBI, the firmware path skips the trampoline and enters directly in S-mode. - Secondary harts: Currently parked in
wfiloops. Per-hart scheduler state and SMP scheduling are future work.
7. File-Level PikeOS → RISC-V S-mode Mapping
| PikeOS 5.0 Source (ARM ukernel) | RISC-V UniversalisOS Equivalent | Notes |
|---|---|---|
sources/ukernel-arm_v7hf/src/main.c |
arch/riscv/kernel.cpp |
Bare-metal entry, subsystem init. |
sources/ukernel-arm_v7hf/arch/arm/src/aexcpt.S |
arch/riscv/trap.S |
Trap entry/exit (S-mode). |
sources/ukernel-arm_v7hf/arch/arm/src/cexcpt.c |
arch/riscv/exceptions.cpp |
C trap dispatch (U-mode ecall → hypercall). |
sources/ukernel-arm_v7hf/arch/arm/src/mmu.c |
arch/riscv/page_table.cpp |
Sv39 page tables (no G-stage). |
sources/ukernel-arm_v7hf/src/sched.c / tps.c |
arch/riscv/task_sched.cpp |
Time partitioning + priority scheduler. |
sources/ukernel-arm_v7hf/src/int.c |
arch/riscv/plic.cpp |
Physical PLIC + paravirtualized IRQ routing. |
sources/ukernel-arm_v7hf/src/task.c / thread.c |
arch/riscv/vm.cpp |
Partition / task lifecycle. |
sources/ukernel-arm_v7hf/src/respart.c |
respart.cpp (future) |
Physical partition allocator (architecture-neutral). |
sources/ukernel-arm_v7hf/src/uos_kdev_*.c |
TBD | Kernel device framework. |
sources/ukernel-arm_v7hf/src/hm.c |
arch/riscv/hm.cpp |
Health monitoring / safety. |
8. Build & Run Commands
# ARM build (default, verified working)
cd /home/fabiorafaelcoutada/portugalfuturista/universalisos/kernel
make ARCH=arm clean && make ARCH=arm
# RISC-V build (requires riscv64-unknown-elf-g++ and qemu-system-riscv64)
make ARCH=riscv clean && make ARCH=riscv
make ARCH=riscv run
9. Known Limitations of This Session
- No RISC-V toolchain in this environment: The code is written against the RISC-V ISA and has not been compiled or executed here. Syntax/semantics errors may exist.
- Guest execution is not yet exercised:
riscv_task_run()sets upsatpand enters U-mode viasret, but a real guest image and MMIO emulation path are still TODO. - Device pass-through is skeletal: Only the PLIC and UART drivers are present; IOMMU, virtio, and PCI are not implemented.
- PikeOS API parity is partial: Only the capability and resource-partition foundations are shared with the ARM build; the full
uos_*/p4_*API surface is still being mapped. - SMP is not active for RISC-V: Secondary harts park; per-hart scheduler state and SMP scheduling are future work.
- No H-extension: The Icicle Kit U54 cores do not implement the RISC-V H-extension. The design is S-mode paravirtualized, not type-1 hardware-virtualized.
10. Next Immediate Steps
- Install/obtain
riscv64-unknown-elf-g++andqemu-system-riscv64and fix any compile errors. - Provide a minimal guest image (e.g., a tiny bare-metal RV64 binary) and test
riscv_task_run(). - Implement paravirtualized virtio-console or block device so guests can perform I/O.
- Port the PikeOS
p4_*API surface to RISC-Vecallhypercalls. - Map PikeOS
respart.c,task.c, andhm.csemantics onto the RISC-V S-mode paravirtualized model.