Switching a Windows KVM guest to Paravirtualised Drivers

Switching a Windows KVM guest to Paravirtualised Drivers

Windows guests on KVM run faster with paravirtualised storage and networking drivers than with fully virtualised (ie emulated) hardware.

However, the initial installation of Windows is easier without paravirtualised drivers, instead using emulated SATA or IDE and Ethernet. I personally could not get installation of Microsoft Windows 2008R2 directly onto a virtio volume to work.

So, the following procedures will switch an already-installed Windows KVM guest from emulated to paravirtualised storage and network drivers. This allows you to install Windows onto emulated IDE or SATA and Ethernet, then switch to the virtio drivers after install.

This is an expanded and updated version of the procedure described on linux-kvm.org.

The steps below focus on using the command line on the Linux KVM host.
Some of these steps are easier to perform using a GUI such as virt-manager. However not everyone has access to and likes using a GUI, so a procedure focusing on the command line is useful.

Paravirtualised Storage

  1. Firstly, check that the guest is using emulated storage drivers. My guest’s Device Manager looked like this:
    Initial configuration: emulated Intel IDE and Realtek 8139 drivers.

    Initial configuration: emulated Intel IDE and Realtek 8139 drivers.

  2. Download an ISO image of the paravirtualised drivers from Fedora. At time of writing, the driver ISO image was the only .iso file in this directory.
    Caution: Version 0.1-49 (now obsolete) caused Blue Screens Of Death with another Windows 2008R2 VM I admin. Version 0.1-52 and later seem OK.
  3. Place the ISO file somewhere on the KVM host. One sensible place is in the default KVM storage pool, which on a Debian system is located at /var/lib/libvirt/images.
  4. Mount the driver ISO image on the guest’s virtual CD-ROM device. Assuming that your VM already has a virtual CD-ROM drive hdc, you can attach an ISO image to this virtual CD-ROM using a command of the form:
    sudo virsh attach-disk myguest /var/lib/libvirt/images/virtio-win-0.1-59.iso hdc --type cdrom
    Alternatively, if you prefer graphical tools, virt-manager has a convenient ‘Connect’ button for this purpose.
  5. Ensure that the guest can see the virtio driver files in its CD-ROM device. A reboot may be necessary.
  6. Create a temporary volume, which we will later access via a paravirtualised driver:
    sudo kvm-img create -f qcow2 /var/lib/libvirt/images/temp.img 1G.
  7. Add the volume to the guest as a paravirtualised device, using a command of the form:
    sudo virsh attach-disk myguest /var/lib/libvirt/images/temp.img vdx --type disk --driver qemu
    At this point Windows will notice the new device, so will require the virtio drivers. Default choices in the provided Windows wizard worked for me. I did not need to reboot, but perhaps you may.
  8. After installation of the paravirtualised storage drivers and any reboot, check (for example using Device Manager) that Windows sees the temporary volume and that it is using virtio drivers to access it rather than emulated IDE, SATA or SCSI.
    Note: It does not matter that there is no valid Windows partition or filesystem on the volume; it is sufficient that Windows be able to access the volume itself using the correct paravirtualised drivers.
    At this point, my VM’s Device Manager looked like this:
    Both emulated Intel IDE and paravirtualised storage drivers installed.

    Both emulated Intel IDE and paravirtualised storage drivers installed.

  9. Dump the guest domain’s XML configuration data (incorporating the changes made by the two attach-disk commands above) to a file. This is necessary because the changes made above do not automatically persist across guest reboots. There may be some way to auto-refresh the domain configuration, but I was unable to find it.
    sudo virsh dumpxml myguest > tmp.xml
  10. Shut down the guest.
  11. Redefine the guest from the saved domain XML file (thus restoring and making permanent the two attach-disk changes made above):
    sudo virsh define tmp.xml
  12. Set the boot and/or system volume(s) to use virtio instead of emulated IDE or SATA.
    In my case I needed to change this:

    <disk type='block' device='disk'>
    <driver name='qemu' type='raw'/>
    <source dev='/dev/vg1/myguest'/>
    <target dev='hda' bus='ide'/>
    <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>

    to this:

    <disk type='block' device='disk'>
    <driver name='qemu' type='raw'/>
    <source dev='/dev/vg1/myguest'/>
    <target dev='hda' bus='virtio'/>
    </disk>

    I omitted the <address> element, which was automagically re-generated with sensible values.
  13. Start the guest again. In my case, immediately after bootup and Administrator login, Windows wanted to be rebooted again (?!), which I permitted.
  14. Confirm that Windows can still see the system, boot and temp volumes and that access to each volume is via the paravirtualised drivers.
    At this point, my guest’s Device manager looked like this:
    Both volumes (boot and temp) using paravirtualised storage drivers.

    Both volumes (boot and temp) using paravirtualised storage drivers.

  15. Shut the guest down.
  16. Remove the temp volume from the guest VM’s configuration, using either a graphical tool or sudo virsh edit myguest
    In my case, I edited the XML and removed the stanza:

    <disk type='file' device='disk'>
    <driver name='qemu' type='raw'/>
    <source file='/var/lib/libvirt/images/temp.img'/>
    <target dev='vdx' bus='virtio'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </disk>
  17. The temporary volume file /var/lib/libvirt/images/temp.img (or other) created in step 6 is no longer necessary. It can now be deleted to save disk space, for example using:
    sudo rm /var/lib/libvirt/images/temp.img
  18. Start the guest again. It should now be using virtio drivers for the boot/system volume(s), and the temp volume should be gone.
    Mine looked like this:
    Boot/system volume using paravirtualised storage drivers; temp volume no longer present.

    Boot/system volume using paravirtualised storage drivers; temp volume no longer present.

