Windows can run fine under QEMU and KVM, but since installing it with QEMU or libvirt directly is not very straightforward, most people prefer using other hypervisors which have a fancy GUI.

KVM is known to have the best performance as Linux host, and require no external drivers, and with virt-manager it’s not more difficult to setup than other solutions.

A proper Windows installation, with VirtIO drivers and guest tools, will run stable and perform almost as a physical machine.
This is how the system appears:

Get the software

Assuming that your Linux distribution has qemu, libvirt and virt-manager already installed, to proceed download the following:

Put both the ISO in a libvirt pool directory, like /var/lib/libvirt/images/

Prepare the VM

Create a new VM via the virt-manager wizard. Select the Windows ISO as install media and select the “Customize configuration before install” option. Be generous with the disk size, we’ll find out how to avoid space waste later.

At this point, we’ll change the VM definition so to use the VirtIO drivers.

First, go to the disk drive, and set the bus to VirtIO. In the advanced options, set “discard mode” to unmap, to get rid of the virtualized TRIM command and discard the free space in the guest filesystem from the host.

Set the NIC type to VirtIO as well, it has much better performances than emulating a physical card:

To be able to install the VirtIO drivers during setup, add a secondary optical drive, with the virtio driver ISO we downloaded.

In Windows, we may want to use Windows Hello for login using a PIN. This requires a TPM chip, but QEMU can present one to the guest, either software emulated via swtpm, or pass /dev/tpm0 in passthrough:

Not strictly necessary, but nice to have, QEMU can emulate an hardware watchdog to reboot the guest when it hangs.

And a hardware RNG, to get entropy from the host.

At this point, we’re ready to start the install by clicking on “Begin Installation”. Be sure to select BIOS as firmware, because UEFI snapshots are not implemented yet.

Windows installation

At this point the VM starts with the Windows installation running from the optical drive, until it stops because no disk drives are detected.

Press the “load driver” button, and browse E:\viostor\w10\amd64 to find the storage drivers for the virtio disk.

At this point, Windows should detect the virtio bus, and list the drive we created.

Use again the load driver function to install the network card. It’s better to have a working connection during the installation steps.

Not strictly necessary, but might offer a more pleasant experience during installation, load the virtualized GPU drivers as well.

Now finally start the installation and wait for it to complete, after some reboots.

System setup

We installed very mandatory drivers during the installation, now let’s install the optional ones. A convenient installer for all the virtio drivers and the guest agent is at the root of the virtio driver CD.
Guest agent allows to sync the clipboard between the host and guest.

Saving space

At this point Windows is ready to run. Since we use the virtio disk driver, the guest will report to the hypervisor the range of the free space in the filesystem. The hypervisor then will pass this information to QEMU, which will punch holes in the disk image, and free space on the host.
To maximize the savings, we can take some additional steps.

Windows keeps a hiberfil.sys file as big as the system ram to support hibernation. It’s unlikely to use hibernation in a VM, given they can be paused, so disable it by running in an administrator command prompt powercfg -h off.

More free space can be gained by running the cleanup tool:
configure it once with cleanmgr /sageset:0 and select all the checkboxes
then run it every time with cleanmgr /sagerun:0

Windows update stores some backup data to rollback upgrades. Again, it’s unlikely to do it since we have VM snapshots, so this data can be freed by running in an administrator command prompt:
dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase

After we’ve done with all the cleaning, run the Optimize Drive utility from Explorer. Windows will detect the drive as “thin provisioned drive” and issue discards to the host instead of regular disk defragmenting.

After the trim is done, we should have that the disk image in the host is a sparse file, with the real size being much lower than the apparent one:

root@turbo:/var/lib/libvirt/images# ll win10.qcow2
-rw — — — -. 1 root root 101G ott 27 02:23 win10.qcow2
root@turbo:/var/lib/libvirt/images# du -sh win10.qcow2
13G win10.qcow2

proud free software supporter, working @ Microsoft

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store