Skip to content

Design: one userland input owner for the ARM desktop - #868

Closed
Japabu wants to merge 1 commit into
mainfrom
codex/arm-input-design
Closed

Japabu wants to merge 1 commit into
mainfrom
codex/arm-input-design

Conversation

@Japabu

@Japabu Japabu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator

Problem and result

The ARM shipping image initializes graphics and starts the compositor, but
the compositor exits because no input source can supply its keyboard and
mouse handles. Input should have one userland owner on both architectures.
The kernel should retain device claims, DMA isolation and interrupt delivery;
it should neither drive virtio input nor interpret its event records.

Design

Add system/inputserver and have the compositor receive its input port.
The same images/system.toml starts it on both architectures. It owns the
existing keyboard/mouse device handles where those are present and any
virtio input PCI functions its manifest names. The compositor consumes one
input protocol regardless of which devices the machine has. This moves
source selection and state merging into userland, and gives the future USB
driver an existing destination rather than another kernel injection API.

Use toyos-pci-claim and toyos-virtio for transport, register bounds,
isolated grants and split queues. Virtio input configuration is read and
validated before accepting events; the driver handles key transitions,
relative or absolute pointer reports, and SYN_REPORT batches. Keyboard
codes become the HID usages the SDK already exposes. A malformed device
record ends that source by name. The service merges held keys, modifiers
and buttons across its live sources and releases the state of a source that
ends. Events and initial state reach only the compositor's endowed
connector; the server bounds pending handshakes and never blocks on a
client. A slow reader is ended by name rather than silently losing a
release. Reconnection starts from an explicit state snapshot.

