display: resilient scanout — supervised driver, survive loss, re-attach (v2 V6)

The compositor now survives the virtio-gpu driver dying and re-attaches when device-manager
restarts it — the last piece of display v2.

Three parts:

- The driver hellos the device manager (role: bus). It never did, so the manager — which
  spawns it supervised and expects a hello — was stopping it at the 3s hello deadline every
  run (the gate markers just printed first). Now it is properly supervised: not stopped for
  silence, and restarted on death.

- A kernel IPC fix so a call to a dead service errors instead of hanging. An endpoint records
  its owner; when that task dies, its registered endpoints are marked dead (and any parked
  senders woken with -EPEER), so ipc_call returns -EPEER rather than blocking on a reply that
  will never come. Without this the compositor's first present after the driver died blocked
  forever. General robustness — any client of any service benefits.

- The compositor re-attaches. Its .scanout calls now fail cleanly (caught), freezing the last
  frame; when the restarted driver re-announces, attach_scanout detects the backend is already
  virtio and logs "scanout re-attached", mapping the fresh shared surface and re-looking-up
  .scanout. (The previous shm mapping leaks — no shm_unmap syscall yet — but its frames are the
  dead driver's, reclaimed on exit.)

- device-manager gains a "test-scanout-restart" mode (like test-usb-restart) that kills the
  virtio-gpu driver once after it hellos; the displayReattachTest kernel scenario drives it.

Gate: python3 test/qemu_test.py display-reattach — "scanout upgraded to virtio-gpu" then
"scanout re-attached", no CPU exception, passing 3/3. host tests, ipc/ipc-call/ipc-cap,
supervision, shm, display-service, display-demo, virtio-gpu, display-native, and
display-modeset all pass; default zig build clean. v2 (V1-V6) complete.
This commit is contained in:
Daniel Samson
2026-07-14 13:10:21 +01:00
parent 4231301896
commit 0217662808
10 changed files with 160 additions and 13 deletions
+12 -2
View File
@@ -224,6 +224,13 @@ fn attachScanout(stride: u32, width: u32, height: u32, format: u32, capability:
if (width == 0 or height == 0 or stride < width) return fail(reply);
const mapped = runtime.shm.map(cap) orelse return fail(reply);
const scanout = ipc.lookup(.scanout) orelse return fail(reply);
// A second announce means the driver died and was restarted (V6): re-attach to its fresh
// scanout. (The previous shared mapping leaks — there is no shm_unmap syscall yet — but the
// frames are the dead driver's, reclaimed on its exit; a handful across a crash is benign.)
const reattach = switch (backend) {
.virtio => true,
else => false,
};
backend = .{ .virtio = .{
.pixels = @ptrCast(@alignCast(mapped)),
@@ -236,9 +243,12 @@ fn attachScanout(stride: u32, width: u32, height: u32, format: u32, capability:
background = protocol.pack(format, 0x20, 0x30, 0x48); // re-pack the wallpaper for the mode
addDamage(screenRect()); // the whole new surface must be painted
pending_native_verify = true;
pending_modeset_check = true;
if (!reattach) pending_modeset_check = true; // the mode-set self-check runs once, on first upgrade
_ = system.timerOnce(service_endpoint, 50); // present once the driver is serving .scanout
_ = system.write("display: scanout upgraded to virtio-gpu\n");
_ = system.write(if (reattach)
"display: scanout re-attached\n"
else
"display: scanout upgraded to virtio-gpu\n");
return ok(reply);
}