Skip to content
LinuxDeep Dive Published Updated 13 min readViews unavailable

QEMU, KVM, and libvirt on Linux: Separate Execution, Devices, and VM Ownership

Trace the Linux QEMU/KVM stack from host capability checks to guest lifecycle, then choose one owner for storage, networking, security, and operations.

QEMU, KVM, and libvirt are often described as if they were three names for one hypervisor. They are different layers with different responsibilities. QEMU provides a userspace machine and device model. KVM is a Linux kernel interface that can accelerate guest CPU execution using host virtualization facilities. Libvirt is an optional management layer that defines and controls domains, networks, storage, and lifecycle policy.

That separation matters operationally. A QEMU process can exist without using KVM. A KVM-capable host does not by itself define a virtual disk, a virtual network, or a safe VM lifecycle. A guest reaching a login prompt proves neither that its storage is recoverable nor that the host has a production-ready isolation policy.

The execution and management boundaries

The useful mental model is a stack, not a single executable:

Operator or automation
        |
        +-- libvirt API, virsh, virt-install, virt-manager (optional manager)
                    |
                    +-- QEMU userspace process
                              |-- virtual machine and device models
                              |-- storage and network backends
                              |-- KVM API requests through /dev/kvm
                                          |
                                          +-- Linux KVM kernel subsystem
                                                    |
                                                    +-- CPU virtualization facilities

QEMU’s system emulator constructs a guest-visible machine: architecture, machine type, firmware path, CPUs, memory, interrupt controllers, disks, network devices, console, and other device models. Its device front ends and backends handle the host-facing side of those devices. Some data paths can use paravirtualized devices or optional kernel and userspace offloads, but those are separate choices and must be verified for the selected host, guest, and QEMU build.

KVM exposes kernel APIs for creating virtual machines and vCPUs and entering guest execution. On a supported Linux host, QEMU can use KVM as an accelerator. That does not mean KVM replaces QEMU’s machine definition or device model. Many emulated device operations still involve the QEMU userspace process. Conversely, QEMU can use its Tiny Code Generator (TCG) to emulate guest CPU instructions without KVM, including some cross-architecture combinations that hardware-assisted KVM cannot accelerate.

This is why the words QEMU is installed and KVM is available are not interchangeable. QEMU can be used with TCG, KVM, and other accelerators on their supported host platforms. KVM is Linux-specific, and its supported guest architectures and capabilities depend on the host architecture and kernel. Do not assume that KVM on one CPU family accelerates a guest built for an unrelated architecture.

Check the host capability in layers

Begin by recording the host architecture, kernel, and installed QEMU build. Use the guest target binary appropriate to the intended architecture:

uname -m
uname -r
qemu-system-x86_64 --version
qemu-system-x86_64 -accel help

The example uses the x86_64 system emulator. For an ARM host or guest, use the corresponding system emulator and consult that target’s documentation. QEMU options, machine types, accelerator support, and device models are architecture- and build-dependent.

On an x86 host, firmware must expose hardware virtualization and the host kernel must be able to initialize its KVM driver. On other architectures, the relevant processor facility and kernel support differ. The presence of a vmx or svm CPU flag, where those x86 flags apply, is only one diagnostic clue: it does not prove firmware settings, kernel initialization, access permissions, or support for every feature the guest needs.

Check the device and run the distribution’s host validator:

if test -c /dev/kvm; then
  ls -l /dev/kvm
else
  printf '%s\n' "/dev/kvm is not present for this host"
fi

virt-host-validate qemu

virt-host-validate qemu checks whether the host meets a set of prerequisites known to libvirt. A warning or failure is a diagnostic to investigate, not an instruction to disable a security control. A passing report is also not a certification that every optional device, confidential-computing mode, passthrough path, or production workload will work.

If /dev/kvm exists but the current user cannot open it, identify which service, libvirt connection, device permissions, polkit rules, or distribution-specific group policy is intended to grant access. Do not copy a group name from a different distribution and do not apply chmod 666 to /dev/kvm. If the KVM module is not loaded, inspect the kernel’s logs and the distribution’s supported module configuration. A virtualized host may also need nested virtualization enabled by its upstream hypervisor; the guest host cannot manufacture a CPU capability the outer layer does not expose.

The Ubuntu Server documentation covers its libvirt connection setup and host requirements. Red Hat Enterprise Linux documents a different package and service setup, and its supported workflow explicitly favors libvirt tools over manually starting qemu-* commands. Follow the documentation for the actual host distribution rather than combining package names, service units, permissions, and security defaults from unrelated systems.

