ArticlesOptimizing Windows VM performance on QEMU and KVM

Optimizing Windows VM performance on QEMU and KVM

Configuring VirtIO drivers, Hyper-V enlightenments, SPICE tools, and storage optimizations for Windows guests on Linux KVM.

Running a Windows guest virtual machine on a Linux host is straightforward with standard type-2 hypervisors like VirtualBox, but those setups introduce noticeable overhead in CPU execution, disk I/O, and graphics latency.

Running applications on bare-metal KVM (Kernel-based Virtual Machine) achieves near-native performance. Unlocking that potential requires paravirtualized VirtIO drivers, Hyper-V enlightenments, and targeted guest OS optimizations.

Prerequisites and host preparation

This guide covers configuration and performance tweaks using Virtual Machine Manager (virt-manager) on Linux hosts.

Ensure the virtualization stack is installed and running on your Linux host:

bash
sudo systemctl enable --now libvirtd.service
sudo systemctl status libvirtd.service

Verifying the libvirtd service status on the Linux host

Before creating virtual machines, add your user account to the relevant virtualization groups to avoid permission prompts:

bash
sudo usermod -aG libvirt $USER
sudo usermod -aG libvirt-qemu $USER
sudo usermod -aG kvm $USER
sudo usermod -aG input $USER
sudo usermod -aG disk $USER

Download the necessary installation media before proceeding:

  • A clean Windows 10 or 11 installation ISO.
  • The latest stable virtio-win.iso driver package from the official Fedora VirtIO repository.

Virtual machine configuration

When creating the new virtual machine in Virtual Machine Manager, check Customize configuration before install on the final creation step.

Selecting customize configuration before starting installation

Storage bus configuration

In the customization window, navigate to your VM disk storage and change the Disk bus from SATA or IDE to VirtIO.

Setting the VM disk bus to VirtIO

Dedicated storage drive passthrough offers the highest throughput if a spare physical NVMe or SATA drive is available. For file-backed storage, VirtIO with QCOW2 or raw images provides substantial I/O improvements over emulated SATA.

Network and video devices

Change the Network Interface device model to virtio to enable paravirtualized network throughput and reduced host CPU overhead.

Selecting VirtIO for the network device model

For video output without dedicated PCIe GPU passthrough, select QXL as the video model.

Configuring QXL as the primary video model

Attaching VirtIO driver media

To load the storage driver during Windows setup, attach the driver ISO as a secondary CD-ROM device:

  1. Click Add Hardware in the bottom-left corner.
  2. Under Storage, select Select or create custom storage and click Manage.

Adding custom storage hardware in virt-manager

  1. Locate the downloaded virtio-win.iso file.
  2. Set the device type to CDROM device and the bus to SATA or IDE.

Configuring virtio-win.iso as a secondary CD-ROM device

  1. Click Begin Installation at the top left to boot the virtual machine.

Applying customization and booting the VM installer

Windows setup and driver injection

When the Windows installer starts, select Custom: Install Windows only (advanced).

Selecting Custom Windows installation

The drive list will appear empty because Windows does not bundle VirtIO SCSI drivers natively. Click Load driver.

Clicking Load driver in the storage partition menu

Browse to the attached virtio-win CD-ROM drive and select the storage driver directory matching your target Windows architecture (for example, viostor\w10\amd64).

Selecting the VirtIO storage driver for Windows 10

Once the driver loads, the virtual disk will appear immediately. Proceed with the standard partition creation and OS installation.

Proceeding with Windows installation on the recognized VirtIO volume

Guest tools and SPICE integration

After completing the initial Windows setup and reaching the desktop, open File Explorer and navigate to the mounted virtio-win CD drive.

Opening the VirtIO CD-ROM drive in Windows File Explorer

Execute virtio-win-guest-tools.exe to install all remaining paravirtualized drivers, including network (NetKVM), balloon memory management, and serial communication.

Launching the virtio-win-guest-tools installer

Accept the default selections and complete the driver package installation.

Completing the VirtIO driver installation wizard

Installing SPICE guest tools

To enable dynamic display resizing, clipboard sharing, and smooth mouse pointer integration, download the latest spice-guest-tools package from the official SPICE repository.

Accessing the SPICE download portal

Download and run the spice-guest-tools Windows installer package.

Installing SPICE guest tools for desktop integration

Hardware channels and hypervisor features

Shut down the guest to add management channels and hypervisor enlightenments.

QEMU guest agent and watchdog

In virt-manager, add a new Channel device with the name org.qemu.guest_agent.0. This enables the host to perform clean ACPI shutdowns, query IP addresses, and freeze filesystems for consistent snapshots.

Adding the QEMU guest agent channel device

Optionally, add a watchdog device (such as i6300esb) with the default reset action to automatically reboot the guest if the kernel hangs.

Configuring a hardware watchdog device

Hyper-V enlightenments configuration

Hyper-V enlightenments allow KVM to emulate Windows-specific hypervisor interfaces, reducing virtualization overhead and clock synchronization drift.

Enable direct XML editing in virt-manager preferences:

  1. Open Edit -> Preferences from the main Virtual Machine Manager menu.

Opening virt-manager preferences

  1. Check Enable XML editing.

Enabling XML editing in preferences

  1. Open the VM details, switch to the XML tab, and add the following <hyperv> block inside <features>:
xml
<features>
  <hyperv>
    <relaxed state='on'/>
    <vapic state='on'/>
    <spinlocks state='on' retries='8191'/>
    <vpindex state='on'/>
    <runtime state='on'/>
    <synic state='on'/>
    <stimer state='on'>
      <direct state='on'/>
    </stimer>
    <frequencies state='on'/>
  </hyperv>
</features>

Adding Hyper-V enlightenments to the domain XML

  1. Add the hypervclock timer inside the <clock> section:
xml
<clock offset='localtime'>
  <timer name='hypervclock' present='yes'/>
</clock>

Adding the hypervclock timer to the XML clock configuration

Operating system storage optimizations

Reclaim disk footprint and reduce host image inflation by tuning guest maintenance settings.

Disable hibernation

Virtual machine state can be managed directly by KVM snapshots. Disabling Windows hibernation removes hiberfil.sys, immediately saving gigabytes of disk space:

shell
powercfg -h off

Disabling Windows hibernation using powercfg

Component store cleanup

Clean up superseded update packages using the Deployment Image Servicing and Management (DISM) tool in an elevated command prompt:

shell
dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase

Running DISM component cleanup to reduce Windows footprint

Disk cleanup automation

Pre-configure Windows Disk Cleanup with all cleaning categories:

shell
cleanmgr /sageset:0

Configuring automated Disk Cleanup options

Execute the cleanup pass:

shell
cleanmgr /sagerun:0

Executing automated Disk Cleanup pass

Trim and drive optimization

Run the Windows Drive Optimizer. When running over VirtIO SCSI with discard support, Windows detects the volume as a thin-provisioned drive and issues TRIM commands back to the host filesystem:

shell
defrag C: /O

Running drive optimization with TRIM discard support

Operational review

With VirtIO drivers, Hyper-V enlightenments, and OS-level trimming applied, the Windows guest operates with low CPU baseline utilization, responsive graphics, and fast disk access.

Final optimized Windows VM operating smoothly on Linux KVM

This architecture separates host resource management from guest execution, delivering a high-performance Windows environment suitable for development and productivity tasks directly on Linux.

Discussion

Comments load from GitHub only when requested. The Article remains available if GitHub is blocked.Open Article discussions on GitHub.