Introduction

This page documents the process of converting a dual-boot Linux/Windows installation into a Linux installation running the Windows partition under a KVM virtual machine. This work was first performed under Ubuntu 10.10 and 11.04 versions.

Why virtualize Windows 7?

During my development activities, customer needs infrequently require use of software only available under Windows. But booting between OSes is an incredible waste of time and drain on productivity. My work notebook, a Lenovo X201, came pre-installed with an OEM version Windows 7 Home Premium. The obvious solution? Virtualize Windows under Linux.

Microsoft licensing issues?

The OEM Windows EULA allows for virtualization

I downloaded the EULA for Windows 7 from microsoft.com as applicable for pre-installed OEM versions of Windows 7 Home Premium. For this OS configuration, the license specifically allows execution of the pre-installed OEM OS when virtualized on the same hardware. The actual text is found in Section 3.d:

Use with Virtualization Technologies. Instead of using the software directly on the licensed computer, you may install and use the software within only one virtual (or otherwise emulated) hardware system on the licensed computer. When used in a virtualized environment, content protected by digital rights management technology, BitLocker or any full volume disk drive encryption technology may not be as secure as protected content not in a virtualized environment. You should comply with all domestic and international laws that apply to such protected content.

Virtualization requirements

For Windows virtualization to be effective in my development use cases, the following requirements and constraints must be met. Additionally, I want the virtualization solution to support running additional virtual machines as well.

  • Run 32-bit x86 Windows 7 from 32-bit x86 Ubuntu Linux 10.10 and newer.
  • Run various flavors of Linux or other Intel x86 based operating environments.
  • No unnecessary dependences to software or hardware that will limit the ability of the virtualized OS from functioning properly in the future.
  • Ability to run with native disk, not disk-as-file, for improved IO performance.
  • Supports use of VT-x and VT-d, again for performance.
  • Will be sufficiently performant on the target hardware when virtualized. The X201 has an i5-M560 CPU which offers 4 cores at 2.66 GHz each, and 8 GB of RAM.
  • Simple management of VMs, including configuration, start and stop.
  • VMs must behave sanely in the presence of host OS power saving functionality, like suspend.
  • There is no requirement to continue to run Win7 natively.
  • High end graphics are not required: no need for 3D, Aero effects, video playback, etc.
  • And finally, a reliable mechanism return to the prior physical configuration if the VM experiment fails to work as hoped.

Selecting a virtualization framework

There are a few virtualization options suitable for use on a development system, including VMware, Xen, VirtualBox, and KVM. All can do the job, but KVM was chosen for a variety of reasons:

  • KVM has the features needed, and is available through the standard Ubuntu repositories.
  • KVM management via libvirt is more than adequate.
  • KVM can use an SDL local window for rendering the virtualized OS, for quite good display performance.
  • The enterprise features of Xen are overkill for this application.
  • VMWare is not open source, so there is some concern about support for this particular hardware in the far future (I tend to keep hardware for a very long time).
  • VirtualBox can not access USB hardware unless the purchased version is used.

The virtual machine manager, using libvirt, is a pretty nice environment. This management tool already supports a few different VM strategies, called backends, and they are likely to improve moving forward. Therefore, gaining knowledge about VMM, libvirt, and KVM could in the near future represent an intellectual asset deployable against future customer needs.

Disk organization, pre-virtualization

Prior to any changes, the 320 GB notebook disk drive was organized as follows:

/dev/sda1, 1.17 GiB, Label=SYSTEM_DRV
/dev/sda2, 78.17 GiB, Label=WindowsOS_7
/dev/sda3, 19.68 GiB, Label=Lenovo_Recovery
/dev/sda4, an extended partition container
/dev/sda5, 15.26 GiB, swap partition
/dev/sda6, 23.84 GiB, / partition
/dev/sda7, 159.96 GiB, /home partition
  • The SYSTEM_DRV apparently supports the Lenovo ThinkVantage functionality which includes some backup and restore capability.
  • The WindowsOS_7 partition is the one to virtualize, containing the licensed OEM version of Windows 7 Home Premium that came with this notebook.
  • The system boots using Grub2, which initially included an entry to boot the Windows_7 partition.

The solution

Unfortunately, the solution is not so simple as to point the VM to the /dev/sda2 partition. First, the virtual hardware expects to see a hard drive, complete with partition table. Second, suitable drivers for the virtual hardware must be installed into the windows installation. I took several steps to convert /dev/sda2 in place to look like a hard drive (kpartx, etc) but the best I could accomplish was Windows 7 hanging during boot. Since my expertise with Windows internals is limited, and so is the information available online, I elected to do a clean re-install Windows from the virtual environment.

Create backups

R&R image

Levnovo offers a recovery capability accessible by booting the LenovoRecovery partition. I used this to create a recovery image for the WindowsOS7 partition.

  • Create a windows repair disc from the Win7 OS
  • Create an R&R recovery boot disc
  • Back up the current Win7 image via R&R to the Lenovo_Recovery partition. This required removing all other prior backups because of size constaints in that partition.
  • Back up the current Win7 image to a set of DVD optical discs. It took 3: a boot disc and two data discs.

Partition level backups

Since the space was available in the Linux partition, I opted to create parition level backups as well, which would be 'easier' to restore, at least for me.

