Skip to content

vhost-user-vsock: enable savevm/loadvm for VM snapshots - #13

Open
omerzlabs wants to merge 1 commit into
panda-re:mainfrom
omerzlabs:feat/vhost-user-vsock-savevm
Open

vhost-user-vsock: enable savevm/loadvm for VM snapshots#13
omerzlabs wants to merge 1 commit into
panda-re:mainfrom
omerzlabs:feat/vhost-user-vsock-savevm

Conversation

@omerzlabs

Copy link
Copy Markdown

Summary

This patch enables savevm/loadvm for the vhost-user-vsock device, allowing VM snapshots when vsock-based networking is in use (e.g., Penguin's VPN port forwarding).

Currently vhost-user-vsock is marked as non-migratable, blocking all snapshot operations even though the parent class (vhost-vsock-common) already provides correct save/restore hooks. The kernel-backed variant (vhost-vsock) uses these hooks and is fully migratable. This patch brings vhost-user-vsock to parity.

Changes

Single file: hw/virtio/vhost-user-vsock.c (19 lines added, 1 removed)

1. Replace unmigratable VMStateDescription with a proper one

The empty vuv_vmstate with .unmigratable = 1 is replaced with a vmstate that:

  • Saves/restores VMSTATE_VIRTIO_DEVICE (virtio ring state, features, config)
  • Uses vhost_vsock_common_pre_save() — asserts the vhost backend is stopped before save
  • Uses vhost_vsock_common_post_load() — sends VIRTIO_VSOCK_EVENT_TRANSPORT_RESET after load so the guest kernel reconnects vsock sockets

This matches the kernel-backed vhost-vsock device exactly.

2. Remove the vhost-level migration blocker after device init

vhost_dev_init() registers a migration blocker when the backend lacks VHOST_F_LOG_ALL (dirty-page tracking for live migration). For savevm/loadvm, dirty tracking is unnecessary — the VM is paused and state is captured atomically. The blocker is removed after successful device initialization.

Note: migrate_del_blocker() removes the blocker for all migration modes. If live migration support is ever added for this device, the blocker handling should be revisited.

Why this is safe

  • vm_stop() is called before savevm, which triggers virtio_vmstate_change() -> vuv_set_status(0) -> vhost_vsock_common_stop(). The backend is guaranteed stopped when pre_save runs.
  • The chardev/vhost-user connection survives same-process savevm/loadvm — nothing tears it down.
  • On loadvm, post_load schedules a VIRTIO_VSOCK_EVENT_TRANSPORT_RESET via timer, telling the guest kernel to reconnect. set_status then restarts the backend.
  • Changes are scoped entirely to vhost-user-vsock — no other devices are affected.

Testing

  • make check unit tests: 97 pass / 0 fail / 4 skip (unchanged from baseline)
  • qtest-x86_64/migration-test: 40 subtests pass (unchanged from baseline)
  • savevm with vhost-user-vsock-pci enabled: succeeds (previously blocked with "State blocked by non-migratable device")
  • loadvm from snapshot: VM restores, guest receives transport reset
  • End-to-end: validated with Penguin firmware emulations across multiple vendors (Netgear, D-Link, TP-Link) — services accessible after snapshot restore

@omerzlabs
omerzlabs force-pushed the feat/vhost-user-vsock-savevm branch from 4a04b4e to b106574 Compare April 7, 2026 17:48
vhost-user-vsock was marked as unmigratable, blocking savevm/loadvm
even though the parent class (vhost-vsock-common) already provides
correct save/restore hooks. This patch enables in-process VM snapshots
for configurations using vhost-user-vsock-pci (e.g., vsock-based port
forwarding in Penguin).

Two changes to hw/virtio/vhost-user-vsock.c:

1. Replace the empty unmigratable VMStateDescription with a proper one
   that reuses vhost_vsock_common_pre_save (asserts backend is stopped)
   and vhost_vsock_common_post_load (sends VIRTIO_VSOCK_EVENT_TRANSPORT_RESET
   so the guest kernel reconnects vsock sockets). This matches the
   kernel-backed vhost-vsock variant exactly.

2. Remove the vhost-level migration blocker after vhost_dev_init().
   The blocker exists because the vhost-user backend lacks
   VHOST_F_LOG_ALL (dirty-page tracking for live migration). For
   savevm/loadvm, dirty tracking is unnecessary — the VM is paused
   and state is captured atomically. Since PANDA uses paused
   in-process snapshots and does not perform live migration, removing
   this blocker is safe.

Note: migrate_del_blocker() removes the blocker for all migration
modes, not just snapshots. If live migration support is ever added
for this device, the blocker handling should be revisited.

Tested with:
- make check (unit): 97 pass / 0 fail / 4 skip (unchanged)
- migration-test (qtest): 40 subtests pass (unchanged)
- savevm with vhost-user-vsock-pci enabled: succeeds
- loadvm from snapshot: VM restores, transport reset delivered
@omerzlabs
omerzlabs force-pushed the feat/vhost-user-vsock-savevm branch from b106574 to 3081c0a Compare April 7, 2026 17:49
@omerzlabs omerzlabs closed this Apr 7, 2026
@omerzlabs omerzlabs reopened this Apr 8, 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