Claude Code keeps per-project memory at <home>/.claude/projects/<key>/,
where <key> is the project's absolute path with every separator and the
drive colon turned into a dash. That makes it both rename-fragile and
machine-specific, and this project has hit each of those once:
- D:\DEV\Schunix -> D:\DEV\SchOS changed the key, and 43 memories were
invisible until moved across by hand.
- Development happens from Windows and from Linux, and each looks in a
different place for the same checkout.
Committing .claude/memory/ fixes both -- git carries it across renames
and between hosts -- and `import` puts it wherever the local machine
expects. .claude/settings.local.json stays ignored: those are per-machine
permissions.
The colon maps to a dash rather than being dropped. Deleting it gives
D-DEV-SchOS, which matches nothing and silently finds zero memories; that
was the first attempt. On Git Bash the key comes from `cygpath -w`,
because Claude Code is a Windows program and sees D:\DEV\SchOS, not
/d/DEV/SchOS.
59 lines
3 KiB
Markdown
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/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.
|