"In het verleden behaalde resultaten bieden geen garanties voor de toekomst"
About this blog

These are the ramblings of Matthijs Kooijman, concerning the software he hacks on, hobbies he has and occasionally his personal life.

Most content on this site is licensed under the WTFPL, version 2 (details).

Questions? Praise? Blame? Feel free to contact me.

My old blog (pre-2006) is also still available.

See also my Mastodon page.

Sun Mon Tue Wed Thu Fri Sat
Powered by Blosxom &Perl onion
(With plugins: config, extensionless, hide, tagging, Markdown, macros, breadcrumbs, calendar, directorybrowse, feedback, flavourdir, include, interpolate_fancy, listplugins, menu, pagetype, preview, seemore, storynum, storytitle, writeback_recent, moreentries)
Valid XHTML 1.0 Strict & CSS
Running an existing Windows 7 partition under QEMU/KVM/virt-manager

I was previously running an ancient Windows XP install under Virtualbox for the occasional time I needed Windows for something. However, since Debian Stretch, virtualbox is no longer supplied, due to security policy problems, I've been experimenting with QEMU, KVM and virt-manager. Migrating my existing VirtualBox XP installation to virt-manager didn't work (it simply wouldn't boot), and I do not have any spare Windows keys lying around, but I do have a Windows 7 installed alongside my Linux on a different partition, so I decided to see if I could get that to boot inside QEMU/KVM.

An obvious problem is the huge change in hardware between the real and virtual environment, but apparently recent Windows versions don't really mind this in terms of drivers, but the activation process could be a problem, especially when booting both virtually and natively. So far I have not seen any complications with either drivers or activation, not even after switching to virtio drivers (see below). I am using an OEM (preactivated?) version of Windows, so that might help in this area.

Update: When booting Windows in the VM a few weeks later, it started bugging me that my Windows was not genuine, and it seems no longer activated. Clicking the "resolve now" link gives a broken webpage, and going through system properties suggests to contact Lenovo (my laptop provider) to resolve this (or buy a new license). I'm not yet sure if this is really problematic, though. This happened shortly after replacing my hard disk, though I'm not sure if that's actually related.

Rebooting into Windows natively shows it is activated (again or still), but booting it virtually directly after that still shows as not activated...

Creating the VM

Booting the installation was actually quite painless: I just used the wizard inside virt-manager, entered /dev/sda (my primary hard disk) as the storage device, pressed start, selected to boot Windows in my bootloader and it booted Windows just fine.

Booting is not really fast, but once it runs, things are just a bit sluggish but acceptable.

One caveat is that this adds the entire disk, not just the Windows partition. This also means the normal bootloader (grub in my case) will be used inside the VM, which will happily boot the normal default operating system. Protip: Don't boot your Linux installation inside a VM inside that same Linux installation, both instances will end up fighting in your filesystem. Thanks for fsck, which seems to have fixed the resulting garbage so far...

To prevent this, make sure to actually select your Windows installation in the bootloader. See below for a more permanent solution.

Installing guest drivers

To improve performance, and allow better integration, some special Windows drivers can be installed. Some of them work right away, for some of them, you need to change the hardware configuration in virt-manager to "virtio".

I initially installed some win-virtio drivers from Fedora (I used the 0.1.141-1 version, which is both stable and latest right now). However, the QXL graphics driver broke the boot, Windows would freeze halfway through the initial boot animation (four coloured dots swirling to form the Windows logo). I recovered by booting into safe mode and reverting the graphics driver to the default VGA driver.

Then, I installed the "spice-guest-tools" from, which again installed the QXL driver, as well as the spice guest agent (which allows better mouse integration, desktop resizing, clipboards sharing, etc.). Using this version, I could again boot, now with proper QXL drivers. I'm not sure if this is because the QXL driver was actually different (version number in the device manager / .inf file was in both cases I believe), or if this was because additional drivers, or the spice agent were installed now.

Switching to virtio

For additional performance, I changed the networking and storage configuration in virt-manager to "virtio", which, instead of emulating actual hardware, provides optimized interaction between Windows and QEMU, but it does require specific drivers on the guest side.

For the network driver, this was a matter of switching the device type in virt-manager and then installing the driver through the device manager. For the storage devices, I first added a secondary disk set to "virtio", installed drivers for that, then switched the main disk to "virtio" and finally removed the secondary disk. Some people suggest this since Windows can only install drivers when booted, and of course cannot boot without drivers for its boot disk.

I did all this before installing the "spice-guest-tools" mentioned above. I suspect that using that installer will already put all drivers in a place where Windows can automatically install them from, so perhaps all that's needed is to switch the config to "virtio".

Note that system boot didn't get noticably faster, but perhaps a lot of the boot happens before the virtio driver is loaded. I haven't really compared SATA vs virtio in normal operation, but it feels acceptable (but not fast). I recall that my processor does not have I/O virtualization support, so that might be the cause.

Replacing the bootloader

As mentioned, virtualizing the entire disk is a bit problematic, since it also reuses the normal bootloader. Ideally, you would only expose the needed Windows partition (which would also provide some additional protection of the other partitions), but since Windows expects a partitioned disk, you would need to somehow create a virtual disk composed of virtual partition table / boot sector merged with the actual data from the partition. I haven't found any way to allow this.

Another approach is to add a second disk with just grub on it, configured to boot Windows from the first disk, and use the second disk as the system boot disk.

I tried this approach using the Super Grub2 Disk, which is a ready-made bootable ISO-hybrid (suitable for CDROM, USB-stick and hard disk). I dowloaded the latest .iso file, created a new disk drive in virt-manager and selected the iso (I suppose a CDROM drive would also work). Booting from it, I get quite an elaborate grub menu, that detects all kinds of operating systems, and I can select Windows through Boot Manually.... -> Operating Systems.

Since that is still quite some work (and easy to forget when I haven't booted Windows in a while), I decided to create a dedicated tiny hard disk, just containing grub, configured to boot my Windows disk. I found some inspiration on this page about creating a multiboot USB stick and turned it into this:

matthijs@grubby:~$ sudo dd if=/dev/zero of=/var/lib/libvirt/images/grub-boot-windows.img bs=1024 count=20480
20480+0 records in
20480+0 records out
20971520 bytes (21 MB, 20 MiB) copied, 0.0415679 s, 505 MB/s
matthijs@grubby:~$ sudo parted /var/lib/libvirt/images/grub-boot-windows.img mklabel msdos
matthijs@grubby:~$ sudo parted /var/lib/libvirt/images/grub-boot-windows.img mkpart primary 2 20
matthijs@grubby:~$ sudo losetup -P /dev/loop0 /var/lib/libvirt/images/grub-boot-windows.img
matthijs@grubby:~$ sudo mkfs.ext2 /dev/loop0p1
(output removed)
matthijs@grubby:~$ sudo mount /dev/loop0p1 /mnt/tmp
matthijs@grubby:~$ sudo mkdir /mnt/tmp/boot
matthijs@grubby:~$ sudo grub-install --target=i386-pc --recheck --boot-directory=/mnt/tmp/boot /dev/loop0
matthijs@grubby:~$ sudo sh -c "cat > /mnt/tmp/boot/grub/grub.cfg" <<EOF
insmod chain
insmod ntfs
search --no-floppy --set root --fs-uuid F486E9B586E9790E
chainloader +1
matthijs@grubby:~$ sudo umount /dev/loop0p1
matthijs@grubby:~$ sudo losetup -d /dev/loop0

The single partition starts at 2MB, for alignment and to leave some room for grub (this is also common with regular hard disks nowadays). Grub is configured to find my Windows partition based on its UUID, which I figured out by looking at /dev/disk/by-uuid.

I added the resulting grub-boot-windows.img as a disk drive in virt-manager (I used SATA, since I was not sure if virtio would boot, and the performance of this disk is irrelevant anyway) and configured it as the first and only boot disk. Booting the VM now boots Windows directly.

0 comments -:- permalink -:- 20:10
Copyright by Matthijs Kooijman - most content WTFPL