Up to Main Index                          Up to Journal for February, 2025

                    JOURNAL FOR MONDAY 17TH FEBRUARY, 2025
______________________________________________________________________________

SUBJECT: KVM+QEMU Windows 10 to 11 upgrade on Alder Lake
   DATE: Mon 17 Feb 18:53:43 GMT 2025

This was supposed to be published last week. However, I had a nasty bout of
the winter vomiting bug (Norovirus). At the same time my home lab went down
and I was too ill at the time to fix it :(

I hate Windows, I really do. I want my computer to do what I tell it to do
when I tell it. I don’t want to be sitting around waiting while the OS is off
doing it’s own thing in the background holding me up. Having said that, I do
need to occasionally use Windows — mostly for testing software I’ve written.
Some users of my software are Windows users and I need to support them.

Ironically, I’m actually enrolled in the Windows Insider Program... :|

Until now, I have had Windows 10 running in a KVM+QEMU virtual machine. My
main desktop has a 12th Gen Alder Lake i9-12900T CPU. Getting KVM+QEMU running
on Alder Lake properly, with more than 2 CPUs in the guest, is not an easy
task. QEMU does not like the mix of performance and efficiency cores. The best
incantation I came up with was:


    taskset -c 2-7,12-15 \
    qemu-system-x86_64 \
      -accel kvm \
      -cpu host,level=30 \
      -device ahci,id=ahci \
      -device usb-tablet \
      -device virtio-net,netdev=n1 \
      -display vnc=127.0.0.2:0 \
      -drive id=disk,file=./disk.qcow2,if=virtio \
      -m 16G \
      -netdev bridge,br=br0,id=n1 \
      -rtc base=localtime,clock=host \
      -smp 8,sockets=1,cores=4,threads=2,maxcpus=8 \
      -usb


This lets me run Windows 10 with 8 CPUs and 16Gb RAM. It uses the bridged
networking for fast access to the local network through the host. The host is
currently Debian Trixie (testing). It runs in the background and I connect via
VNC. The taskset limits the VM to only run on some performance cores. I’m not
saying this is the best setup to use, it’s the setup that works for me on my
machine.

The upcoming Windows 10 end-of-life on October 14th prompted me to think about
upgrading to Windows 11. That and the fact I have Windows 11 users to support.
These notes detail how I upgraded Windows 10 to Windows 11 in the VM and may
be of some help to others also wanting to upgrade.

Be warned, upgrading is a nightmare. First of all I had to meet the Windows 11
minimum requirements. CPU was fine. I hadn’t exposed my hardware TPM to the VM
and didn’t want to. Then there was the disk space as I’d only allocated 40Gb
to the VM. I also needed to convert the disk to UEFI for secure boot.

The TPM issue was dealt with by installing the swtmp package. This provides a
software emulated TPM 2.0 device. I start swtmp at the beginning of my startup
script with a sleep to let it initialise and settle:


    swtpm socket --tpmstate dir=./tpm1 \
      --ctrl type=unixio,path=./tpm1/swtpm-sock --tpm2 &
    sleep 5


NOTE: Update the path as appropriate for your setup. I did try to find a nice
way to detect when the TPM device was initialised and failed, hence sleeping.

To sort out the disk I first had to resize it from 40Gb to 100Gb:


    qemu-img resize ./disk.qcow2 +60G


Then I had to resize the partitions in Windows 10. This involved deleting and
recreating the recovery partition as it was in the way and preventing the main
data partition from being extended. On Windows, as admin in a command prompt,
replace “disk 0” with your disk and “part 3” with your recovery partition:


    reagentc /disable
    diskpart
    list disk
    sel disk 0
    list part
    sel part 3
    delete part override


Then extend the data partition using disk manager. Make sure to leave 1Gb free
for the recovery partition if you want it back again. To recreate the recovery
partition on a basic partition:


    diskpart
    create partition primary size=1000 id=27


Then re-enable the recovery partition:


    reagentc /enable


Now to convert the disk to UEFI:


    boot to the recovery environment (hold shift while restarting Windows)
    select Troubleshoot
    select Advanced options
    select Command prompt
    check if the disk can be converted:
        mbr2gpt.exe /validate
    if there are no errors, convert:
        mbr2gpt.exe /convert


That’s the disk resized and converted to UEFI.

On the Debian host the ovmf package needs to be installed. It provides the
UEFI firmware the VM needs for secure boot. Make a copy of OVMF_VARS_4M.ms.fd
into your local VM directory.

Now the TPM device and KVM+QEMU can be used to start the VM. This is the Bash
script I run to bring everything up:


  swtpm socket --tpmstate dir=./tpm1 \
    --ctrl type=unixio,path=./tpm1/swtpm-sock --tpm2 &
  sleep 5
  taskset -c 2-7,12-15 \
  qemu-system-x86_64 \
    -accel kvm \
    -boot menu=on \
    -chardev socket,id=chrtpm,path=./tpm1/swtpm-sock \
    -cpu host,level=30 \
    -device ahci,id=ahci \
    -device tpm-tis,tpmdev=tpm0 \
    -device usb-tablet \
    -device virtio-net,netdev=n1 \
    -display vnc=127.0.0.2:0 \
    -drive id=disk,file=./disk.qcow2 \
    -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE_4M.ms.fd,readonly=on \
    -drive if=pflash,format=raw,unit=1,file=./OVMF_VARS_4M.ms.fd \
    -global driver=cfi.pflash01,property=secure,value=on \
    -global kvm-pit.lost_tick_policy=discard \
    -m 16G \
    -machine q35,smm=on,hpet=off \
    -netdev bridge,br=br0,id=n1 \
    -rtc base=localtime,clock=host,driftfix=slew \
    -smp 8,sockets=1,cores=4,threads=2,maxcpus=8 \
    -tpmdev emulator,id=tpm0,chardev=chrtpm \
    -usb


If you use the bridge networking and have permission problems try updating the
helper permissions, which get reset when the qemu-system-common package is
updated. As root:


  chmod u+s /usr/lib/qemu/qemu-bridge-helper


Next, go into Windows update and upgrade to Windows 11.

The only thing missing after upgrading to Windows 11 was the virtio SCSI
drivers on the disk. For this I had to temporally create a dummy disk:


  qemu-img create dummy.qcow2 1G


Then add the following to the configuration:


  -drive id=disk1,file=./dummy.qcow2,if=virtio


Add the CD-ROM image with the virtio drivers:


  -cdrom ./virtio-win-0.1.229.iso


The virtio ISO can be downloaded from Fedora People[1]. The 0.1.229 version is
not the latest, but the version that worked for me.

Restart the VM and install the drivers for virtio SCSI on the dummy disk from
the CD-ROM image. Modify the configuration and change:


  -drive id=disk,file=./disk.qcow2

To:

  -drive id=disk,file=./disk.qcow2,if=virtio


Restart the VM again. In the device manager both disks should be using the
Red Hat virtio SCSI drivers.

Shutdown the VM and remove the two previously added lines from the
configuration:


  -drive id=disk1,file=./dummy.qcow2,if=virtio

  -cdrom ./virtio-win-0.1.229.iso


Start the VM and the virtio SCSI drivers should now load properly for the data
drive. The dummy.qcow2 can be removed from the host.

In Windows, doing a disk clean-up, including system files, when everything was
finished reclaimed about 25Gb of space.

One point of note. Adding the machine type “-machine q35,smm=on” caused
Windows to deactivate the Windows license linked to my account due to
“extensive hardware changes”. I tried to reactivate the license a number of
times before giving up. Then suddenly everything was okay and activated :/

Second point of note: It really bugs me that Windows 11 idles, doing “nothing”
but running itself, at 14-16% CPU usage.

If anyone has comments or any handy tips they want to add, drop me a quick
email: diddymus@wolfmud.org

--
Diddymus

  [1] Windows virtio ISO download archive @ Fedora People:
      https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/


  Up to Main Index                          Up to Journal for February, 2025