universalisos/RISCV_PIKEOS_PARITY_PLAN.md

241 lines
14 KiB
Markdown

# 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 (`p4hwvirt` headers, `hwvirt-linux` guest 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).
### 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.
---
## 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 `sret`s to `_start_smode`.
- Guests run in **U-mode** (User mode) with their own `satp` page tables.
- **No H-extension:** All privileged operations are mediated by `ecall` hypercalls.
### 3.2 Required RISC-V Extensions
- `rv64imac` base (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 `satp` with Sv39 identity map (`_boot_l1_pt`).
- Each guest partition uses its own `satp` with 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
- [x] Reference analysis (PikeOS, Bao, Jailhouse, seL4).
- [x] M-mode trampoline → S-mode boot (`arch/riscv/boot.S`).
- [x] NS16550a UART driver (`arch/riscv/uart.cpp`).
- [x] Sv39 page-table allocator (`arch/riscv/page_table.cpp`).
- [x] S-mode trap vector (`arch/riscv/trap.S`) and C handler (`arch/riscv/exceptions.cpp`).
- [x] CLINT timer (`arch/riscv/timer.cpp`) + PLIC skeleton (`arch/riscv/plic.cpp`).
- [x] Task context structure (`arch/riscv/vm.h`) and assembly save/restore (`arch/riscv/context_switch_asm.S`).
- [x] Makefile `ARCH=riscv` target.
- [x] Per-hart kernel stack in trap frame (`kernel_sp` field).
- [x] Scheduler ready-queue fix (`in_ready_queue` flag).
- [x] Guest virtual time / timer hypercall.
- [x] Paravirtualized IRQ routing (`riscv_plic_route_irq`).
- [x] Console hypercall with guest-VA translation.
- [x] Memory map/unmap hypercalls.
- [x] Partition reset / yield / IPI hypercalls.
- [x] Multi-partition scheduling (time-partition windows).
### Phase B — PikeOS Parity Core 🔄 IN PROGRESS
- [x] PikeOS-style scheduler with time partitions / windows (`arch/riscv/task_sched.cpp/h`).
- [x] PikeOS-style memory map API (`arch/riscv/memory.cpp/h`).
- [x] Health monitoring hooks (`arch/riscv/hm.cpp/h`).
- [x] Guest image loading / boot (`arch/riscv/guest_loader.cpp/h`).
- [x] Paravirtualized PLIC IRQ routing to guests.
- [ ] Guest device tree generation (not needed for paravirtualized guests).
- [ ] Port partition lifecycle (`partition.c`) — mapped to `vm.cpp`.
- [ ] PikeOS API syscall mapping on RISC-V `ecall` — partial in `hypercall.cpp`.
---
## 5. Files Added / Modified in This Session
### New files
- `kernel/src/arch/riscv/csr.h`
- `kernel/src/arch/riscv/page_table.h`
- `kernel/src/arch/riscv/page_table.cpp`
- `kernel/src/arch/riscv/trap.S`
- `kernel/src/arch/riscv/cpu.h`
- `kernel/src/arch/riscv/cpu.cpp`
- `kernel/src/arch/riscv/vm.h`
- `kernel/src/arch/riscv/vm.cpp`
- `kernel/src/arch/riscv/context_switch_asm.S`
- `kernel/src/arch/riscv/context_switch.cpp`
- `kernel/src/arch/riscv/timer.h`
- `kernel/src/arch/riscv/timer.cpp`
- `kernel/src/arch/riscv/plic.h`
- `kernel/src/arch/riscv/plic.cpp`
- `kernel/src/arch/riscv/sbi.h`
- `kernel/src/arch/riscv/sbi.cpp`
- `kernel/src/arch/riscv/task_sched.h`
- `kernel/src/arch/riscv/task_sched.cpp`
- `kernel/src/arch/riscv/memory.h`
- `kernel/src/arch/riscv/memory.cpp`
- `kernel/src/arch/riscv/hm.h`
- `kernel/src/arch/riscv/hm.cpp`
- `kernel/src/arch/riscv/guest_loader.h`
- `kernel/src/arch/riscv/guest_loader.cpp`
- `kernel/src/arch/riscv/hypercall.h`
- `kernel/src/arch/riscv/hypercall.cpp`
- `kernel/src/arch/riscv/exceptions.h`
- `kernel/src/arch/riscv/exceptions.cpp`
- `kernel/src/arch/riscv/smp.h`
- `kernel/src/arch/riscv/smp.cpp`
- `kernel/src/arch/riscv/boot.S`
- `kernel/src/arch/riscv/linker_polarfire.ld`
- `kernel/src/arch/riscv/uart.h`
- `kernel/src/arch/riscv/uart.cpp`
- `kernel/src/arch/riscv/board_icicle.h`
- `kernel/src/arch/riscv/kernel.cpp`
### Renamed files (old → new)
- `kernel_riscv.cpp``kernel.cpp`
- `sched_pikeos.cpp``task_sched.cpp`
- `sched_pikeos.h``task_sched.h`
- `mem_pikeos.cpp``memory.cpp`
- `mem_pikeos.h``memory.h`
- `guest_boot.cpp``guest_loader.cpp`
- `guest_boot.h``guest_loader.h`
- `hcall.cpp``hypercall.cpp`
- `hcall.h``hypercall.h`
---
## 6. Notes & Risks
1. **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.
2. **No RISC-V toolchain in current environment:** `riscv64-unknown-elf-g++` / `qemu-system-riscv64` are not installed in this environment. Code is written for cross-compilation on a host with the toolchain; syntax correctness has not been verified locally.
3. **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.
4. **QEMU firmware=none path:** The M-mode trampoline in `boot.S` handles direct QEMU entry. When using OpenSBI, the firmware path skips the trampoline and enters directly in S-mode.
5. **Secondary harts:** Currently parked in `wfi` loops. 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/kdev_*.c` | TBD | Kernel device framework. |
| `sources/ukernel-arm_v7hf/src/hm.c` | `arch/riscv/hm.cpp` | Health monitoring / safety. |
## 8. Build & Run Commands
```bash
# 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
1. **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.
2. **Guest execution is not yet exercised:** `riscv_task_run()` sets up `satp` and enters U-mode via `sret`, but a real guest image and MMIO emulation path are still TODO.
3. **Device pass-through is skeletal:** Only the PLIC and UART drivers are present; IOMMU, virtio, and PCI are not implemented.
4. **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.
5. **SMP is not active for RISC-V:** Secondary harts park; per-hart scheduler state and SMP scheduling are future work.
6. **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
1. Install/obtain `riscv64-unknown-elf-g++` and `qemu-system-riscv64` and fix any compile errors.
2. Provide a minimal guest image (e.g., a tiny bare-metal RV64 binary) and test `riscv_task_run()`.
3. Implement paravirtualized virtio-console or block device so guests can perform I/O.
4. Port the PikeOS `p4_*` API surface to RISC-V `ecall` hypercalls.
5. Map PikeOS `respart.c`, `task.c`, and `hm.c` semantics onto the RISC-V S-mode paravirtualized model.