Repository navigation
virtio-gpu leaves the kernel: the compositor drives it through its claim and follows the host's display - #925
Conversation
The kernel had the only virtio-gpu driver, behind a `Gpu` trait and four `SYS_GPU_*` syscalls the compositor and the console called through the framebuffer claim. The compositor now claims `pci:1af4:1050` and drives the function itself over `toyos-virtio`; the kernel keeps only the firmware's framebuffer, which a `framebuffer` claim maps as one scanout. - `system/compositor/virtio-gpu` (`toyos-virtio-gpu`): the 2D commands of Virtio 1.2 §5.7 over the control and cursor queues in one grant. Every control command is fenced and its answer held to the fence, length and type; `RESP_ERR_OUT_OF_MEMORY` to the three commands that make a scanout declines a mode, any other error ends the device. A mode change is a page flip: the new scanout is lent, created, attached and drawn while the old one is on screen, and the old backing is given back only after `SET_SCANOUT` and its fenced `UNREF`. Every wake of the claim, inside a command's wait too, drains the cursor queue and reads `events_read`; the output is read after the events are cleared. Host-tested on a model of the device. - The compositor takes virtio first and the framebuffer otherwise (`display.rs`), starts at the device's preferred size clamped into `toyos-desktop`'s mode bounds (642x446 to 7680x4320) and flips to the size each display event asks for. `screen WxH` takes the same flip. - `toyos-virtio`'s `Live` reads and writes the device-specific structure. - pcidev: what a claim lends is bounded by its own window, `toyos_abi::pci::LEND_WINDOW` (256 MiB, two scanouts at the largest mode), apart from the 32 MiB grant bound. - Gone: `drivers/virtio_gpu.rs`, `gpu.rs`, the four `SYS_GPU_*` numbers and `toyos::gpu`, the claim's cursor and second scanout, the panic console's virtio arms, `console`'s presents, `abuse_gpu_resolution`, and the decline control with its `virtio-no-access-platform` actuator, by the orchestrator's ruling on PR #895. - `cargo run`'s Virtio profile on macOS opens `cocoa,zoom-to-fit=on`, so the window's size reaches the guest. - `the_compositor_drives_the_virtio_gpu` boots QEMU's virtio-gpu, reads the first frame off the scanout, resizes the display over VNC and reads the followed mode's frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Metal readbacks at head
The images that ran are the staged ones (sha256 in the README). On metal, the compositor's GOP path and the adapted mint control are unchanged in result. |
Review of #925 at
|
…t refusal is said - Every claim description installs one handle now, so the mint-rollback self-test could not go red for the defect it was written for: it goes with its actuator, its judge, its metal row, `install_all`, `stage_room` and `Region::empty`; a description is one `install`. - `toyos-desktop`'s fit assertion says that the window holds two of the largest scanouts only together: first-fit placement can leave no run for a mode past half of it, a flip declined with the old mode kept. `issues/a-lent-scanout-is-one-contiguous-run.md` records the sequence. - `InitRefusal`'s doc names `offer` and `accept`. - `issues/a-refused-framebuffer-reads-as-no-display.md` says what the virtio-gpu boot measured: the kernel's line is the same for both shapes. - The compositor ends on a virtio-gpu function it was given and cannot bring up rather than falling back; `HeadlessVirtioGpu` states the device's preferred size; the panic console's `detach`/`rearm` are private; the restarted-holder issue names its owner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
|
Review round 1 at
Suggestions taken: the VNC-boot comment now gives the configuration reason; Rerun:
The driver crate is unchanged, so m1–m5 stand. No bench rerun: Evidence: README. |
|
T14 The image sha256 is |
# Conflicts: # kernel/src/pcidev/mod.rs
|
Merged main
|
#925 moved virtio-gpu into the compositor behind `Display`. Kept both: - One layout for a mode and a scale: #925's `relayout(mode)` and this branch's `lay_out(scale)` are `lay_out(mode, scale)`, which `change_mode`'s flip, a display event and the display port's `screen scale` all take. A display event's panel scale is the base where no scale is kept or named by the image, so a host window's resize changes the mode and, only then, the panel's scale. - The display port's `screen WxH` takes #925's flip through `mode::follow`; a display that keeps the firmware's mode refuses it as `NoModes` (`Display::sets_modes`). `MSG_SET_RESOLUTION` stays gone. - `Display::set_cursor` takes the hot spot; the cursor is the display's where it has a plane and the sprite fits 64 pixels, emptied otherwise. - `mode::LEAST` is built from `TEXT_CELL`, and `Scale`'s least screen is it. - clipboardcase's compositor serves `display` beside #925's claim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
…w moves to P1 Conflicts: `usbd_spare` claims by arrival as #926 has every job do, in the shared `src/usbd_spare.rs` this branch moved its arms into: the one function of a spare's card the kernel does not drive, or, where it drives every one, the only one (the AMD bench's `03:00.3` and `03:00.4` share an id). `tests/toyos.rs` keeps #926's `drives` row beside this branch's refusal rows. `amdvi_usbd_drives_its_own_entry` leaves the registered AMD rows for P1's exit in `issues/there-is-no-wifi.md`: on the AMD bench `03:00.4`'s only BAR sits behind port `00:08.1`, whose window `0xd0000000..0xd0500000` bus 3 fills, so it cannot move to a 2 MiB slot of its own and stays where firmware put it, which only P1's 4 KiB pages hand over. Its jobs stay; its judge `amdvi_usbd` goes and comes back with P1 (at c648c14). `issues/an-amd-vi-machine-isolates-no-device.md` closes: its rows passed on the AMD bench at c648c14 (`amdvi_translates_the_stick_controller`, `amdvi_remaps_the_stick_controller` with `SmiFEn` and `SmiFLogEn` set, `amdvi_claim_refused_without_remapping`), its remaining claim reading is P1's. Every citation of it is rewritten. The MSI-X issue stays open, depending on P1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1
Stage 2 of
issues/the-desktop-draws-at-the-panels-scale.mdand the virtio-gpu half of stage 1 ofissues/every-driver-is-still-in-the-kernel.md, as the design accepted on #895 (comment) has it. Head9a1bff55e4769b70bcd9c8223913ba678e307d1a, with main ate136c77fdmerged (review round 1 at1ab1d9917; the claim is spelledpci:03:80:00/1af4:1050in #926's grammar).Problem and resulting behaviour
The kernel had the only virtio-gpu driver, behind a
Gputrait and fourSYS_GPU_*syscalls that the compositor andconsolecalled through theframebufferclaim. It asserted on device answers, allocated a second scanout nobody read, never askedGET_DISPLAY_INFO, floored the mode at 1280x720, and could not follow a host window.Now the compositor holds a
pci:1af4:1050claim (images/system.toml) through the ordinary claim path: BAR, one MSI-X entry, its IOMMU domain, grants and lends. It drives the function in-process. Virtio is taken first and the firmware's framebuffer otherwise. On metal (GOP) the compositor gets the same one-scanout framebuffer as before. NoSYS_GPU_*number is left insdk/abi/src/syscall.rs, and the kernel has no virtio-gpu code.system/compositor/virtio-gpu(toyos-virtio-gpu): Virtio 1.2 §5.7's 2D commands over the control and cursor queues, in one grant, ontoyos-virtio(no second transport). Pure and host-tested on a device model.RESP_ERR_OUT_OF_MEMORYtoRESOURCE_CREATE_2D,RESOURCE_ATTACH_BACKINGorSET_SCANOUTdeclines the mode and the old one stays.SET_SCANOUT, flush, then a fencedUNREFof the old one, and only after that the old backing is unlent.UPDATE_CURSOR/MOVE_CURSORunfenced. Usedlen0 is no answer (QEMU's, measured on The loader hands the panel's EDID to the compositor, which chooses the display's scale #895); 24 is an answer and is checked; anything else is refused.events_read. The output is read afterevents_clear(§5.7.4.2, §5.7.5).display.rs,session.rs):toyos-desktop's newmodebounds (least 642x446, the oldScalefloor moved there; largest 7680x4320). A disabled output gives the least mode.mode::followaccepts it.screen WxHtakes the same flip on virtio and is refused by name on GOP; it is still the window protocol'sMSG_SET_RESOLUTIONuntil thedisplayport of the scale issue's item 1.toyos_abi::pci::LEND_WINDOW= 256 MiB, apart from the unchanged 32 MiB grant bound.toyos-desktopasserts at compile time that two scanouts at the largest mode fit in it.toyos-virtio:Live::device_read32/device_write32, bounded to the device structure,FAILEDon a refusal, and host-tested.cargo runon macOS opens the Virtio profile with-display cocoa,zoom-to-fit=on, so a window resize reaches the guest's mode. Gop and Metal keepcocoa.What goes (measured against the merge base)
drivers/virtio_gpu.rs(649),gpu.rs(121), theSYS_GPU_*dispatch andsys_gpu_reset_scanout, the claim's cursor region and second scanout,remint, and the panic console's virtiodisable.VirtioDevice::init, and thevirtio-no-access-platformactuator withplatform_addressing.toyos::gpu(48), andFramebufferInfo's second scanout, cursor and flags.console's presents (it draws only on a GOP machine now).abuse_gpu_resolution(127), which guarded a syscall that is gone.declining_is_not_free, per the orchestrator's ruling on The loader hands the panel's EDID to the compositor, which chooses the display's scale #895: with the kernel driving only its console the actuator reached nothing.Profile::HeadlessVirtioGpustays.lib.rs650 andwire.rs148 production;tests.rs787),display.rs396,mode.rs176 including its tests, and the VNC client 74 (test harness).install_all,stage_roomandRegion::empty. Its staged T14/AMD run passed and proved nothing.Tests and evidence (README)
cargo run -- --build-onlycargo run -- --ci hostthe_compositor_drives_the_virtio_gpu(new, x86-64 q35,Profile::HeadlessVirtioGpu)iommu_virtio_platform,desktop_without_x2apic(GOP),screen_fatal_halt_composited(GOP),console_image_boots(GOP)What the new guest row establishes. The compositor drives QEMU's virtio-gpu through its claim, and a host display resize reaches the guest's mode. The row:
SetDesktopSize.compositor: mode 1024x768and screendumps the scanout again at that size.A screendump counts as drawn only if it has at least 64 colours: a scanout no frame reached is one colour, or QEMU's two-colour notice. The log shows the device's event read back as
display 1024x768, panel 260x195 mm, scale 1.Why a guest row: no metal machine has a virtio-gpu, and the host model is this design's own reading of §5.7, so only QEMU's device can say it was read right. It boots separately from the clipboard boot because its VNC display may give QEMU's clipboard a peer that the clipboard test's premise rules out. AArch64 is not covered, because a
virtboot hands over no PCI claim yet (issues/an-aarch64-cargo-run-boot-hands-over-no-pci-claim.md).Negative controls, as checked patches, each built and then reverted:
toyos-virtio-gputests:UNREFsent unfenced.SET_SCANOUT.Metal (round 0, head
883e496f7): staged with--metal-readbackforgop_edid_scale(the compositor's display row,metalcaseboot, T14 and AMD bench) andleak_rollback_selftest(the adapted mint control,shared-debugboot). Both benches then ran it, green:gop_edid_scaleT14 handle 0, 309x173 mm, 1.5; AMD handle 1, 309x174 mm, 1.5 (readbacks). The leak row is deleted. No bench rerun for round 1. Ongop_edid_scale's path, the framebuffer mint now uses oneinstallin place of a one-objectinstall_all, with the same effect; the GOP rowscreen_fatal_halt_compositedpasses in QEMU at the new head.Round 1 checks at
1ab1d9917(README):--build-onlyexit 0;--ci hostexit 0, 83 steps green; the new row, the clipboard row andscreen_fatal_halt_composited3/3. The driver crate is unchanged, so m1–m5 stand.Records
issues/the-gpu-driver-asserts-on-what-the-device-answers.mdandissues/the-second-scanout-buffer-is-read-by-nobody.md.issues/a-lent-scanout-is-one-contiguous-run.md: a mode change is declined when no contiguous run exists, though §5.7.6.1 takes scatter lists.issues/a-restarted-display-holder-lends-around-its-predecessors-scanouts.md: residue on a function no mechanism resets.lenmeasured).Risks and open points
LEND_WINDOWholds two scanouts at the largest mode only together. Lends are placed first-fit, so a small scanout left where it split the window can leave no run for a mode past half of it. That flip is declined, the old mode kept and logged. This is stated at the assertion and inissues/a-lent-scanout-is-one-contiguous-run.md.DEVICE_ANSWER(10 s) is policy for a wait's ceiling, not a measurement.followed()drops an event whose mode equals the current one even if only the EDID's mm changed. The scale is drawn at by nothing yet.🤖 Generated with Claude Code
https://claude.ai/code/session_016UzbDnM9m6nQWhbjGi6Lv1