Paravirtualised Networking

  1. Obtain access to the graphical console of the Windows guest VM using some means other than direct network access to the guest VM itself. Remote network access to the VM (such as Remote Desktop) is about to break, since we are about to reconfigure the guest’s network access.
    If you have a Linux workstation you can use virt-viewer (part of virt-manager) for this purpose. Otherwise VNC is the way to go. Google Is Your Friend.
    Check that this method of remote access works and that you have Administrator (or equivalent) privilege remotely.
  2. Shut the guest down so we can reconfigure its networking drivers.
  3. Edit the guest domain’s XML configuration file, for example using sudo virsh edit myguest, and modify the <interface> element to use the paravirtualised driver rather than the emulated Ethernet driver.
    In my case, I had to change this:

    <interface type='bridge'>
    <mac address='mymacaddr'/>
    <source bridge='br0'/>
    <target dev='vnet1'/>
    <model type='rtl8139'/>
    <alias name='net0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </interface>

    to this:

    <interface type='bridge'>
    <mac address='mymacaddr'/>
    <source bridge='br0'/>
    <target dev='vnet1'/>
    <model type='virtio'/>
    <alias name='net0'/>
    </interface>

    Again, the <address> element can be omitted, in which case sensible values are automagically generated.
  4. Start the guest again. Its existing emulated Ethernet network interface will have disappeared, and a new paravirtualised network interface (currently without working drivers) will have appeared. We now need to install the paravirtualised network driver.
  5. Warning: Don’t do this
    I naively ran Device Manager, and accepted the default auto-install options from the wizard which appeared. However this seemed to find the wrong drivers, because the wizard completed with an error message, and after it closed, Device Manager displayed:
    Accepting the wizard defaults yields a driver which installs, but does not work.

    Accepting the wizard defaults yields a driver which installs, but does not work.

  6. Instead, forcing installation of the obviously-correct driver by navigating in the wizard to the (well-hidden) ‘Have Disk…’ option, then clicking ‘Browse’, then navigating to the directory D:\WIN7\AMD64 (on the virtual CD-ROM drive) and selecting the file NETKVM.INF, resulted in successful installation of a working driver.
  7. The guest should now be using paravirtualised networking drivers. In my case, Device Manager looked like this:
    Paravirtualised network (and storage) drivers installed

    Paravirtualised network (and storage) drivers installed

  8. Configure the paravirtualised network interface.
    Windows may warn you that the IP address conflicts with that assigned to the now-absent emulated Ethernet device. This is OK; you can either permit Windows to delete the remembered configuration of the now-absent interface, or simply ignore this problem, as the two interfaces will never become active simultaneously.