Appendix C: KVM ioctl Reference

KVM's userspace API is organized by file descriptor. The same numeric command space is used for system, VM, vCPU, and device operations, so an ioctl name is not complete documentation until its target fd and capability requirements are known.

This appendix indexes the ioctls used by the book. Chapter 5 develops the three-fd model, Chapter 6 covers memory slots and dirty tracking, Chapter 7 covers interrupts and time, and Chapter 8 covers exits.

Opening /dev/kvm and issuing these ioctls requires a bare-metal Linux host or a VM with nested virtualization. Treat experiments as isolated lab work. The tables are an API reference, not commands to run on a workstation.

Read The Encoding Carefully

KVM defines KVMIO as 0xAE. On architectures using the generic ioctl layout, _IOC(dir, type, nr, size) packs the command number like this:

Field Generic Bits Meaning
nr 7-0 Operation number within the ioctl family
type 15-8 Subsystem magic, 0xAE for KVM
size 29-16 Encoded argument size
dir 31-30 No data, write, read, or read/write

The macro names describe data movement from the kernel's point of view: _IOW copies input from userspace, _IOR copies output to userspace, and _IOWR does both. Historical exceptions make those direction bits unreliable as semantic documentation. For example, KVM_GET_DIRTY_LOG is _IOW because its top-level struct contains a userspace pointer, KVM_GET_ONE_REG is also _IOW, and KVM_SET_IRQCHIP is spelled _IOR in the UAPI header. Use the published macro, not a reconstructed "corrected" encoding.

_IO commands have no encoded struct size, so their generic value is simply 0x0000AE00 | nr. Other raw values depend on the argument layout and ioctl encoding of the build architecture. The operation number and macro are the portable reference.

Follow The File Descriptors

flowchart LR A["open /dev/kvm"] -->|"system fd"| B["KVM_CREATE_VM"] B -->|"VM fd"| C["KVM_CREATE_VCPU"] B -->|"VM fd"| D["KVM_CREATE_DEVICE"] C -->|"vCPU fd"| E["KVM_RUN and vCPU state"] D -->|"device fd"| F["device attributes"]

VM ioctls must be issued from the process address space that created the VM. The KVM documentation says vCPU ioctls should remain on the thread that created the vCPU; moving them can impose a first-call performance cost. Device ioctls must remain in the VM creator's address space. A few ioctls deliberately accept more than one fd class, so check each entry rather than assuming that a command number uniquely determines scope.

System Ioctls

These target the fd returned by open("/dev/kvm", O_RDWR).

Ioctl UAPI Definition Effect
KVM_GET_API_VERSION _IO(KVMIO, 0x00) Return the stable API version, currently and validly 12
KVM_CREATE_VM _IO(KVMIO, 0x01) Create a VM and return its fd
KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list) List x86 MSRs available to vCPU MSR ioctls
KVM_CHECK_EXTENSION _IO(KVMIO, 0x03) Query a KVM_CAP_* value
KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) Return the required vCPU mapping size
KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2) Return x86 CPUID entries KVM can support
KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) List feature MSRs readable on the system fd

Reject an API version other than 12. Extensions evolve through KVM_CHECK_EXTENSION, not by incrementing that base version. Most capability queries return zero or one, but some return a count, size, bitmask, or limit. When KVM_CAP_CHECK_EXTENSION_VM is available, the VM-fd form can report the capabilities of that configured VM and is preferred where the distinction matters.

KVM_GET_VCPU_MMAP_SIZE supplies the length for mapping offset zero of every vCPU fd. Do not substitute sizeof(struct kvm_run). The returned layout may also account for the historical coalesced-MMIO page and dirty-ring pages.

VM Ioctls

These target the fd returned by KVM_CREATE_VM unless noted otherwise.

Ioctl UAPI Definition Effect
KVM_CREATE_VCPU _IO(KVMIO, 0x41) Create a vCPU and return its fd
KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log) Copy one memory slot's dirty bitmap to userspace
KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, struct kvm_userspace_memory_region) Create, modify, or delete a userspace-backed memory slot
KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) Reserve the x86 Intel TSS region
KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) Set the x86 Intel identity-map page address
KVM_SET_USER_MEMORY_REGION2 _IOW(KVMIO, 0x49, struct kvm_userspace_memory_region2) Extended slot API with guest_memfd fields
KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) Create an in-kernel interrupt controller model
KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) Assert or deassert an irqchip input
KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip) Read x86 PIC or IOAPIC state
KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip) Restore x86 PIC or IOAPIC state
KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing) Install GSI routing entries
KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd) Bind an eventfd to guest interrupt injection
KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config) Create the x86 in-kernel PIT
KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd) Bind a guest write at an address to an eventfd
KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data) Set VM clock state
KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data) Read VM clock state
KVM_CLEAR_DIRTY_LOG _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log) Clear and reprotect a dirty-log range in manual mode
KVM_RESET_DIRTY_RINGS _IO(KVMIO, 0xc7) Return harvested dirty-ring entries to KVM
KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device) Create an in-kernel device and return its fd

