Linux Kernel Virtualization

Last update: 2024-10-12 06:57:35 +0800 +0800
tags: Kernel | Kvm | Linux
Available translations: 日本語 / 中文(简体) / 中文(繁體)

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:

  1. Open /dev/kvm, then require KVM_GET_API_VERSION to return KVM_API_VERSION (currently 12). Query optional behavior with KVM_CHECK_EXTENSION, not a kernel-version comparison.
  2. Issue KVM_CREATE_VM on the system descriptor. The returned VM descriptor starts with no RAM and no vCPUs.
  3. Register memory slots and create the architecture’s interrupt controller and other in-kernel devices where required.
  4. Issue KVM_CREATE_VCPU on the VM descriptor. Use KVM_GET_VCPU_MMAP_SIZE, then map the vCPU descriptor’s shared struct kvm_run area.
  5. Configure the CPU model and initial register state, then execute KVM_RUN from 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:

sh
test -r /dev/kvm && test -w /dev/kvm
ls -l /dev/kvm
lscpu | grep -i virtualization

QMP 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)