Files
vatrog-vm-signaling/include/vmsig_adapter.h
T
lirent 709f4b586a 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.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 18:46:31 +03:00

82 lines
4.4 KiB
C

#ifndef VMSIG_ADAPTER_H
#define VMSIG_ADAPTER_H
#include "vmsig_event.h"
#include "vmsig_memctx.h" /* vmsig_memctx_reg — address-space context registration seam */
/* vmsig_adapter.h — unified SI adapter interface. One vtable, three readiness
* shapes behind it. The adapter is the ONLY place that includes neighbor headers
* (memmodel.h/win32.h/vgpu_stream.h/vmctl.h). It registers 0..N fds with the core;
* the core does not know whether it is a socket, eventfd or timerfd. SI specifics
* never leave these functions. */
typedef struct vmsig_adapter vmsig_adapter; /* opaque adapter instance */
/* How the adapter expresses readiness. The core treats all three as ordinary
* epoll fds; the enum is documentation + the choice of default epoll flags. */
typedef enum {
VMSIG_RDY_FD = 0, /* native pollable fd (socket) */
VMSIG_RDY_TIMERFD = 1, /* timerfd; adapter samples shared memory */
VMSIG_RDY_EVENTFD = 2 /* worker thread bridges a blocking API -> eventfd */
} vmsig_readiness;
/* Sink handed by the core to the adapter for emitting UP events without knowing
* the internals of the context. emit() is thread-safe (also called from worker
* threads); register_memctx/unregister_memctx are called ONLY on the loop thread.
* The registration hooks may be NULL (adapters/tests need not call them). */
typedef struct {
int (*emit)(void* token, vmsig_event* ev); /* UP (thread-safe) */
int (*register_memctx)(void* token, const vmsig_memctx_reg* reg); /* loop thread: AS context; 0/-1 */
void (*unregister_memctx)(void* token, uint32_t endpoint); /* loop thread: context gone */
void* token;
} vmsig_emit;
/* One fd contributed by the adapter, with epoll flags and a cookie for demux. */
typedef struct {
int fd;
uint32_t epoll_events; /* EPOLLIN / EPOLLOUT / ... */
vmsig_readiness shape;
uint32_t cookie; /* adapter-private fd discriminator */
} vmsig_fd_reg;
/* Adapter vtable. Each SI adapter implements this; SI specifics do not leak. */
typedef struct vmsig_adapter_ops {
const char* name; /* "memctx"/"input"/"vmhost" — diagnostics */
vmsig_source source; /* neutral seam role */
uint32_t codec; /* vmsig_codec owned by the adapter */
/* Create an instance from opaque cfg (adapter parses it; core passes as-is).
* Returns an instance or NULL. `endpoint` is the id of the VM it binds to. */
vmsig_adapter* (*open)(const void* cfg, uint32_t endpoint);
/* Attach: open the SI contract, bring up workers, hand fds into reg[]
* (<=cap), store `emit` for UP. Returns the number of registered fds (>=0) / -1. */
int (*attach)(vmsig_adapter* a, const vmsig_emit* emit,
vmsig_fd_reg* reg, int cap);
/* Readiness of one of the adapter's fds: `cookie` identifies the fd, `events`
* are the epoll flags. The adapter does NON-blocking work (reads the socket /
* drains the eventfd / reads the timerfd + samples counters) and calls emit on
* each UP. 0 — ok, -1 — fatal (the core detaches the adapter). */
int (*on_readiness)(vmsig_adapter* a, uint32_t cookie, uint32_t events);
/* Consume a DOWN event (a control decision): encode it into the contract
* (vmctl_batch / vmctl power; write the vgpu control block; read request to vmie).
* For blocking sinks it hands the work to a worker and returns immediately;
* completion arrives later as an UP VMSIG_EV_ACT_ACK (keyed by ev->corr).
* 0 — accepted, 1 — rejected (not for this seam), -1 — error. */
int (*submit)(vmsig_adapter* a, const vmsig_event* ev);
/* Detach + free: stop workers, close SI handles and fds. */
void (*close)(vmsig_adapter* a);
} vmsig_adapter_ops;
/* Factories (defined in each adapter's TU — the only symbol the build/cli layer
* needs; keeps neighbor headers out of the core's include-path). */
const vmsig_adapter_ops* vmsig_memctx_ops(void); /* vmie: address-space context (kcr3+locator) */
const vmsig_adapter_ops* vmsig_input_ops(void); /* vmctl */
const vmsig_adapter_ops* vmsig_vmhost_ops(void); /* QEMU/QMP (its own signaling) */
/* (vgpu frame sensor is no longer a signaling adapter: vgpu perception lives in an
* out-of-repo S-lib that consumes memctx; see vgpu-perception-handoff.) */
#endif /* VMSIG_ADAPTER_H */