This commit is contained in:
MrARM
2026-07-07 00:25:38 -05:00
parent 8207a1e356
commit 7ff39227fe
89 changed files with 20141 additions and 408 deletions

141
docker-qemu-emulation.md Normal file
View File

@@ -0,0 +1,141 @@
# Docker/QEMU Emulation Scaffold
## Scope
Workspace-local implementation:
- `emulation/`
Purpose:
- Build a Docker-packaged QEMU environment for booting a generated copy of the extracted AArch64 rootfs.
- Expose the guest display through QEMU VNC and noVNC in a browser.
- Provide a browser dashboard for logs and early virtual switch events.
- Keep target rootfs evidence files unmodified.
Static-analysis boundary: this page documents the emulator scaffold and evidence-based design. Creating and booting `emulation/work/rootfs.ext4` executes a generated guest copy, not the extracted evidence files directly.
## Evidence Basis
The main game and SPIKE menu use a direct DRM/KMS display path rather than a desktop windowing path.
Confirmed string/import evidence:
- `/games/pokemon_pro/game` imports `libEGL.so.1`, `libGLESv2.so.2`, `libdrm.so.2`, and `libgbm.so.1`; see `analysis/static-triage/game.objdump-p.txt`.
- `/games/pokemon_pro/game` strings include `/sys/class/drm`, `/dev/dri/card1`, `/dev/dri/card0`, `drmModeSetCrtc fail`, `drmModePageFlip`, `gbm_bo_create`, `eglGetPlatformDisplayEXT`, and `egl resolution: %d x %d`; see `analysis/static-triage/game.strings`.
- `/games/pokemon_pro/spike3/spike_menu/game` has matching GBM/EGL/DRM strings at offsets including `0x382cd0` (`/sys/class/drm`), `0x383030` (`/dev/dri/card1`), `0x383058` (`/dev/dri/card0`), and `0x383730` (`drmModeSetCrtc fail`); see `analysis/static-triage/spike_menu_game.strings`.
- `/etc/init.d/S12lvds_panel` launches `/games/spike3/bin/boot_display` early, and `/etc/init.d/game_monitor` later stops `boot_display` before launching `/games/game`.
Implementation consequence: the first emulator path uses QEMU `virtio-gpu` and browser-visible VNC/noVNC, not X11 forwarding.
## Implemented Files
Primary files:
| Path | Purpose |
| --- | --- |
| `emulation/compose.yaml` | Docker Compose entry point and port mapping. |
| `emulation/docker/Dockerfile` | Debian-based image with QEMU, noVNC, ffmpeg, qemu-user-static, and AArch64 cross tools. |
| `emulation/docker/fetch-debian-arm64-kernel.sh` | Installs a Debian ARM64 kernel and initramfs into `/opt/spike3-kernel/`; the initramfs seeds DRM/`virtio_gpu` modules. |
| `emulation/scripts/prepare-rootfs-image.sh` | Copies target-root entries into `emulation/work/rootfs-stage`, injects helpers, and builds `emulation/work/rootfs.ext4`. |
| `emulation/scripts/run-qemu.sh` | Boots QEMU `virt` with `virtio-blk`, `virtio-gpu`, VNC, serial logging, user networking, and a virtio-serial control socket. |
| `emulation/guest/emu-init` | Guest init used by QEMU with `init=/usr/local/spike-emu/bin/emu-init`. |
| `emulation/dashboard/server.py` | Browser dashboard on port `8090` for links, logs, and virtual switch events. |
| `emulation/stubs/spike3emu_stub.c` | Optional AArch64 `LD_PRELOAD` stub for inert fake device opens/ioctls on GPIO, I2C, serial, input, and `/dev/mem` paths. |
Generated runtime files:
| Path | Purpose |
| --- | --- |
| `emulation/work/rootfs.ext4` | Generated guest root disk; not checked in as evidence. |
| `emulation/work/logs/` | Host/container logs for QEMU, dashboard, noVNC, and conagent backend. |
| `emulation/work/control.sock` | QEMU virtio-serial socket used by the dashboard event bridge. |
## Usage
Start the default boot-display target:
```sh
docker compose -f emulation/compose.yaml up --build
```
Open:
- Dashboard: `http://localhost:8090/`
- Display: `http://localhost:6080/vnc.html?host=localhost&port=6080&autoconnect=true`
- Conagent backend emulator: `http://localhost:8088/`
Try later targets after the virtual display is visible:
```sh
SPIKE3_AUTOSTART=spike-menu docker compose -f emulation/compose.yaml up
SPIKE3_AUTOSTART=game docker compose -f emulation/compose.yaml up
SPIKE3_AUTOSTART=monitors docker compose -f emulation/compose.yaml up
```
The guest init accepts these autostart targets:
- `boot-display`
- `spike-menu`
- `game`
- `monitors`
- `shell`
## Current Emulator Behavior
The generated guest image:
- Mounts `/proc`, `/sys`, `/dev`, `/dev/pts`, `/run`, and `/tmp`.
- Creates writable `/connectivity`, `/connectivity/dump`, `/data`, and `/tmp/cache/mesa`.
- Preserves `/games/game -> /games/pokemon_pro/game`.
- Injects `/usr/local/spike-emu/bin/launch-target.sh` to start `boot_display`, SPIKE menu, game, or monitors.
- Injects an optional `LD_PRELOAD` hardware stub at `/usr/local/spike-emu/lib/libspike3emu_stub.so` when the Docker image has `aarch64-linux-gnu-gcc`.
- Injects overlay Mesa DRI fallback drivers under `/usr/local/spike-emu/mesa-dri` when the Docker image has ARM64 `virtio_gpu`, `kms_swrast`, and `swrast` drivers.
- Starts a guest control agent that logs virtio-serial dashboard events to `/run/spike-emu/events.log` and `/connectivity/dump/log/spike-emu/control-agent.log`.
The dashboard:
- Links to noVNC and the existing conagent backend emulator.
- Reads host logs from `emulation/work/logs/`.
- Sends virtual switch/button events as JSON to `emulation/work/control.sock` when QEMU is running. Verified APIs are `POST /api/event` and `POST /api/switch/<name>`.
## Verification Status
Commands run from the workspace root:
```sh
docker compose -f emulation/compose.yaml build spike3-emu
docker compose -f emulation/compose.yaml run --rm --entrypoint /workspace/emulation/scripts/prepare-rootfs-image.sh spike3-emu
SPIKE3_SKIP_PREPARE=1 SPIKE3_AUTOSTART=boot-display docker compose -f emulation/compose.yaml up --force-recreate
```
Confirmed results:
- Docker image contains `/opt/spike3-kernel/vmlinuz` and `/opt/spike3-kernel/initrd.img`; the initramfs includes `drm.ko`, `drm_kms_helper.ko`, `virtio_dma_buf.ko`, and `virtio-gpu.ko`.
- QEMU boots the generated `emulation/work/rootfs.ext4` and reaches `SPIKE3 emulator init complete; autostart=boot-display` in `emulation/work/logs/qemu-serial.log`.
- QEMU serial log confirms `virtio-gpu-pci detected`, `Initialized virtio_gpu`, and `fb0: virtio_gpudrmfb frame buffer device`.
- Guest hardware log confirms `/dev/dri/card0`, `/dev/dri/renderD128`, `/sys/class/drm/card0`, `/sys/class/drm/card0-Virtual-1`, and loaded `virtio_gpu`/`drm` modules.
- noVNC responds at `http://localhost:6080/vnc.html`; the dashboard responds at `http://localhost:8090/api/status`.
- `POST /api/switch/start` returns `sent_to_guest: true` and appends a switch event to `emulation/work/dashboard-events.jsonl`.
Current blocker:
- `/games/spike3/bin/boot_display` is reached, but it still logs `create_window RETRY 1 / 27` through `27 / 27`, shader compile/link failures, and `cpuspi: device open failed`.
- A nonblank SPIKE frame is not yet confirmed. The next display pass should focus on the userspace Mesa/GBM/EGL path or a targeted display interposer.
## Limitations and Next Steps
Confirmed current limitations:
- The dashboard event path is only a guest-visible event log. It does not yet inject events into the games SPIKE nodebus model.
- The optional `LD_PRELOAD` stub is intentionally broad and inert. It can move early hardware probing forward, but any deterministic game failure still needs specific static/dynamic analysis before adding a targeted shim.
- QEMU `virtio-gpu` is not Raspberry Pi VC4/V3D. It is the right first display target because the binary asks for standard DRM/GBM/EGL surfaces, but shader/extension mismatches may still require a display interposer or patch.
- Docker Desktop on macOS runs this under QEMU TCG without KVM acceleration, so startup may be slow.
Next implementation targets:
1. Fix the remaining `boot_display` userspace rendering path so a nonblank noVNC frame is produced.
2. Run `spike-menu` before the full game because it uses the same display stack with a smaller binary/image payload.
3. Run `game` and capture the first deterministic hardware/display failure from serial logs and `/connectivity/dump/log/spike-emu/`.
4. Map dashboard switch events into a first SPIKE nodebus emulator, reusing recovered node command evidence from `main-game-behavior.md` and `topper-serial-key-emulator.md`.
5. Add targeted stubs only for confirmed failing APIs or device paths.