16 Commits

Author SHA1 Message Date
lirent 85041c12ab fix(input): resolve the real evdev node for input-linux, not the sysfs name
UI_GET_SYSNAME returns the input-class directory name (inputNNN), not a usable
device node -- /dev/input/inputNNN does not exist, so QEMU's input-linux failed
with "Could not open". Resolve the actual evdev node (/dev/input/eventN) as the
event* child of /sys/class/input/<sysname>/. Confirmed against the live host
sysfs. The unit path can't exercise this (no /dev/uinput in CI) -- armed only.

Bump 0.3.10.
v0.3.10
2026-06-24 16:50:05 +03:00
lirent 228dc5af79 fix(input): use the hyphenated QMP object-add/object-del command names
The 0.3.8 bridge sent object_add/object_del (underscores, modeled on the legacy
device_add) but QMP's object commands are hyphenated -- object-add/object-del --
so QEMU rejected them with CommandNotFound and no bridge was set up. Confirmed
against the live monitor: object-add/object-del exist, object_add does not, and
input-linux is a creatable type. The stub QMP in the unit test used the same
wrong string, so it didn't catch this -- only the armed monitor did.

Bump 0.3.9.
v0.3.9
2026-06-24 16:41:46 +03:00
lirent d6c45ddb04 feat(input): daemon sets up the host->guest input-linux bridge via QMP
The uinput devices the input adapter creates were never forwarded into the
guest: the input-linux bridge was external (manual monitor object_add), so it
was lost on every reconfigure and whenever the kernel-assigned device numbers
changed. Make the vmhost seam -- which already owns the VM's single QMP
connection -- add the input-linux objects itself on reaching READY (A=keyboard
+abs with grab_all, B=mouse) and object_del them on teardown. The input adapter
publishes the uinput evdev paths into a per-endpoint home; discovery attaches
input before vmhost so the paths are ready. No second QMP socket or connection.

Also move the mouse buttons (incl. middle) and the wheel onto device B, so B is
a complete relative mouse and A is keyboard+abs only.

Bump 0.3.8.
v0.3.8
2026-06-24 16:31:23 +03:00
lirent 929bcf0e74 fix(discovery): tolerate CRLF line endings in mtree parsing
mtree_low_split anchored the system flatview on "Root memory region: system"
followed by LF/space/EOF, but QEMU's HMP `info mtree -f` output is CRLF, so the
byte after "system" is '\r'. The anchor was rejected, the parser returned 0
(fail-closed), and on a real guest the daemon never attached the VM (low=0 =>
ok=0). The synthetic LF-only fixture hid this; the fix is verified against the
real CRLF output.

Accept '\r' in the anchor check (LF-only input still works) and add a regression
test that re-encodes the fixture as CRLF in memory.

Bump 0.3.7.
v0.3.7
2026-06-24 15:08:07 +03:00
lirent 3142337e62 fix(discovery): derive the below-4G split robustly from fragmented mtree
host_probe derived the guest's below-4G split (vmie `low`) by taking the first
GPA-0 RAM run in `info mtree -f`. When low RAM is fragmented by overlay pages
(Hyper-V SynIC) and blackhole holes (smbase/tseg), that first run is a tiny
fragment, so the split came out far too small and host_bootstrap could never
recover the System DTB — the memctx context was never published.

Extract a pure parser, mtree_low_split(): anchor on the system flatview, take
`low` from the @file-offset of the high-RAM region at GPA >= 4 GiB (which equals
the split by construction), cross-validate against the PCI-hole base, and fail
closed when it can't be derived. QMP-reply un-escaping moves to the transport
boundary so the parser works on plain text. Unit-tested against a synthetic
fragmented flatview including a decoy non-system address space.

postinst also hints to restart the daemon after an upgrade (a running instance
keeps the old build until restarted).

Bump 0.3.6.
v0.3.6
2026-06-24 14:26:50 +03:00
lirent 26e5ab4709 fix(memctx): retry cold bootstrap with backoff while guest boots
The cold address-space bootstrap (host_bootstrap -> System DTB) ran once and was
terminal: when the adapter attached before the guest finished booting, no System
process was found, the adapter emitted a single ERROR and never retried, so the
memctx datum was never published.

Make it self-healing: on bootstrap failure arm a one-shot backoff timerfd (a
second adapter fd, demuxed by cookie) that re-kicks the bootstrap until it
succeeds; reset and disarm on success. Drop the per-failure URGENT ERROR (a
still-booting guest is transient, not a fault) for a single diagnostic line on
the first failure. Add a stub fail-injection (cfg fail_boots) and test_retry.

