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:
- It is what the boards have. BeaglePlay and PocketBeagle 2 (AM62x)
carry Synopsys DWC3 controllers (
snps,dwc3in U-Boot 2026.07'sdts/upstream/src/arm64/ti/k3-am62-main.dtsi), and BeagleY-AI (J722S) carries a Cadence USB3 controller (cdns,usb3,k3-j722s-main.dtsi). In host mode both are xHCI: U-Boot'sdrivers/usb/dwc3/dwc3-generic.cline 251 anddrivers/usb/cdns3/host.cline 31 both callxhci_register. - One interface on both sides. Glint's native driver and its emulated controller share xHCI's data structures (rings of transfer request blocks, device and endpoint contexts, the event ring), so one set of Crystal types serves both. That is Parsimony.
- Guests already drive it. Linux binds a memory-mapped xHCI described in
the devicetree as
generic-xhci(unverified: Linux's source isn't in the workspace; U-Boot'sdrivers/usb/host/xhci-generic.cline 60 binds the same string). One controller covers USB 1.1 to 3.x speeds, where the older UHCI, OHCI and EHCI would each need a model. - QEMU has a reference.
hw/usb/hcd-xhci.cin the pinned QEMU 11.1.2 is a model to read and to test Glint's native driver against (qemu-xhcion both machines), which is Demonstrability.
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.