58 lines
3.1 KiB
Markdown
58 lines
3.1 KiB
Markdown
# T8-1.2f QEMU Runtime Test — Findings (2026-07-11)
|
|
|
|
## What Works
|
|
|
|
1. **Kernel builds with `PERSONALITY_BOOT=1`** — `make ARCH=aarch64 PLATFORM=qemu-aarch64-virt PERSONALITY_BOOT=1` produces a valid ELF.
|
|
2. **QEMU boots the EL2 hypervisor** — MP0 initializes UART, MMU, GICv3, timer, scheduler.
|
|
3. **Personality binary loads via QEMU `-device loader`** — `MP1: personality binary @ 0x0000000050000000 (loaded by QEMU)`.
|
|
4. **Personality starts executing** — the gate test banner `T8-1.2f: hardened_malloc GATE TEST` prints, and `Test 1: malloc(64) ...` starts.
|
|
|
|
## What Fails
|
|
|
|
The personality's `svc #0` syscalls (POSIX_SVC_MMAP, etc.) are **not handled** by the EL2 hypervisor. The hypervisor's `el2_guest_sync_handler` only handles `EC_HVC_AA64` (hypercalls via `hvc #0`), but the personality uses `svc #0` (supervisor calls, EC_SVC_AA64 = 0x15).
|
|
|
|
**Result:** `malloc(64)` returns NULL (the `svc #0` traps to EL2, which doesn't recognize it, and the return value is garbage/0).
|
|
|
|
## Root Cause
|
|
|
|
The musl personality is designed as a **native UOS task** using the POSIX_SVC_* ABI (`svc #0`, x8=syscall number). But the current aarch64 kernel architecture runs all payloads as **EL1 guests** under the EL2 hypervisor, which expects `hvc #0` (UOS_HV_* ABI).
|
|
|
|
The personality loader (`personality_loader.cpp`) creates a `task_context_t` and sets up the task, but the current boot path (`kernel_aarch64.cpp`) doesn't use it — it uses the vCPU/EL1 guest path instead.
|
|
|
|
## Two Paths Forward
|
|
|
|
### Path A: Run personality as native UOS task (correct long-term)
|
|
|
|
Modify `kernel_aarch64.cpp` to:
|
|
1. Use `personality_loader_create()` + `personality_loader_load_elf()` + `personality_loader_boot()` instead of the vCPU guest path
|
|
2. Add a `svc #0` handler in the EL2 trap handler that routes POSIX_SVC_* calls to the appropriate kernel services
|
|
3. The personality runs at EL1 (or EL0) as a native task, not as a virtualized guest
|
|
|
|
### Path B: Add SVC handling to EL2 guest trap (quick fix)
|
|
|
|
Add `EC_SVC_AA64` handling to `el2_guest_sync_handler`:
|
|
1. Decode `x8` as the POSIX_SVC_* number
|
|
2. Route `POSIX_SVC_MMAP` to a Stage-2 memory allocator
|
|
3. Route `POSIX_SVC_MPROTECT` to Stage-2 page table updates
|
|
4. etc.
|
|
|
|
This is a stopgap — the personality would still be a virtualized guest, not a native personality.
|
|
|
|
## Recommendation
|
|
|
|
Path A is the correct architecture for a musl POSIX personality. The personality should be a first-class UOS citizen, not a virtualized guest. This requires:
|
|
- Wiring the personality loader into the boot path
|
|
- Adding a POSIX syscall handler in the kernel
|
|
- Setting up the personality's address space via the UOS MMU (not Stage-2)
|
|
|
|
## Files Changed for This Test
|
|
|
|
- `kernel/Makefile` — added `run-personality` target, `PERSONALITY_BOOT=1` flag
|
|
- `kernel/src/arch/aarch64/kernel_aarch64.cpp` — added `UOS_PERSONALITY_BOOT` path (skips embedded payload, uses QEMU-loaded binary, entry=0x50000390)
|
|
|
|
## Verification
|
|
|
|
- Build: PASS (kernel builds with `PERSONALITY_BOOT=1`)
|
|
- Boot: PASS (QEMU boots, personality loads)
|
|
- Execution: PARTIAL (personality starts but syscalls fail)
|
|
- Gate tests: FAIL (malloc returns NULL due to unhandled `svc #0`)
|