# Backup the first MiB of /dev/sda to capture MBR and any bootloader stuff
dd if=/dev/sda of=mbr.save bs=1M count=1
# Use ntfsclone to make a space-efficient copy of the windows partition
ntfsclone --save-image -o - /dev/sda2 | gzip -c > sda2.img.gz

Prepare /dev/sda2 for virtualization

First, /dev/sda2 must look like a DOS style disk, complete with disk level partition information. This can be accomplished using this fdisk command:

fdisk -c -u /dev/sda2

Drive fdisk to create a single windows partition spanning the entirety of the 'disk' (actually the physical partition /dev/sda2). Now /dev/sda2 will look like a valid disk image usable by a VM to re-install Windows 7.

Install the virtualization tools in Linux

sudo apt-get install virt-manager virt-viewer python-vm-builder \
    kvm-pxe ubuntu-vm-builder

I tested the VM tools by creating an Ubuntu 11.04 install. I ran the Virtual Machine Manager using an Ubuntu 11.04 install .iso image as its CD-ROM. The installation was successful and the resulting virtual machine worked without fail.

Re-install Windows 7

Next windows was re-installed. A Windows 7 Home Premium 32-bit OEM .iso was used to do a clean install of Win7. See the virtioinstall.sh script for more information. I used the Win7 iso, and virtual floppy and CD-ROM images from RedHat containing signed virtio drivers for disk and network devices. The VM was started using the virtio disk driver, booting into the Win7 iso. Then the virtual floppy was accessed during the Win7 install process to load in the virtio drivers so the Win7 install program could see the disc, which was of course the disk image on the host /dev/sda partition. I formatted the 'drive' (which is really the /dev/sda2 partition on the physical drive), then proceeded to install Win7 onto it. The installation process, from first boot of the Win7 iso, to first user login to Win7, took just under 45 minutes.

At this point, the VM was stopped so its configuration could be altered it use the virtio network driver. The VM was then restarted with the virtio iso from RedHat connected as the virtual CD-ROM disc. Once Win7 was running, in device manager the drivers for the broken network device were updated from the .iso to get the network running. The virtio network interface seems very efficient. The VM configuration was finally modified to provide for 2 CPU cores and 2 GB of RAM.

Re-activate Windows 7

At this time, Win7 had to be re-activated. The online technique failed, so the phone call technique was required. It was a bit painful, but the end result was a properly activated installation.

Install other Windows 7 tools

Since I installed from scratch, I had to reinstall the few tools I use under Windows. Since these tools were few in number, this process was pretty painless. This strategy would be much more painful if there were lots of tools and/or custom configuration or data required to be recovered.

Improving diplay performance

The default display mechanism when interacting with the Windows VM display is VNC. This is not very performant. Since the Windows VM is only to be accessed from the local hardware, I instead configured the VM to use SDL for rendering the VM display in a window. Interestingly, this change also allowed sound from the Win7 VM to propagate to the sound hardware. The SDL configuration is fast enough to watch Netflix from the VM.

Stop the win7 VM
Reconfigure the VM:
    Remove VNC graphics entry for the VM and add the local SDL one.
    Change the sound driver to ac97
Edit /etc/libvirt/qemu.conf. Add:
    user = "smckown" 
    group = "smckown" 
sudo service libvirtd-bin restart
Restart the virtual machine

Why not SPICE?

The SDL method creates a new local window that hosts the VM display. It cannot be embedded into the virtual manager VM window. It looks like the better solution is going to be to use the SPICE facility. Special drivers in the VM work with special client features to implement a much improved connection. SPICE provides better display performance than VNC, can do stereo sound, and also provides for USB redirection. As of 7/13/12, Ubuntu 12.04 does not have the right stuff to do spice through virt-manager. There is a PPA that will allow it. The nice thing about SPICE is it is network-able and can be embedded. Since network access to the VM is not necessary, the SDL window method seems optimal.

Anti Virus considerations

It should be noted that the VM, as the native install before it, is running Microsoft Security Essentials for Anti-Virus. There appears a noticeable performance hit for using AV within the VM, in comparison to running it natively. Unfortunately, the protection offered is probably worth the performance penalty.

Conclusion

I am quite happy with the results of this process. Win7 boots noticeably faster from the VM than it did on native hardware. Disk CPU are perceptibly sluggish within the VM with respect to native performance, but it is tolerable. Network performance seems on par with native. For the tasks in which I will use Windows, the virtual machine performance is more than adequate.

Of course the big win is that Win7 can be running simultaneously with Ubuntu. This solves a host of workflow problems and removes the terrible inefficiencies caused by having to boot between the two OSes natively. For one, I was able to continue working with apps in the host Ubuntu OS while the Win7 VM chugged away literally for hours downloading and rebooting ad nauseum as it updated itself with the latest Win7 SP1 and subsequent patches.

My overall concern with this strategy is that a change in Microsoft policy could complicate my life. Although this use of my windows license is perfectly legitimate according to my reading of the EULA, I depend upon Windows Product Activation to honor this legitimacy. Here is to hoping that Microsoft will take care to ensure that their WPA policies retain convenient use of Windows for all legitimate uses.


Updates

2012-08-13

After using this configuration for over a year, I have found it to be quite reliable. The upgrade to 12.04 triggered Windows Product Activation, and another phone call to the automated WPA phone number was required. The activation was successful.


Links

The following links, in no particular order, were invaluable in completing this project. Thanks to all those who published their prior experience for others to use!