feat: wire display + input servers to snake, fix QEMU 11.x GPU bug

VirtIO GPU: QEMU 11.x has RESOURCE_ATTACH_BACKING (0x0104) and
RESOURCE_FLUSH (0x0106) command types swapped in its legacy MMIO
VirtIO GPU implementation. Workaround: send swapped type values.
Confirmed via QEMU monitor (xp shows correct bytes in memory)
and QEMU trace events (device dispatches to wrong handler).

Display pipeline now works end-to-end:
  adapter → GPU init → create_2d → attach_backing → set_scanout
  display-server → clear(blue) → flush → transfer + resource_flush
  snake → draw commands via IPC → display renders → flush to GPU

Input server:
  - New driver-input-uart crate (reads UART at mapped VA 0x20000)
  - New bins/input-qemu composition root
  - Adapter loads input-server, maps UART MMIO into its address space
  - Init delegates both display_ep (slot 0) and input_ep (slot 1) to snake
  - WASD keys → UART → input-server → IPC → snake direction change

Snake game runs with display and input, exits on wall collision.
This commit is contained in:
2026-10-18 21:10:42 +02:00
parent 7c7e3b8748
commit 27be73f42d
19 changed files with 363 additions and 32 deletions

View File

@@ -13,6 +13,8 @@ const CMD_READ_FILE: usize = 1;
fn create_cap() -> CapSlot { CapSlot::new(0).unwrap() }
fn storage_ep() -> CapSlot { CapSlot::new(2).unwrap() }
fn display_ep() -> CapSlot { CapSlot::new(3).unwrap() }
fn input_ep() -> CapSlot { CapSlot::new(5).unwrap() }
fn debug_print(s: &[u8]) {
for &b in s {
@@ -124,11 +126,9 @@ struct ServerInfo {
}
const SERVERS: &[ServerInfo] = &[
ServerInfo { filename: b"input.elf", name: b"input" },
ServerInfo { filename: b"log.elf", name: b"log" },
ServerInfo { filename: b"permis.elf", name: b"permis" },
ServerInfo { filename: b"session.elf", name: b"session" },
ServerInfo { filename: b"snake.elf", name: b"snake" },
];
pub fn run(shared_buf_va: usize) -> ! {
@@ -165,6 +165,17 @@ pub fn run(shared_buf_va: usize) -> ! {
debug_print(b")\n");
}
// Load snake — give it display endpoint (slot 0) and input endpoint (slot 1)
debug_print(b"init: loading snake... ");
if let Some(snake) = load_binary(shared_buf, b"snake.elf") {
syscall::delegate(display_ep(), snake.process_cap, ipc_perms);
syscall::delegate(input_ep(), snake.process_cap, ipc_perms);
syscall::spawn_thread_in(snake.process_cap, snake.entry_point, USER_STACK_TOP);
debug_print(b"ok\n");
} else {
debug_print(b"SKIP\n");
}
debug_print(b"init: all loaded, supervising\n");
loop {