KVM_CREATE_VCPU accepts an ID in [0, max_vcpu_id). Query KVM_CAP_NR_VCPUS for the recommended count, KVM_CAP_MAX_VCPUS for the hard count limit, and KVM_CAP_MAX_VCPU_ID for the ID-space limit. Count and ID are separate constraints.

On x86, KVM_CREATE_IRQCHIP creates two PICs and an IOAPIC, and arranges for future vCPUs to receive local APICs. Order therefore matters: call it before creating vCPUs when the machine design requires in-kernel LAPICs. On arm64 the ioctl creates a GICv2; KVM_CREATE_DEVICE is the preferred interface and is required for other GIC versions such as GICv3.

KVM_SET_TSS_ADDR is an x86 Intel-host requirement. Its three-page guest physical range must remain below 4 GiB and must not overlap RAM or MMIO. The guest must not use it. This is not a guest task-state segment supplied by the guest OS; it is KVM's VMX compatibility reservation.

Memory And Dirty Tracking

The basic memory-slot struct connects a guest-physical range to an existing userspace virtual range:

struct kvm_userspace_memory_region {
    __u32 slot;
    __u32 flags;
    __u64 guest_phys_addr;
    __u64 memory_size;
    __u64 userspace_addr;
};

Slot IDs occupy bits 0-15; with KVM_CAP_MULTI_ADDRESS_SPACE, bits 16-31 hold the address-space ID. Slots cannot overlap within one address space. Setting memory_size to zero deletes a slot. An existing slot can move or change flags but cannot be resized in place. KVM recommends matching the low 21 bits of guest_phys_addr and userspace_addr so guest large pages can be backed by host large pages.

KVM_MEM_LOG_DIRTY_PAGES enables bitmap tracking. By default, KVM_GET_DIRTY_LOG returns dirties since the preceding call and clears the bits before returning. With KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, userspace instead clears and reprotects selected ranges through KVM_CLEAR_DIRTY_LOG. The dirty-ring interface is a separate per-vCPU producer path; after harvesting entries, userspace marks them reset and calls KVM_RESET_DIRTY_RINGS.

KVM_SET_USER_MEMORY_REGION2 adds guest_memfd and offset fields. The KVM_MEM_GUEST_MEMFD flag belongs to that extended struct, not the legacy one. Its capability and memory-attribute contracts are part of confidential-guest support and must be negotiated together.

Interrupt Eventfds

KVM_IOEVENTFD and KVM_IRQFD remove the userspace vCPU loop from common notification paths:

guest write -> KVM_IOEVENTFD -> eventfd -> device backend
device event -> eventfd -> KVM_IRQFD -> routed guest interrupt

An ioeventfd registration identifies a PIO or MMIO address, optional data match, access length, and eventfd. A matching guest write signals the eventfd instead of producing a userspace exit. With KVM_CAP_IOEVENTFD_ANY_LENGTH, a zero length ignores the guest write width.

An irqfd registration binds an eventfd to a GSI. KVM_SET_GSI_ROUTING maps that GSI to an irqchip pin or MSI route. With KVM_CAP_IRQFD_RESAMPLE, a second eventfd reports deassertion after a level-triggered interrupt is resampled; the device backend must requeue the interrupt if its condition remains true.

vCPU Ioctls

These target a vCPU fd.