Choose one owner: direct QEMU or libvirt

Direct QEMU is useful for a disposable experiment, emulator development, or a deliberately managed custom process. The operator or wrapper script then owns the full command line and all state: PID and restart policy, QMP or monitor socket access, disk paths, file permissions, network backend, logs, shutdown behavior, backups, and upgrade compatibility. Starting a process with QEMU does not register a persistent libvirt domain.

Libvirt is usually the better ownership boundary for a persistent Linux VM. It represents a VM as a domain definition, commonly serialized as XML, and provides APIs and tools for lifecycle operations and related network and storage objects. A system connection such as qemu:///system is commonly used for host-managed VMs; a session connection such as qemu:///session has a different user and resource boundary. The exact connection availability and authorization policy vary by distribution. Decide which URI and operator identity own the VM before creating it.

For example, inspect the intended system connection before modifying anything:

virsh -c qemu:///system uri
virsh -c qemu:///system net-list --all
virsh -c qemu:///system pool-list --all

Use virt-install, a supported graphical manager, or reviewed domain XML to create the VM through that same connection. Keep the source definition under change control if the VM is managed as infrastructure. After defining it, inspect the canonical configuration with virsh dumpxml NAME, then use virsh dominfo NAME, virsh domstate NAME, and virsh domiflist NAME to check the manager’s view of its configuration and runtime state.

Libvirt’s persistent domain definition and a running QEMU process are different lifecycle states. A defined domain can be stopped; a transient domain can disappear after shutdown; and host boot does not automatically imply that every defined domain should start. Configure autostart intentionally, document shutdown ordering, and test what happens after a host reboot or a libvirt service restart. Do not start the same writable disk through a manual QEMU command while libvirt or another QEMU process owns it. Concurrent writers can corrupt guest storage.

Red Hat’s RHEL 10 guidance is deliberately stricter than a generic QEMU tutorial: on that supported platform it advises against direct qemu-* commands because manually assembled configurations can miss security and lifecycle settings. That does not make QEMU’s command line irrelevant; it means the supported manager should construct and own it. On another distribution, read that distribution’s policy before treating direct launch as supported administration.

Treat the disk as state, not as a filename

QEMU can consume raw, qcow2, and other supported block backends. A format choice changes capabilities and failure modes. A qcow2 image can have a virtual capacity larger than its current host allocation; guest writes can therefore consume host space later. A backing-file chain makes the visible guest disk depend on multiple files and on their identity and order. Record the complete chain, keep base images immutable while overlays depend on them, and check host free space as well as guest filesystem space.

With libvirt, storage pools and volumes can provide a managed inventory, but they do not remove the operator’s backup responsibility. Confirm the actual source path, format, permissions, ownership, SELinux label or AppArmor policy, capacity, and backing relationships before starting a guest. Avoid mounting or editing a guest disk from the host while the guest is writing to it. Do not attach a host filesystem or physical block device to a guest unless its ownership, exclusivity, and recovery procedure are explicit.

A snapshot is not automatically a backup. A snapshot may be crash-consistent rather than application-consistent, and a qcow2 snapshot or backing chain can still rely on the same host storage and failure domain as the original. For a backup, define how guest writes are quiesced or coordinated, which disk and firmware state must be captured, how the copy is kept independent, and how a restore is tested. Never use a successful guest write as evidence that an independent backup exists.

For a short-lived local experiment, QEMU’s image utility can create an image in a directory owned by the invoking user:

mkdir -p "$HOME/vm-labs"
qemu-img create -f qcow2 "$HOME/vm-labs/lab.qcow2" 20G
qemu-img info "$HOME/vm-labs/lab.qcow2"

This creates an empty virtual disk with a 20 GiB guest-visible capacity; it does not reserve 20 GiB of host space up front. Check the installed QEMU image documentation before using advanced features, and do not run image repair or conversion operations against a disk that is active or has no independent copy.

Design the network as an exposure decision

QEMU’s user-mode network backend and libvirt’s managed virtual networks are not the same object. User-mode networking is convenient for a local test and typically permits guest-originated connections through the host without attaching the guest directly to the physical LAN. It has its own forwarding and protocol limitations; it should not be treated as a bridge or as a complete isolation policy.

