KVM exposes Linux hardware virtualization through /dev/kvm. KVM supplies the
kernel execution mechanism, while a virtual machine monitor such as QEMU constructs
and operates a complete guest machine.
Division of Responsibilities #
KVM uses Intel VT-x, AMD-V, Arm virtualization extensions, or the corresponding host facility to execute guest instructions directly when possible. Kernel code manages vCPU state, second-stage memory translation, interrupt delivery, timers, and transitions between guest and host execution. KVM intentionally does not provide a complete firmware and device model.
QEMU provides that machine model: firmware interfaces, PCI topology, storage and
network controllers, display and input devices, image backends, migration, and
management through QMP. With -accel kvm, QEMU delegates accelerated CPU execution
to KVM; without an accelerator it can use its TCG instruction translator instead.
QEMU’s supported options remain machine- and architecture-specific.
Guest Memory and Memory Slots #
QEMU first reserves host virtual memory, backed by anonymous memory, memfd, a file,
or huge pages. It then registers portions of that address space with a VM file
descriptor by using KVM_SET_USER_MEMORY_REGION. Each region describes:
- a slot number and flags;
- a guest-physical base and size; and
- the userspace virtual address that backs the slot.
Setting a slot’s size to zero removes it. Slots describe mappings rather than allocating guest RAM, so userspace must preserve the backing mapping while KVM uses it. Optional dirty-page logging records writes for migration and snapshot coordination.
A guest memory reference can involve two translations. Guest page tables translate a guest virtual address to a guest-physical address; KVM and the MMU hardware then translate that address to a host physical page corresponding to the registered userspace mapping. Intel calls the hardware second stage EPT, while AMD calls it NPT. KVM handles missing or invalid second-stage mappings and can install new mappings without exiting to QEMU when the access targets ordinary RAM. Access to an emulated MMIO range instead causes an exit or an in-kernel device operation.
NUMA placement, transparent or explicit huge pages, swapping, and memory overcommit affect latency without changing the guest-visible address model. Device assignment adds DMA mappings; VFIO therefore relies on an IOMMU and an isolation boundary that does not expose unrelated host devices or memory.
/dev/kvm Lifecycle
#
The stable KVM userspace ABI is organized by file-descriptor type:
- Open
/dev/kvm, then requireKVM_GET_API_VERSIONto returnKVM_API_VERSION(currently 12). Query optional behavior withKVM_CHECK_EXTENSION, not a kernel-version comparison. - Issue
KVM_CREATE_VMon the system descriptor. The returned VM descriptor starts with no RAM and no vCPUs. - Register memory slots and create the architecture’s interrupt controller and other in-kernel devices where required.
- Issue
KVM_CREATE_VCPUon the VM descriptor. UseKVM_GET_VCPU_MMAP_SIZE, then map the vCPU descriptor’s sharedstruct kvm_runarea. - Configure the CPU model and initial register state, then execute
KVM_RUNfrom the vCPU’s host thread.
VM and device ioctls must follow the process and thread restrictions documented by
the KVM API. The VM’s lifetime follows references to its file descriptor rather than
the lifetime of the process that created it; accidental references inherited through
fork or created by dup can therefore retain VM resources.
Virtual CPUs, Exits, and Interrupts #
Each vCPU has a KVM descriptor and commonly has a corresponding QEMU thread.
KVM_RUN enters guest mode and returns when userspace must act, a signal interrupts
the host thread, or an exit condition occurs. QEMU examines
kvm_run.exit_reason, handles an exit such as port I/O, MMIO, shutdown, or a debug
event, and calls KVM_RUN again. Instructions that KVM can virtualize entirely in
the kernel do not require a userspace exit.
Interrupts can enter through an emulated userspace controller or an in-kernel
irqchip. KVM_IRQ_LINE, MSI routing, and irqfd connect device events to guest
interrupts; ioeventfd lets selected guest MMIO or PIO writes notify an eventfd
without a round trip through the main emulation loop. KVM injects a pending
interrupt when the guest CPU can accept it.
Virtio and Exit Reduction #
Trap-and-emulate devices reproduce hardware register interfaces, but every
userspace-handled access crosses the KVM boundary. Virtio instead defines a
paravirtual device and shared virtqueues: the guest places descriptors in memory,
then notifies the host after batching work. QEMU, an in-kernel vhost backend, or a
vhost-user process can service the queue. Batching, interrupt suppression, and
irqfd/ioeventfd reduce exits, while device passthrough can remove the software
device model from the data path at the cost of stricter IOMMU and migration
constraints.
Isolation and Operational Observability #
Access to /dev/kvm controls who can create KVM VMs, but a QEMU process also handles
guest-controlled device input and host files. Run untrusted guests under a dedicated
identity and constrain QEMU with cgroups, namespaces, seccomp, and SELinux or
AppArmor. Minimize emulated devices, keep the kernel, QEMU, and guest firmware
updated, and treat VFIO IOMMU groups and shared-memory backends as explicit trust
boundaries. CPU side channels can also require SMT and scheduling policy beyond
memory isolation.
Basic host checks are:
test -r /dev/kvm && test -w /dev/kvm
ls -l /dev/kvm
lscpu | grep -i virtualizationQMP and management layers such as libvirt report guest state, vCPU time, block I/O,
and migration progress. At the host level, perf kvm stat summarizes costly KVM
exits, KVM tracepoints under the tracing filesystem expose entry, exit, MMIO, and
interrupt events, and /proc/PID/task identifies the QEMU vCPU threads. Debugfs and
tracefs require elevated access and can be unavailable when the kernel was built
without the relevant options.
The authoritative interfaces are the KVM API and the QEMU system-emulation documentation.
Comments
Read or comment on GitHub (sign-in required to comment)