Login
Track U: USB
Login

xv6 §6, "Interrupts and device drivers". "A driver is the code in an operating system that manages a particular device: it configures the device hardware, tells the device to perform operations, handles the resulting interrupts, and interacts with processes using the device." Track U does that twice: Glint drives a real USB controller, and Glint is the device a guest's driver talks to.

Emulating a USB controller is the primary peripheral Glint captures, in the maintainer's words on the forum (glint 366ac226de). The plan already made USB native (Devices and the Linux guest): Glint owns the real controller and the USB tree behind it, and keeps the keyboard so the user can always reach it. Track U adds the guest's side. A guest sees an emulated USB host controller, and the devices behind it are ones Glint chooses to show it, never the real controller.

The controller is xHCI. Glint emulates an xHCI host controller, for four reasons:

x86_64 guests don't get it. Under the maintainer's choice A for x86 (devices only through I/O ports, no instruction decoder), an x86 guest can't reach an xHCI: its registers are only memory-mapped. QEMU registers xHCI's BAR 0 as 64-bit memory (hw/usb/hcd-xhci-pci.c line 165), and xHCI defines no I/O-port BAR. So the emulated controller is aarch64-only. Glint's own xHCI driver still runs on x86_64 (U.4), because driving a real controller traps nothing. On aarch64 a guest's loads and stores to the controller reach Glint with their size and register in the data-abort syndrome (5.1), so no decoder is needed there either.

Slices

U.1 The xHCI register file (aarch64). After Phase 5. The capability, operational, runtime and doorbell registers as a device model on 5.2's dispatcher, at a guest-physical address the test guest is told about. The test guest reads the capability registers and halts and resets the controller, as a driver's first steps do. It needs only 5.2 and 5.3, so it can land before Phase 6. Host specs check each register's reset value and writable bits against QEMU's model.

U.2 Rings and an empty root hub. After 6.7b, which gives virtual interrupts and an unmodified Linux guest. The command ring and event ring live in guest memory, read and written through translate. Glint answers No Op, Enable Slot and Address Device, and raises the event interrupt. With nothing attached, Linux's xHCI driver probes the controller and reports an empty root hub.

U.3 A virtual keyboard behind it. A HID boot-protocol keyboard model on a root port, fed from Glint's console. Linux sees a USB keyboard and types into its shell. It proves control and interrupt transfers end to end without any real USB hardware.

U.4 Glint's own xHCI driver. Glint drives QEMU's qemu-xhci on both machines, enumerates a usb-kbd, and reads keys from it, the trusted path that keeps the keyboard Glint's. It needs Phase 6's interrupts and DMA into pages Glint owns.

U.5 Forwarding. A device Glint enumerated in U.4 is shown to the guest through U.2's controller, with its transfers forwarded. Glint can withhold any device, and always withholds the keyboard it keeps. Mass storage first, since it meets Phase 10.

U.6 On Beagle hardware. U.4 and U.5 on BeaglePlay and BeagleY-AI, with the DWC3 and Cadence controllers in host mode. It joins Phase 13.

Order

U.1 follows Phase 5 and goes before Phase 6. U.2 to U.5 go inside Phase 6, after 6.7b, once a Linux guest boots with virtual interrupts, and before the Zephyr slices 6.8–6.10, since this is the primary peripheral. U.6 lands with Phase 13.