Bump 0.3.5.
v0.3.5
2026-06-24 11:20:32 +03:00
lirent 6fea392d46 build: derive the project version from VMSIG_VERSION so one tag drives every package + the .so version 2026-06-22 20:35:10 +03:00
lirent 0289817821 packaging: split vgpu perception into separate libvgpu-perception0 + -dev packages
- the vmsig package no longer ships the gpu lib; it is a Sensor lib for the control, not the daemon
- vgpu-perception gets SOVERSION; runtime (libvgpu-perception0) and dev (-dev) packages, like the vmie split
- per-component install + a 3-package make deb; fix a stale comment (the windows producer is in-tree)
v0.3.4
2026-06-22 20:32:21 +03:00
lirent d1aa09ecac ci: reach the package registry over https for authenticated apt; bump 0.3.3 v0.3.3 2026-06-22 19:33:43 +03:00
lirent 64b1a39b55 bump project version to 0.3.2 v0.3.2 2026-06-22 19:29:04 +03:00
lirent b14ea0e381 ci: authenticate apt to the private package registry (Basic Auth via token) 2026-06-22 19:27:00 +03:00
lirent bd8b966017 vgpu in-guest producer in-tree, release CI, flexible vmie discovery
- src/si/vgpu-stream: in-guest vgpu producer built as a Windows cross-compiled target (if(WIN32))
- .gitea: release workflow — cross-build the agent and build/publish the deb against system vmie
- cmake/makefile: resolve vmie from a source tree (LIBVMIE_PATH) or installed libvmie-dev
v0.3.1
2026-06-22 18:35:12 +03:00
lirent 9bde398b6c vmsig: management daemon, runtime endpoint lifecycle, roster, discovery, in-tree drivers, packaging
- core: runtime attach/detach of a per-endpoint adapter trio (runtime-safe add_adapter + vmsig_core_detach_endpoint, deferred reap)
- roster: VMSIG_EV_ROSTER + CAP_ROSTER, retained per-endpoint and replayed to late subscribers
- discovery: inotify trigger dir, vmid/endpoint slot allocator, host probe; vmsigd daemon with config + per-uid admission
- input driver and vgpu perception built in-tree; vgpu perception as a separate library
- memctx: own the supplied ro_fd (closed at detach)
- deb packaging: install rules, systemd unit, tmpfiles, default config
v0.3.0
2026-06-22 17:25:06 +03:00
lirent 0d387a4249 input: one-packet pointer moves, uinput-only injection, fire-and-forget
- Pointer motion is now a single event carrying both coordinates (MOVE_ABS /
  MOVE_REL with x,y) rather than one event per axis; the adapter actuates both
  axes in a single batch. The per-axis ABS/REL kinds are removed.
- Input injection is uinput-only: the driver selection and the optional
  guest-side passthrough drop out of the adapter config (the driver is the
  driver's concern). A QMP path is still carried for the unchanged service
  power/lifecycle path.
- A per-event fire-and-forget flag lets a control inject input without an
  actuation acknowledgement, for high-rate streams; without it the addressed
  ACT_ACK is emitted as before. Service commands always acknowledge.

The neutral input payload gains x/y/flags, still within the inline event body.
Capability, lease and source gates are unchanged.
v0.2.0
2026-06-21 10:31:36 +03:00
lirent e6c7aed8eb memwrite: per-process (cr3) target and full-extent socket SRC
- CMD_MEMWRITE now carries a target page-table root (cr3) as its first field;
  cr3 == 0 keeps the kernel address-space default (backward-compatible). A control
  that has discovered a process's cr3 through its own read-only perception can
  write that process's private memory under the same exclusive write lease.
  Freshness of the cr3 is the control's responsibility — signaling does not
  validate it (that is perception, not coherence), mirroring the read side.

- A socket control can now carry an SRC larger than the inline frame budget: a
  length-prefixed SRC tail follows the CMD_MEMWRITE frame (flag SRC_PAYLOAD, the
  length being the frame's own len). A per-connection two-phase receiver
  accumulates the tail into a fixed conn-owned buffer up to the extent bound,
  matching the in-process payload path. A zero or over-bound length is a framing
  violation that closes the connection: leaving the promised tail unread would
  desync the stream and draining an arbitrary length would be a denial of service.

The capability, exclusive lease, source and extent gates are unchanged and
reused; only the event header gained the cr3 field and the socket transport
gained the tail receiver. The adapter resolves cr3 == 0 to the kernel root on
its worker thread and writes atomically.
2026-06-20 21:21:20 +03:00
lirent e9aee057c7 vmsig: a neutral signaling layer between sensors/input and controls
An epoll-driven, neutral transfer-event bus that connects sensors and input
actuators to one or more controls, bidirectionally. It owns the transfer context
and events — delivery order, priority, protocol-level timing, and an
interrupt-driven event model over fd sources (eventfd/timerfd/sockets) — and
stays agnostic to both the sensor/input drivers and the control.

What lives here:
- memctx: a coherent address-space context per endpoint — the guest address-space
  root paired with a pre-opened read-only RAM-region fd, with per-endpoint epoch
  invalidation and retained replay to late subscribers. Perception lives in
  out-of-tree sensor libraries that consume this datum read-only.
- exclusive-ownership leases for destructive resource classes (input, power,
  memory-write).
- write-signaled memory writes (MEMWRITE): an atomic write to guest memory routed
  through the seam under an exclusive lease, never a writable mapping.
- a host-management seam for VM lifecycle/status and a neutral input-injection
  command path.
- multi-VM endpoints; capability-gated, audited control authorization over an
  in-process or unix-socket transport.

Builds against headers only by default (a stub mode that exercises the seam
without a VM); armed builds link the real sensor/input libraries behind flags.
2026-06-20 21:21:20 +03:00