# Linux – Windows 10 UEFI Physical to KVM/libvirt Virtual

linux-kvmp2vuefiwindows 10

# Original Post

I am migrating my PC from Windows 10 to Linux. There are a few things for which I still need Windows, and I am currently dual-booting, with Windows and Linux on separate physical disks. I'd like to get away from dual-booting, and run my Windows 10 installation virtualized under KVM+libvirt+qemu.

The tricky part here seems to be that my Windows 10 install was done through UEFI (with GPT partition table), rather than legacy BIOS MBR. Here's what my Windows disk looks like:

$sudo parted /dev/nvme0n1 print Model: Unknown (unknown) Disk /dev/nvme0n1: 500GB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 1 1049kB 524MB 523MB ntfs Basic data partition hidden, diag 2 524MB 628MB 104MB fat32 EFI system partition boot, esp 3 628MB 645MB 16.8MB Microsoft reserved partition msftres 4 645MB 500GB 499GB ntfs Basic data partition msftdata  Since it was setup as UEFI, it seems there are some extra steps needed to virtualize, as libvirt doesn't appear to support UEFI out of the box. What I tried was to export each of the above partitions as a qcow2 image, with a command like this: $ qemu-img convert -f raw -O qcow2 /dev/nvme0n1p1 win10_part1.qcow2


And repeated for all four partitions. Then I created a virtual machine under virt-manager, importing all four of the qcow2 drives. I installed the "ovmf" package for my distro (Manjaro), and added this line into the virtual machine's XML config file, in the "os" section:

<loader type='rom'>/usr/share/ovmf/x64/OVMF_CODE.fd</loader>


When I boot the virtual machine, I see the TianoCore splash screen. But it just drops me into a grub2 shell, rather than finding the Windows bootloader.

I also tried booting this VM from the Windows 10 install ISO, hoping that I could "repair" the system to boot. But that did not work.

I'm sure I'm missing something. Even better would be to convert this to MBR boot, just to avoid the OVMF dependency.

# Edit/Update…

Per Dylan's comment, I did get it working, but a number of small issues came up along the way, I thought I'd post them here in case others have similar issues.

First step was, as Dylan wrote, to create an image of the whole disk, rather than individual per-partition disks. I used this command:

qemu-img convert -f raw -O qcow2 /dev/nvme0n1 win10_import.qcow2


I then created the virtual machine in virt-manager, specifying the above disk image ("win10_import.qcow2") as my drive.

Next was to use the OVMF (TianoCore) UEFI firmware. This was done by installing the ovmf package ("ovmf" on Manjaro), then adding it to the virtual machine's XML definition:

  <os>
<type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
</os>


After that, Windows would still crash during the boot, with a bluescreen and the error "SYSTEM THREAD EXCEPTION NOT HANDLED". For some reason, it didn't like the "Copy host CPU configuration" CPU setting. I changed to "core2duo", and that booted. Right now I'm using "SandyBridge" and that also works. (For what it's worth, I did create another, separate Win10 VM doing a fresh install from scratch. That VM did work with the "Copy host CPU configuration". My CPU is AMD Ryzen 5 2400G.)

Next problem I encountered was that Windows 10 ran unbearably slow. Somehow I managed to create the VM with the "QEMU TCG" hypervisor, rather than "KVM". This makes sense, as the former is emulation and dreadfully slow, while the latter is true hardware-assisted virtualization. (How this happened: while trying to get this to work, I also did a BIOS upgrade on the physical system, which reset all my BIOS settings, one of which disabled virtualization (called "SVM" in my BIOS). Once I corrected that, I was able to use the near-native speed KVM hypervisor.)

Next issue was that the screen resolution was stuck at 800×600. Windows wouldn't let me change it. I could do a one-time fix by pressing Esc as soon as the machine boots, right when the TianoCore splash appears. That takes me into UEFI settings, where I can force a higher resolution. But this isn't a permanent fix.

Since my virtual machine specified QXL as the video device, I needed to install the QXL drivers in Windows. This page, Creating Windows virtual machines using virtIO drivers explains how to do that. The short version is this: download the virtio-win iso on the host machine. Add it to the VM as a CD-ROM drive. Then, boot into the VM, navigate to the right folder on the CD-ROM, and install all the needed VirtIO drivers. Specifically, for QXL video on Windows 10, the "qxldod" folder has the right driver.