Virtual Machines

QV-VM-001 Rev 1.0 — January 2026

Complete guide to VM lifecycle management, vCPU topology and register-level control, PCI device assignment and passthrough, snapshots, cloning, guest agent integration, and resource limits. For initial VM creation walkthrough, see Getting Started.

VM Lifecycle #

A VM progresses through a defined set of states. State transitions are triggered by CLI commands, API calls, or internal events (e.g., guest-initiated shutdown via ACPI).

TransitionCLI CommandWhat Happens Internally
→ CREATEDvm create --configParse JSON, allocate VMCS/VMCB per vCPU, build EPT/NPT, initialize devices, allocate guest RAM
CREATED → RUNNINGvm startLoad guest firmware (OVMF/SeaBIOS) at reset vector, execute VMLAUNCH/VMRUN on all vCPUs
RUNNING → PAUSEDvm pauseSend IPI to all vCPUs, each executes VM-exit, mark vCPUs as de-scheduled
PAUSED → RUNNINGvm resumeRe-schedule vCPUs, VMRESUME on next scheduler tick
RUNNING → STOPPEDvm stopInject ACPI power button (graceful) or force VM-exit and teardown (--force)
RUNNING → MIGRATINGvm migratePQC key exchange with target, begin dirty page tracking, iterative memory transfer
* → DESTROYEDvm destroyRelease VMCS/VMCB, free EPT/NPT, release RAM pages, tear down device emulation

VM Management API (C) #

The hypervisor kernel exposes C functions for VM lifecycle management in hypervisor/core/vm/vm.h:

/* VM lifecycle */
struct vm *vm_create(const char *name, uint32_t max_vcpus, uint64_t ram_size);
void       vm_destroy(struct vm *vm);
int        vm_start(struct vm *vm);
int        vm_stop(struct vm *vm);
int        vm_pause(struct vm *vm);
int        vm_resume(struct vm *vm);
int        vm_reset(struct vm *vm);

/* vCPU management */
int        vm_add_vcpu(struct vm *vm, uint32_t vcpu_id);
struct vcpu *vm_get_vcpu(struct vm *vm, uint32_t vcpu_id);

/* Memory management */
int        vm_add_memory_region(struct vm *vm, uint64_t gpa_base, uint64_t size, uint32_t flags);
void      *vm_gpa_to_hva(struct vm *vm, uint64_t gpa);
int        vm_read_memory(struct vm *vm, uint64_t gpa, void *buf, size_t len);
int        vm_write_memory(struct vm *vm, uint64_t gpa, const void *buf, size_t len);

vCPU Management #

vCPU Topology

QuantaVirt presents configurable CPU topology to the guest through CPUID leaves and ACPI SRAT/SLIT tables. The guest sees the specified socket/core/thread topology, enabling proper NUMA-aware workload placement inside the VM.

Topology ElementConfig FieldGuest Visibility
Socketscpu.topology.socketsCPUID leaf 0x1F / ACPI SRAT
Cores per socketcpu.topology.coresCPUID leaf 0x1F level 1
Threads per corecpu.topology.threadsCPUID leaf 0x1F level 0 (SMT)
NUMA nodescpu.numa_nodeACPI SRAT proximity domains

CPU Pinning

# Pin vCPU 0 to physical CPU 4, vCPU 1 to physical CPU 5
quantavirt vm set myvm --cpu-pin 0:4,1:5

# Show current pinning
quantavirt vm show myvm --cpu-pin
# vCPU 0 → pCPU 4 (NUMA node 0)
# vCPU 1 → pCPU 5 (NUMA node 0)

# Clear pinning (return to scheduler-managed)
quantavirt vm set myvm --cpu-pin auto

vCPU API (C) #

Register-level vCPU control from hypervisor/core/vm/vcpu.h:

/* vCPU lifecycle */
struct vcpu *vcpu_create(struct vm *vm, uint32_t vcpu_id);
void         vcpu_destroy(struct vcpu *vcpu);
int          vcpu_reset(struct vcpu *vcpu, uint64_t boot_ip);
int          vcpu_run(struct vcpu *vcpu);     /* Enter VM, returns on VM-exit */
void         vcpu_kick(struct vcpu *vcpu);    /* Force VM-exit via IPI */
int          vcpu_step(struct vcpu *vcpu);    /* Single-step one instruction */

/* Register access — general purpose (RAX through R15, RIP, RFLAGS, RSP) */
int vcpu_get_regs(struct vcpu *vcpu, struct vcpu_regs *regs);
int vcpu_set_regs(struct vcpu *vcpu, const struct vcpu_regs *regs);
uint64_t vcpu_get_reg(struct vcpu *vcpu, enum vcpu_reg reg);
void     vcpu_set_reg(struct vcpu *vcpu, enum vcpu_reg reg, uint64_t value);