Ioctl UAPI Definition Effect
KVM_RUN _IO(KVMIO, 0x80) Enter the guest until KVM returns or fails
KVM_GET_REGS / KVM_SET_REGS _IOR(..., 0x81, struct kvm_regs) / _IOW(..., 0x82, struct kvm_regs) Transfer general registers on supported architectures
KVM_GET_SREGS / KVM_SET_SREGS _IOR(..., 0x83, struct kvm_sregs) / _IOW(..., 0x84, struct kvm_sregs) Transfer x86 segment, control, and related state
KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) Queue an interrupt for userspace-irqchip operation
KVM_GET_MSRS / KVM_SET_MSRS _IOWR(..., 0x88, struct kvm_msrs) / _IOW(..., 0x89, struct kvm_msrs) Transfer x86 MSRs
KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask) Select signals blocked only while in KVM_RUN
KVM_GET_FPU / KVM_SET_FPU _IOR(..., 0x8c, struct kvm_fpu) / _IOW(..., 0x8d, struct kvm_fpu) Transfer architecture FPU state
KVM_GET_LAPIC / KVM_SET_LAPIC _IOR(..., 0x8e, struct kvm_lapic_state) / _IOW(..., 0x8f, struct kvm_lapic_state) Transfer x86 LAPIC state
KVM_SET_CPUID2 / KVM_GET_CPUID2 _IOW(..., 0x90, struct kvm_cpuid2) / _IOWR(..., 0x91, struct kvm_cpuid2) Set or inspect the x86 guest CPUID table
KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state) Read vCPU runnable/stopped state
KVM_GET_VCPU_EVENTS / KVM_SET_VCPU_EVENTS _IOR(..., 0x9f, struct kvm_vcpu_events) / _IOW(..., 0xa0, struct kvm_vcpu_events) Transfer pending exceptions, interrupts, and NMIs
KVM_SET_TSC_KHZ / KVM_GET_TSC_KHZ _IO(KVMIO, 0xa2) / _IO(KVMIO, 0xa3) Set or read x86 TSC frequency; vCPU or VM scope depends on capability
KVM_ENABLE_CAP _IOW(KVMIO, 0xa3, struct kvm_enable_cap) Enable a capability on the fd class documented for it
KVM_GET_ONE_REG / KVM_SET_ONE_REG _IOW(..., 0xab, struct kvm_one_reg) / _IOW(..., 0xac, struct kvm_one_reg) Transfer one register through a userspace pointer
KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad) Tell KVM the vCPU is being stopped by the host
KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list) Enumerate one-reg IDs on applicable architectures

Snapshot implementations also use architecture-specific state families such as XSAVE/XCRS, debug registers, PIT state, irqchip state, and device attributes. The pair must be restored in the ordering required by each ioctl; a bag of structs is not a portable snapshot format.

With KVM_CAP_VM_TSC_CONTROL, the TSC-frequency pair also accepts a VM fd. The set operation then establishes the initial frequency for subsequently created vCPUs and must run before vCPU creation. Otherwise the pair uses the vCPU fd under its vCPU capabilities.

Set the vCPU model before first run. In particular, KVM warns that changing CPUID with KVM_SET_CPUID2 after KVM_RUN may destabilize the guest. Direct kernel boot must also establish the architecture's entry register state rather than assuming firmware initialized it.

The KVM_RUN Contract

KVM_RUN has no explicit argument. It exchanges inputs and outputs through the mapping at offset zero of the vCPU fd:

struct kvm_run {
    __u8  request_interrupt_window;       /* in */
    __u8  immediate_exit;                 /* in */
    /* ... */
    __u32 exit_reason;                    /* out after return value 0 */
    __u8  ready_for_interrupt_injection;  /* out */
    __u8  if_flag;                        /* out, conditionally valid */
    /* exit-specific union follows */
};

A return value of zero makes exit_reason and its matching union member valid. A return of -1 is an error path; for example, an unmasked pending signal produces EINTR. Do not dispatch a stale exit_reason after an error.

immediate_exit is checked once when a KVM_RUN begins. Setting it alone does not eject a vCPU already executing. The scalable kick pattern sends a signal to interrupt the vCPU thread and sets immediate_exit in the signal handler so a racing re-entry returns EINTR instead of running again. It requires KVM_CAP_IMMEDIATE_EXIT and correct cross-thread memory ordering.

For exits that carry an unfinished read or write, re-entering through KVM_RUN completes the operation. This matters for KVM_EXIT_IO and KVM_EXIT_MMIO: userspace must consume write data or provide read data before the next call. See Chapter 8 for the exit-specific union fields.

Capability Checks

Probe the operation, not the kernel version. The capability families used most often in this book are:

Function Capabilities To Check
Memory slots KVM_CAP_USER_MEMORY, KVM_CAP_NR_MEMSLOTS, optionally KVM_CAP_USER_MEMORY2, KVM_CAP_GUEST_MEMFD
vCPU sizing KVM_CAP_NR_VCPUS, KVM_CAP_MAX_VCPUS, KVM_CAP_MAX_VCPU_ID
x86 interrupt model KVM_CAP_IRQCHIP, KVM_CAP_PIT2, optionally KVM_CAP_SPLIT_IRQCHIP
Eventfd fast paths KVM_CAP_IOEVENTFD, KVM_CAP_IRQFD, optionally KVM_CAP_IOEVENTFD_ANY_LENGTH, KVM_CAP_IRQFD_RESAMPLE
Dirty tracking KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, KVM_CAP_DIRTY_LOG_RING, KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP
vCPU state KVM_CAP_VCPU_EVENTS, KVM_CAP_XSAVE or KVM_CAP_XSAVE2, KVM_CAP_XCRS
Run-loop kick KVM_CAP_IMMEDIATE_EXIT

Do not treat every positive result as Boolean. Read the capability's API entry to learn whether the result is a count, size, bitmask, or versioned mode, and whether it must also be enabled with KVM_ENABLE_CAP.

Sources