---
title: KVM Architecture
url: https://doc.liz6.com/en/linux-kernel/13-kvm-and-virtualization/01-kvm-architecture
locale: en
area: linux-kernel
tags:
- linux-kernel
- kvm-and-virtualization
date: 2026-06-30
modified: 2026-07-16
description: 'Coverage: KVM as Linux hypervisor → VMX/SVM hardware virtualization → vCPU lifecycle → VM exit handling → KVM + QEMU collaboration model → /dev/kvm ioctl API Kernel version: 2.6.20 ~ 6.x'
---

# KVM Architecture

> Coverage: KVM as Linux hypervisor → VMX/SVM hardware virtualization → vCPU lifecycle → VM exit handling → KVM + QEMU collaboration model → /dev/kvm ioctl API
> Kernel version: 2.6.20 ~ 6.x

## Overview

KVM (Kernel-based Virtual Machine) transforms the Linux kernel into a type-1 hypervisor—leveraging Intel VMX or AMD SVM hardware virtualization extensions to allow guests to run directly on physical CPUs in VMX non-root mode. Each VM is a QEMU process in user space, and each vCPU is a thread within that process.

## Architecture Layers

<svg viewBox="0 0 720 340" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Source Han Sans CN','Microsoft YaHei',sans-serif" role="img" aria-label="KVM Architecture Layers: QEMU user space interacts with kernel space KVM module via ioctl">
  <defs>
    <marker id="kvmah1" markerWidth="10" markerHeight="8" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#475569"/></marker>
  </defs>
  <rect width="720" height="340" fill="#ffffff"/>
  <text x="360" y="28" text-anchor="middle" font-size="17" font-weight="700" fill="#1f2933">KVM Architecture Layers: QEMU User Space · Kernel Space KVM</text>

  <rect x="60" y="50" width="600" height="28" rx="6" fill="#4f46e5"/>
  <text x="360" y="69" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">QEMU (User Space)</text>

  <rect x="60" y="88" width="190" height="50" rx="6" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="155" y="108" text-anchor="middle" font-size="12" font-weight="700" fill="#3730a3">Device Emulation</text>
  <text x="155" y="125" text-anchor="middle" font-size="10.5" fill="#4f46e5">virtio / VGA / Storage / Network</text>

  <rect x="265" y="88" width="190" height="50" rx="6" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="360" y="108" text-anchor="middle" font-size="12" font-weight="700" fill="#3730a3">VM Management</text>
  <text x="360" y="125" text-anchor="middle" font-size="10.5" fill="#4f46e5">live migration / snapshot</text>

  <rect x="470" y="88" width="190" height="50" rx="6" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="565" y="108" text-anchor="middle" font-size="12" font-weight="700" fill="#3730a3">KVM ioctl</text>
  <text x="565" y="125" text-anchor="middle" font-size="10.5" fill="#4f46e5">/dev/kvm</text>

  <line x1="360" y1="140" x2="360" y2="176" stroke="#475569" stroke-width="1.8" marker-end="url(#kvmah1)"/>
  <text x="380" y="162" font-size="11" fill="#64748b">ioctl system call crosses user space → kernel space</text>

  <rect x="60" y="180" width="600" height="28" rx="6" fill="#0d9488"/>
  <text x="360" y="199" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">Kernel (KVM)</text>

  <rect x="60" y="218" width="190" height="50" rx="6" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="155" y="238" text-anchor="middle" font-size="12" font-weight="700" fill="#115e59">kvm.ko</text>
  <text x="155" y="255" text-anchor="middle" font-size="10.5" fill="#0f766e">Architecture-independent core</text>

  <rect x="265" y="218" width="190" height="50" rx="6" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="360" y="238" text-anchor="middle" font-size="12" font-weight="700" fill="#115e59">kvm-intel.ko</text>
  <text x="360" y="255" text-anchor="middle" font-size="10.5" fill="#0f766e">VMX support</text>

  <rect x="470" y="218" width="190" height="50" rx="6" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="565" y="238" text-anchor="middle" font-size="12" font-weight="700" fill="#115e59">kvm-amd.ko</text>
  <text x="565" y="255" text-anchor="middle" font-size="10.5" fill="#0f766e">SVM support</text>

  <rect x="60" y="284" width="600" height="44" rx="8" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="76" y="304" font-size="12.5" fill="#3730a3">QEMU communicates with the kernel only via /dev/kvm ioctls, without directly touching virtualization registers;</text>
  <text x="76" y="321" font-size="12.5" fill="#3730a3">kvm.ko is the architecture-independent core, while kvm-intel.ko / kvm-amd.ko interface with VMX / SVM respectively.</text>
</svg>

## VM Entry / VM Exit