/* Interrupt/exception injection */
int vcpu_queue_interrupt(struct vcpu *vcpu, uint8_t vector);
int vcpu_queue_exception(struct vcpu *vcpu, uint8_t vector, uint32_t error_code);
int vcpu_queue_nmi(struct vcpu *vcpu);

/* Convenience: inject common exceptions */
int vcpu_inject_gp(struct vcpu *vcpu, uint32_t error_code);  /* #GP */
int vcpu_inject_ud(struct vcpu *vcpu);                        /* #UD */
int vcpu_inject_pf(struct vcpu *vcpu, uint64_t fault_addr, uint32_t error_code); /* #PF */

PCI Device Assignment #

QuantaVirt supports PCIe device passthrough via IOMMU (VT-d/AMD-Vi), allowing a physical PCIe device to be assigned directly to a VM with near-native performance. The IOMMU provides DMA isolation, ensuring the passthrough device can only access the assigned VM's memory.

# List available PCI devices for passthrough
quantavirt system pci-list --available
# BDF            Vendor   Device   Class          IOMMU Group
# 0000:04:00.0   10DE     2684     3D Controller   5
# 0000:05:00.0   8086     1572     Ethernet        7

# Assign GPU to VM
quantavirt vm set gpu-vm --pci-add 0000:04:00.0

# Or in configuration JSON:
"devices": {
  "pci_passthrough": [
    { "bdf": "0000:04:00.0", "type": "gpu" },
    { "bdf": "0000:05:00.0", "type": "nic" }
  ]
}
IOMMU Required: Device passthrough requires Intel VT-d or AMD-Vi enabled in firmware and iommu=on in the hypervisor boot parameters. All devices in the same IOMMU group must be assigned to the same VM.

Snapshots & Cloning #

# Create snapshot (disk + memory state if running)
quantavirt vm snapshot create myvm --name before-update

# List snapshots
quantavirt vm snapshot list myvm
# NAME              CREATED              SIZE      STATE
# before-update     2026-01-15 14:30:00  1.2 GiB   running

# Restore snapshot
quantavirt vm snapshot restore myvm --name before-update

# Delete snapshot
quantavirt vm snapshot delete myvm --name before-update

# Clone a VM (creates independent copy)
quantavirt vm clone myvm --name myvm-clone
# New disk image created via qcow2 copy-on-write
# New MAC address auto-generated
# New UUID auto-generated

Guest Agent #

The QuantaVirt Guest Agent runs inside the VM and enables enhanced management capabilities: graceful shutdown, filesystem freeze/thaw for consistent snapshots, network information reporting, and PQC attestation from within the guest.

FeatureWithout AgentWith Agent
ShutdownACPI power button onlyClean OS shutdown with service stop
SnapshotsCrash-consistent (disk only)Application-consistent (fs freeze + disk)
IP ReportingDHCP lease parsingReal-time from guest network stack
Time SyncPV clock onlyNTP + PV clock + agent sync
PQC AttestationHypervisor-side onlyGuest-initiated attestation with guest measurements
# Install guest agent inside the VM
# Ubuntu/Debian:
sudo apt install quantavirt-guest-agent
sudo systemctl enable --now quantavirt-guest-agent

# RHEL/Fedora:
sudo dnf install quantavirt-guest-agent
sudo systemctl enable --now quantavirt-guest-agent

Resource Limits #

ResourceCLI FlagRangeDescription
CPU weight--cpu-weight1 – 65535Proportional CPU share (default 256)
CPU cap--cpu-cap0 – 100Maximum % of one pCPU (0 = unlimited)
I/O bandwidth--io-limitbytes/secPer-disk I/O throughput limit
I/O IOPS--iops-limitops/secPer-disk IOPS limit
Network bandwidth--net-limitbits/secPer-interface network bandwidth cap

Hot-Plug Support #

ResourceHot-AddHot-RemoveGuest Requirements
vCPUs✅⚠️ (guest must support)ACPI CPU hotplug support in guest kernel
Memory✅⚠️ (via balloon)VirtIO memory balloon driver or ACPI memory hotplug
VirtIO-blk disk✅✅VirtIO PCI device support
VirtIO-net NIC✅✅VirtIO PCI device support
USB device✅✅USB support in guest
PCI passthrough⚠️ Beta⚠️ BetaPCIe native hotplug in guest
# Hot-add a disk to a running VM
quantavirt vm disk-add myvm --type virtio-blk --path /var/lib/quantavirt/images/data.qcow2

# Hot-add a NIC
quantavirt vm nic-add myvm --type virtio-net --network office-lan

# Hot-add vCPUs (increase from 2 to 4)
quantavirt vm set myvm --vcpus 4