SchOS/.claude/memory/schunix-virtio-gpu.md
Nexoniarz a1c965da1e include: one folder per subsystem, and includes that name it
Sixty-five headers sat side by side in include/, so `#include "irq.h"`
said nothing about where irq.h was or what it belonged to, and errno.h,
stat.h and fcntl.h at the top shadowed the system's for any host tool
built with -I./include. They are in folders now -- arch/ core/ fs/
dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and
every include names the folder, as Linux's do: "core/proc.h".

Done mechanically and checked the hard way: the kernel built from this
tree disassembles identically to the one built from the tree before
it. The full image boots, and userland is the same set of programs.
Paths in docs and comments follow; docs/guides/layout.md has a table
of what is where, and tools/fix-includes.py rewrites old-style
includes from the folders in the tree, for code written before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
2026-10-23 15:05:12 +02:00

59 lines
3 KiB
Markdown

---
name: schunix-virtio-gpu
description: "virtio-gpu 2D driver — the display class's second implementation; how to run it and the transport details that matter."
metadata:
node_type: memory
type: project
originSessionId: 9d8a2aef-bcf0-47a0-96c6-f706efab4a95
modified: 2026-08-08T19:59:27.522Z
---
Written 2026-08-08 from the OASIS virtio 1.1 specification (chapters 2, 4.1,
5.7). `include/dev/virtio.h` + `kernel/drivers/virtio_gpu.c`. Worked on the first
boot.
virtio-gpu: 1280x800, 4000 KB framebuffer, queue 64
display: 1280x800 32bpp stride 5120
display: presented a full frame
**Run it with:** `-vga std -device virtio-gpu-pci`. Keep `-vga std` — the
bootloader draws the splash through VBE and there is no virtio path that early,
so a machine with *only* virtio-gpu boots blind until the kernel is up. Both
register as `DEVCLASS_DISPLAY`; `registry.c` lists virtio-gpu **first** so
`device_find_class()` returns it, and vga_pci still claims the stdvga card
underneath for the splash and text console.
**Why it matters over VBE:** presenting is explicit. VBE is a flat aperture with
no notion of a finished frame, so a compositor races the scanout. Here you
`TRANSFER_TO_HOST_2D` a rectangle then `RESOURCE_FLUSH` it, and the host never
shows a half-drawn frame. `acquire()` returns the guest-side framebuffer
directly — no separate back buffer is needed, because the host cannot see it
until the transfer. `wait_vblank` is deliberately null: whole rectangles are
atomic, so there is nothing to synchronise against, and the wrappers in
device.c handle a null op.
**Transport details that are easy to get wrong:**
- Structures live at an offset inside *whichever BAR the device names* in a
vendor-specific PCI capability (`PCI_CAP_ID_VNDR`, 0x09). Assuming BAR 0 works
on QEMU and is exactly the assumption that breaks on the next device.
- The status handshake order is not negotiable: reset → ACK → DRIVER → read
features → write features → FEATURES_OK → **read FEATURES_OK back** (the
device clears it to reject, and that readback is the only way it ever tells
you) → queues → DRIVER_OK.
- `VIRTIO_F_VERSION_1` is bit 32, so it lives in the *second* 32-bit window —
hence the feature-select registers.
- Notify address is `notify_base + queue_notify_off * notify_off_multiplier`;
the multiplier is a trailing field of the notify capability only.
- MMIO accessed at exact widths. The common config has 8/16/32-bit fields
adjacent, and a device may ignore a wrong-width access silently.
- 64-bit queue address registers are written as two 32-bit halves, low first.
Polled, not interrupt-driven: every caller wants the answer before continuing,
and the wait is microseconds. The poll loop is bounded so a wedged device
cannot hang boot.
`/proc/devices` name and driver columns are 14 wide because `virtio-gpu0` is
eleven characters and overran ten.
**Not done:** cursor queue, multiple scanouts, mode setting (the resolution is
whatever the host reports), resource reuse on resolution change, and 3D/virgl.