<svg viewBox="0 0 720 400" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Source Han Sans CN','Microsoft YaHei',sans-serif" role="img" aria-label="VM Entry / VM Exit: The loop of guest execution and kernel exit handling">
  <defs>
    <marker id="kvmah2" markerWidth="10" markerHeight="8" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#475569"/></marker>
  </defs>
  <rect width="720" height="400" fill="#ffffff"/>
  <text x="360" y="28" text-anchor="middle" font-size="17" font-weight="700" fill="#1f2933">VM Entry / VM Exit: The loop of guest execution and kernel exit handling</text>

  <rect x="50" y="70" width="230" height="130" rx="10" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="165" y="98" text-anchor="middle" font-size="14" font-weight="700" fill="#115e59">Guest Execution</text>
  <text x="165" y="122" text-anchor="middle" font-size="11" fill="#0f766e">VMLAUNCH (VMX) / VMRUN (SVM)</text>
  <text x="165" y="140" text-anchor="middle" font-size="11" fill="#0f766e">→ Enters VMX non-root mode</text>
  <text x="165" y="158" text-anchor="middle" font-size="11" fill="#0f766e">Guest executes directly on physical CPU</text>
  <text x="165" y="176" text-anchor="middle" font-size="11" fill="#14b8a6">(until a VM exit is triggered)</text>

  <rect x="430" y="70" width="240" height="250" rx="10" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="550" y="98" text-anchor="middle" font-size="14" font-weight="700" fill="#3730a3">VM Exit (root mode)</text>
  <text x="550" y="118" text-anchor="middle" font-size="10.5" fill="#4f46e5">Guest executes sensitive instructions</text>
  <text x="550" y="132" text-anchor="middle" font-size="10" fill="#4f46e5">(HLT / IO / EPT violation …)</text>
  <line x1="445" y1="142" x2="655" y2="142" stroke="#c7d2fe" stroke-width="1"/>
  <text x="445" y="158" font-size="10.5" font-weight="700" fill="#3730a3">KVM reads exit reason and dispatches handling:</text>
  <text x="445" y="178" font-size="10.5" fill="#4338ca">IO_INSTRUCTION → Emulate IO instruction</text>
  <text x="445" y="200" font-size="10.5" fill="#4338ca">EPT_VIOLATION → Handle guest page table changes</text>
  <text x="445" y="222" font-size="10.5" fill="#4338ca">CPUID → Emulate CPUID</text>
  <text x="445" y="244" font-size="10.5" fill="#4338ca">HLT → Idle injection</text>
  <text x="445" y="266" font-size="10.5" fill="#4338ca">MSR_READ/WRITE → Emulate MSR access</text>
  <text x="445" y="292" font-size="10.5" font-weight="700" fill="#3730a3">After handling → VMRESUME back to guest</text>

  <line x1="280" y1="110" x2="426" y2="110" stroke="#475569" stroke-width="1.6" marker-end="url(#kvmah2)"/>
  <text x="354" y="100" text-anchor="middle" font-size="10.5" fill="#64748b">Sensitive instruction triggers → Exit to root</text>
  <line x1="426" y1="170" x2="280" y2="170" stroke="#475569" stroke-width="1.6" marker-end="url(#kvmah2)"/>
  <text x="354" y="185" text-anchor="middle" font-size="10.5" fill="#64748b">After handling → VMRESUME back to guest</text>

  <rect x="50" y="340" width="620" height="50" rx="8" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="66" y="360" font-size="12.5" fill="#115e59">VM Exit is the core loop of KVM: guest attempts sensitive operation → traps to kernel → KVM software emulation → VMRESUME resumes;</text>
  <text x="66" y="378" font-size="12.5" fill="#115e59">Reading the exit reason and dispatching by type is the main source of overhead in guest/host switching in virtualization.</text>
</svg>

## vCPU Thread Model

```c
// Each vCPU = one QEMU thread, executing a loop:
while (running) {
    ioctl(vcpu_fd, KVM_RUN, 0);
    // Returns: VM exit
    switch (vcpu->kvm_run->exit_reason) {
    case KVM_EXIT_IO:       handle_io(vcpu);       break;
    case KVM_EXIT_MMIO:     handle_mmio(vcpu);     break;
    case KVM_EXIT_IRQ_WINDOW_OPEN: inject_interrupt(vcpu); break;
    // ...
    }
}
```

### Scheduler Interaction

```c
// KVM knows when a vCPU is preempted via preempt notifier:
// → kvm_sched_out(): vCPU is scheduled out
// → kvm_sched_in():  vCPU is scheduled in
// Used for: steal time accounting, TSC offset calculation
```

## /dev/kvm Interface

```c
// Create VM:
int kvm_fd = open("/dev/kvm", O_RDWR);
int vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, 0);

// Register memory (guest physical address space):
struct kvm_userspace_memory_region region = {
    .slot = 0, .guest_phys_addr = 0, .memory_size = 1ULL << 30,
    .userspace_addr = (__u64)guest_ram_ptr, .flags = 0 };
ioctl(vm_fd, KVM_SET_USER_MEMORY_REGION, &region);

// Create vCPU:
int vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, cpu_id);

// Get KVM version/capabilities:
int version = ioctl(kvm_fd, KVM_GET_API_VERSION, 0);
struct kvm_cpuid2 cpuid = { .nent = N }; 
ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, &cpuid);
```

## Interrupt Injection

```c
// KVM injects interrupts to the guest:
//   1. Set interrupt info fields in VMCS (VMX) or VMCB (SVM)
//   2. Set interrupt window → guest responds immediately after VM entry
//   3. If vCPU is not running (scheduled out) → set kick flags

// Interrupt sources:
//   - virtio devices (msix)
//   - Emulated devices (8259A PIC, IOAPIC)
//   - IPI (multiple vCPUs within guest)
//   - Timer (hrtimer → KVM timer)
```

## References

- **Source Code**: `virt/kvm/kvm_main.c` (core), `arch/x86/kvm/vmx/vmx.c` (Intel VMX), `arch/x86/kvm/svm/svm.c` (AMD SVM)
- **Kernel Documentation**: `Documentation/virt/kvm/`
- **LWN**: "KVM: the Linux virtual machine monitor"

*Keywords: KVM, VMX, SVM, vCPU, VM exit, VMLAUNCH, VMRESUME, /dev/kvm, KVM_RUN, interrupt injection*