Libvirt’s default virtual network, when present and active, commonly uses a host bridge and NAT. The actual configuration is inspectable with virsh net-dumpxml default. A NAT network can provide outbound connectivity, address assignment, and guest-to-guest or host-to-guest reachability according to its configuration. It is not equivalent to an air gap. A bridged network instead places the guest on a LAN-level link, where the guest may receive inbound traffic like another machine; apply the LAN’s firewall, address management, and monitoring controls.

Start with no network for an installer or test that does not need connectivity. Otherwise choose an explicit network model, list the allowed destinations and inbound paths, and verify the live network definition, host firewall behavior, guest firewall, and any port forwarding. Do not respond to a guest connectivity problem by switching to a bridge or forwarding management ports without understanding the exposure change.

Keep host-guest security controls intact

A VM is a useful isolation boundary, not a proof that hostile guest code cannot affect the host. Guest data is processed by QEMU’s device models, host libraries, kernel interfaces, and any enabled shared resources. A compromised guest can also use its assigned network path. Keep the host kernel, QEMU, libvirt, firmware packages, and guest patched under the distribution’s supported update process.

Use the distribution’s managed confinement and privilege separation. Depending on the system, this can include QEMU running under a restricted service identity, SELinux sVirt labeling, AppArmor profiles, seccomp sandboxing, polkit authorization, and cgroup resource limits. Exact features and defaults vary. On RHEL 10, SELinux enforcing mode enables its sVirt virtualization feature, and Red Hat documents several libvirt-provided security controls. On Ubuntu, review the libvirt and AppArmor behavior for the installed release. Do not turn off SELinux, AppArmor, or QEMU sandboxing to make a VM launch; diagnose the denial, confirm the intended disk label or path, and change only the narrow policy that is justified.

Keep the guest’s writable storage inside the VM’s managed storage boundary, expose only required devices, and treat directory sharing, USB, PCI passthrough, host sockets, and clipboard integration as deliberate trust expansions. Do not expose a QEMU monitor or QMP control socket to an untrusted network. Protect management sockets and remote libvirt access with the distribution’s documented authentication and transport configuration. The VM should not run with more host privilege than its devices and workload require.

Diagnose failures by layer

Use the earliest failing boundary instead of changing several settings at once:

  • If the management tool cannot connect, check its libvirt URI, daemon/socket availability, polkit authorization, and whether the system or session connection was intended.
  • If QEMU cannot initialize KVM, verify host architecture, firmware virtualization settings, kernel support, /dev/kvm access, and any outer-hypervisor restrictions. Compare with a controlled TCG run only as a diagnostic; it is not a performance-equivalent production fallback.
  • If QEMU starts but firmware or the guest does not boot, inspect the machine type, firmware image and variable store, boot order, installer architecture, and guest console path.
  • If the guest boots but has no network, inspect the guest driver and address configuration, selected virtual network, DHCP or bridge state, host routing, and firewall rules separately.
  • If a disk cannot be opened, investigate host permissions, ownership, MAC labels, filesystem mount state, and libvirt’s storage path before altering guest partitions.
  • If the desktop appears but the workload is slow or unstable, measure CPU scheduling, memory pressure, storage latency, device support, and guest logs. A boot screen is not a performance test.

Capture the distribution release, kernel and QEMU/libvirt versions, host and guest architectures, connection URI, domain XML, machine and CPU model, accelerator choice, storage format and backing chain, network mode, and the first failing log message. Remove secrets and private network details before sharing logs. Avoid “fixes” such as recursively changing permissions, disabling mandatory access control, deleting the only image, or adding undocumented QEMU flags.

Define what a successful VM means

A QEMU process that remains alive is a host-process result. A libvirt domain reported as running is a manager/runtime result. A guest reaching its installer or login prompt is a boot result. None alone proves that the guest’s services are healthy, that its network policy is correct, that disk writes survive an unclean host failure, that a backup restores, or that the configured isolation controls are active.

For a supportable VM, validate each layer explicitly: the intended accelerator is selected; guest boot and required devices work; storage capacity and recovery are tested; network exposure matches policy; security labels and process confinement are intact; clean shutdown works; host reboot behavior is known; and a backup has been restored on a compatible test target. Record the exact host, guest, QEMU, libvirt, firmware, machine type, and device configuration so that another operator can reproduce the result.

The practical boundary is simple: QEMU defines and runs the machine model, KVM accelerates supported CPU execution through the Linux kernel, and libvirt can own persistent VM configuration and lifecycle. Decide who owns each writable resource and every lifecycle transition. Then a successful start becomes one verified signal in a larger acceptance test, not a claim that the whole virtualization service is production-ready.

Related:

Sources:

Comments