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
+31
View File
@@ -23,6 +23,7 @@ const system = runtime.system;
const ipc = runtime.ipc;
const dp = runtime.display_protocol;
const sp = runtime.scanout_protocol;
const dm = runtime.device_manager_protocol;
const vp = @import("virtio-pci.zig");
const vg = @import("virtio-gpu-protocol.zig");
@@ -400,6 +401,11 @@ fn initialise(endpoint: ipc.Handle) bool {
}
log("virtio-gpu: scanout {d}x{d} online\n", .{ current_width, current_height });
// Hello the device manager so it counts us as up (and does not stop us at the hello
// deadline). A restarted instance re-hellos here and re-announces below — the compositor
// re-attaches to the fresh scanout (V6).
helloManager();
// Read the monitor's EDID (best-effort, when the device offers it) — the mode list a real
// driver derives from it; we log the preferred mode and keep our fixed offered list.
readEdid();
@@ -500,6 +506,31 @@ fn presentFull() bool {
return true;
}
/// Hello the device manager (role: bus — we own a PCI function, though we report no children):
/// the handshake that marks us up so the manager doesn't stop us at the hello deadline, and
/// (as a supervised driver) restarts us if we die. Best-effort: without a manager we still run.
fn helloManager() void {
var tries: u32 = 0;
const manager = while (tries < 100) : (tries += 1) {
if (ipc.lookup(.device_manager)) |h| break h;
system.sleep(20);
} else {
log("virtio-gpu: no device manager to hello\n", .{});
return;
};
const hello = dm.Hello{ .role = @intFromEnum(dm.Role.bus), .device_id = device_id };
var reply: [dm.reply_size]u8 = undefined;
const n = ipc.call(manager, std.mem.asBytes(&hello), &reply) catch {
log("virtio-gpu: hello call failed\n", .{});
return;
};
if (n < dm.reply_size or std.mem.bytesToValue(dm.HelloReply, reply[0..dm.reply_size]).status != 0) {
log("virtio-gpu: hello refused\n", .{});
return;
}
log("virtio-gpu: hello acknowledged\n", .{});
}
/// Announce the scanout to the display service so it upgrades off the GOP framebuffer: hand it
/// the shared surface as a capability plus the geometry. Best-effort and non-fatal — without a
/// display service (the standalone virtio-gpu bring-up test) the driver is still a valid