Extend the generic PCI selector with an optional exact class/subclass
constraint. Vendor/device matches alone continue to require a unique
function; a constrained request also requires a unique function. Never
choose by enumeration order or hard-coded slot. QEMU's keyboard and tablet
share 1af4:1052, but its PCI binding declares keyboard and other-input
classes respectively (QEMU's PCI input binding).
That discriminator is standard PCI identity, not an emulator override.
The driver still validates the input capabilities after the claim.

Replace the shared four-slot assumption with claim capacity derived from
each architecture's interrupt allocation. Every admitted function keeps its
own remapped interrupt and domain; no shared device interrupt broadcasts
activity to unrelated holders. The allocation remains bounded by the
architecture's available interrupt identifiers, with exhaustion refused.
This is required by ordinary machines with several userland drivers, not
just by the two virtual input devices.

The ARM interactive QEMU shape adds virtio-keyboard-pci and
virtio-tablet-pci, each with iommu_platform=on. Both are driven from
isolated PCI claims with ITS interrupts. The x86 machine keeps its existing
input sources and feeds them through the same service. No program contains
an architecture-specific input path.

Roast and alternatives

The largest cost is introducing a service and an IPC protocol while the
kernel still owns the older input drivers. That layer earns its place by
giving all physical input one userland owner and keeping hardware details
out of the compositor. It also moves the merge policy to the place that
can manage source death and reconnection. Growing the kernel's virtio
driver set or manufacturing keyboard availability would get a frame
sooner but would leave input ownership wrong. Moving all of USB before
ARM input would entangle this with mass storage and its ongoing track.
This design keeps the existing x86 drivers' move in that track, while
providing the destination they will eventually feed.

The PCI selector and interrupt allocator are general prerequisites and
should be reviewed as separate, bounded changes before the driver. They
must not relax ambiguity, per-function interrupt identity, isolation or
release ordering. A service split that duplicates decoding or adds a
fallback instead of owning every live source would be sent back.

Verification and scope

  1. Host tests cover selector parsing and wire refusal, unique versus
    ambiguous matching, interrupt allocation exhaustion, virtio event and
    configuration refusal, batch boundaries, merged modifiers/buttons,
    source death, client disconnect and snapshot state. Existing register
    and DMA boundary implementations stay one instruction deep.
  2. ARM guests use isolated input functions. Injected keys and pointer
    events must reach a running compositor and an application's window.
    calc, snake and doom must each map a window and present a frame.
    The same input path is exercised on x86 without changing its visible
    or audible quality.
  3. Negative controls remove each behavior otherwise invisible: selector
    filtering, queue replenishment, batch commit, source release, and input
    delivery to the compositor. Each must build and fail its corresponding
    check; complete patches and logs accompany the implementation PRs.
  4. The virtio specification and PCI identity definitions are the input
    and transport oracles. QEMU supplies the event device in guest tests;
    it supplies no timing or audio-quality verdict.

Scope: the PCI selector and per-architecture claim capacity, the userland
input owner and protocol, compositor input consumption, the common
manifest, ARM QEMU shape, and their tests. This does not claim the whole ARM
track complete: TLS/cache proofs, persistent USB-backed /log, full guest
coverage and the LLVM self-hosting comparison keep their existing exits.

Design only: no production implementation has been started for this PR.

Design round only: an empty commit for review of the input service,
generic PCI identity constraints, per-architecture claim capacity,
compositor input consumption, and isolated virtio input devices.
@Japabu

Japabu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

Design review: #868 at a678a477c, round 1, against origin/main at 1a81b5926. The branch is one empty commit on 177e72a9e, which is 284 commits behind main. git diff --shortstat origin/main...a678a477c is empty, so production and tests are both 0. The design was written before the owner's input ruling (#899 (comment)), before #899's and #901's accepted designs, and before #904's track text.

BLOCKER

  1. "Design", the inputserver and the compositor's input protocol, against the owner's ruling and ps2server: the i8042 driver leaves the kernel, and the owner of input merges every source #899's and S1 of the xHCI move into usbd: a FAT entry that grows its file is written a cache flush after its chain and data, held by a module test that stops the disk inside a flush epoch #901's accepted designs. The ruling: userland owns the merge, there is no kernel feed, and drivers deliver over the input port.

    Design: one userland input owner for the ARM desktop #868 contradicts that in four places:

    With the merge in a shared library and one owner per image, an inputserver between drivers and the compositor adds a process and a protocol hop that nothing needs. Under Growth, that is a new program where a library already does the job. Required: drop inputserver and the compositor protocol. What remains is a virtio-input driver program that claims its functions and delivers each one as a source over input, using ps2server: the i8042 driver leaves the kernel, and the owner of input merges every source #899's records with S1 of the xHCI move into usbd: a FAT entry that grows its file is written a cache flush after its chain and data, held by a module test that stops the disk inside a flush epoch #901's source and gone extension.

  2. "Design", the PCI selector's "optional exact class/subclass constraint": a sibling of what S1 of the xHCI move into usbd: a FAT entry that grows its file is written a cache flush after its chain and data, held by a module test that stops the disk inside a flush epoch #901's accepted S3 builds. S3 adds a class selector to lib/manifest (pci-class:, as in each = ["pci-class:010802"]). Use that selector, and name S3 as a prerequisite, or name the order if Design: one userland input owner for the ARM desktop #868 builds it first and S3 reuses it.

  3. "Design", the cited QEMU source: the clean-room rule (root CLAUDE.md, "Zero legacy"; reviewer.md, Fit). The keyboard-or-tablet discriminator rests on a link to QEMU's hw/virtio/virtio-input-pci.c, which is another implementation's source used as authority.

    • Read the functions' class codes instead, from a boot of the machine, as a measurement.
    • Their meaning comes from the PCI-SIG's class code assignments: base class 09h is an input device controller, and subclass 00h is a keyboard.
  4. "Design", "Keyboard codes become the HID usages" and "SYN_REPORT batches": the code table has no clean oracle.

    • virtio-input's event types and codes are the evdev layer's. SYN_REPORT is a Linux name, so it is an interface defined outside ToyOS, and Fit keeps it out of source.
    • The table from evdev codes to HID usages is defined by Linux's own headers. Under the clean-room rule, one agent writes that table as facts that cite no implementation, keeping the provenance in its evidence, and a different agent builds from it.
    • Usages are checked against USB-IF's HID Usage Tables. The design names neither the table's source nor how it is obtained.
  5. "Design", "Replace the shared four-slot assumption": work that is already filed and assigned.

    • issues/a-cargo-run-boot-claims-every-pcidev-slot.md is held by the orchestrator.
    • On aarch64, cargo run already claims NVMe, network, sound and vdagent. That is all four of MAX_FUNCTIONS (kernel/src/pcidev/mod.rs:146), so two virtio-input functions are refused Exhausted.
    • Name that issue as a prerequisite owned elsewhere, and do not build it here.
  6. "Design", "Both are driven from isolated PCI claims with ITS interrupts": nothing the design depends on works under HVF today. issues/an-aarch64-cargo-run-boot-hands-over-no-pci-claim.md records that no cargo run aarch64 claim is handed over, because there is no ITS and BAR placement lands in ECAM. Enable isolated ARM PCI claims and exclude ECAM from BAR placement #869's split (the GIC/ITS declaration, and apertures on The AML interpreter finished to ACPI 6.5: Load and _OSC, the namespace initialised, every address space, every event, and the bounds stated #875's walk) has to land first. Name that order.

  7. "Verification and scope", item 2: guest tests with no tier reason.

    • "Injected keys and pointer events must reach a running compositor and an application's window" and "calc, snake and doom must each map a window" are guest tests that drive software through a sequence of steps. Under Tests that is refused outside the kernel, and Guest tests asks why a type, a host test or a metal row cannot reach the behaviour.
    • The window-mapping exit belongs to the arm64 track's stage 7, not to this design.
    • What the driver owes is host tests against a fake device. They should cover config validation, queue refill, batch commit, and a malformed record ending its own source, plus at most a cheap smoke test.
    • "Exercised on x86 without changing its visible or audible quality" names no check.

NOTE

SEND BACK

@Japabu

Japabu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

Closed on the owner's ruling: ARM gets input through the USB keyboard and tablet that cargo run's machine already has, served by usbd (#901) once the ARM device fixes land, so virtio-input is dropped from the ARM plan. The review is #868 (comment); this design's findings stay here as a record.

@Japabu Japabu closed this Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant