mirror of
https://dev.lirent.ru/Vatrog/vm-automation-signaling.git
synced 2026-07-11 17:46:37 +03:00
feat(memctx): persist kcr3 to fast-restart without a cold rescan
The cold host_bootstrap hunts the agent beacon across physical RAM and is slow and unstable: after a restart the adapter re-scans from scratch, minutes in which there is no address-space context to vend, though the guest is long booted and its System DTB (kcr3) is unchanged. Cache the kcr3 from a successful live scan in a watch-dir sibling of the slot map (tmpfs: survives a restart, dies with the RAM file on host reboot). On attach, re-validate the cached kcr3 against the live RAM via an O_RDONLY context (open_ro_fd, which bypasses the beacon scan) plus a System-cr3 match, and publish the read datum immediately when it still resolves the kernel. A guest reboot changes the System DTB, so a stale kcr3 no longer resolves and falls back to a cold scan: the boot-session discriminator is the kcr3 itself, not file metadata. The gva_write target is never taken from the cache: it is set only by a fresh live scan, so a persisted kcr3 is a read locator only and MEMWRITE stays fail-closed until a cold bootstrap acquires the write hold. Persist is off unless the path is supplied (NULL keeps current behaviour). Bump 0.3.12.
This commit is contained in:
@@ -60,6 +60,10 @@ struct vmsig_discovery {
|
||||
* writes these at attach; the vmhost seam borrows them to add input-linux objects. Same
|
||||
* lifetime discipline as ep_facts (outlives the deferred adapter reap). */
|
||||
struct { char evdev_a[64]; char evdev_b[64]; } ep_bridge[VMSIG_SLOT_COUNT];
|
||||
/* Stable per-endpoint home for the memctx kcr3-cache path (sibling of .slots in the watch
|
||||
* dir). The memctx adapter keeps the pointer across its lifetime; same lifetime discipline
|
||||
* as ep_facts/ep_bridge (outlives the deferred adapter reap, overwritten on next attach). */
|
||||
char ep_persist[VMSIG_SLOT_COUNT][DISC_PATH_MAX + 32];
|
||||
};
|
||||
|
||||
static uint64_t now_ns(void) {
|
||||
@@ -269,14 +273,25 @@ static void bootstrap_scan(vmsig_discovery* d) {
|
||||
|
||||
static int default_attach(void* ud, vmsig_core* core, uint32_t vmid, uint32_t endpoint,
|
||||
const vmsig_host_facts* f) {
|
||||
(void)vmid;
|
||||
vmsig_discovery* d = ud; /* default sink carries the discovery handle (ep_bridge home) */
|
||||
char* ev_a = d ? d->ep_bridge[endpoint].evdev_a : NULL;
|
||||
char* ev_b = d ? d->ep_bridge[endpoint].evdev_b : NULL;
|
||||
if (d) { ev_a[0] = '\0'; ev_b[0] = '\0'; } /* clear stale paths from a prior attach */
|
||||
|
||||
/* Form the kcr3-cache path (per-vmid, sibling of .slots/the RAM file in the watch dir).
|
||||
* Gated on d->persist — one policy for all ephemeral watch-dir state. NULL => persist off. */
|
||||
const char* persist_path = NULL;
|
||||
if (d && d->persist) {
|
||||
int pn = snprintf(d->ep_persist[endpoint], sizeof d->ep_persist[endpoint],
|
||||
"%s/.kcr3-vm-%u", d->watch_dir, vmid);
|
||||
/* only enable the cache if the path fit (a truncated path would point elsewhere). */
|
||||
if (pn > 0 && (size_t)pn < sizeof d->ep_persist[endpoint])
|
||||
persist_path = d->ep_persist[endpoint];
|
||||
}
|
||||
|
||||
vmsig_memctx_cfg mc; memset(&mc, 0, sizeof mc);
|
||||
mc.stub = 0; mc.ram_path = f->ram_path; mc.low = f->low; mc.ro_fd = -1;
|
||||
mc.persist_path = persist_path;
|
||||
vmsig_input_cfg in; memset(&in, 0, sizeof in);
|
||||
/* input is uinput; power/lifecycle via the vmhost seam. The adapter publishes its uinput
|
||||
* evdev paths into ep_bridge so the vmhost seam can forward them via input-linux. */
|
||||
|
||||
Reference in New Issue
Block a user