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/kvmand 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
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.