Running Windows 10 for ARM64 in a QEMU virtual machine
Since the development stages of Windows 10, Microsoft has been releasing a version of Windows that runs on 64-bit ARM (AArch64) based CPUs. Despite some hardware shipping with Windows 10 ARM [1] [2] [3] this port has received little attention and you can barely find programs that run on it.
Naturally, I wanted to try this out to see if it worked. And it turned out it does!
Getting the ISO
I'm not aware of any official page that lets you download an ARM64 ISO, so this part relies on community-made solutions instead:
In the MDL forums I looked for the right ESD download link and used an ESD>ISO conversion script (also found there) to get a bootable ISO.
Alternatively adguard's download page provides similar scripts that download and pack an ISO for you, though they're pretty slow in my experience.
I had no success booting version 2004 or 20H2 (specifically: 19041.388 / 19041.423) so I went with version 1909 (18363.592) instead.
Starting with 18363.1139 Windows seems to require the virtualization extension [7] to be enabled. I had initially used an older version before finding this out, the command line below has now been corrected accordingly. (Updated 2020-12-27)
Installation
Before we begin we also need:
an appropriately sized disk image (
qemu-img create -f qcow2 disk.qcow2 40G
)QEMU_EFI.fd
extracted from theedk2.git-aarch64
RPM found here
The qemu command line then looks as follows:
isoname=19042.631.201119-2058.20H2_RELEASE_SVC_REFRESH_CLIENTENTERPRISE_VOL_A64FRE_DE-DE.ISO virtio=~/Downloads/virtio-win.iso qemu-system-aarch64 -M virt,virtualization=true -cpu cortex-a53 -smp 4 -m 4096 \ -device qemu-xhci -device usb-kbd -device usb-tablet \ -drive file=disk.qcow2,if=virtio \ -nic user,model=virtio \ -drive file="$isoname",media=cdrom,if=none,id=cdrom -device usb-storage,drive=cdrom \ -drive file="$virtio",media=cdrom,if=none,id=drivers -device usb-storage,drive=drivers \ -bios QEMU_EFI.fd -device ramfb
You can then follow the installation process as normal. Before partitioning
the disks the setup will ask you to load disk drivers, these can be found at
viostor/w10/ARM64/
on the virtio cdrom.
Video output
The above command line already takes these limitations into account, these sections are for explanation only.
A previous blogpost on running Windows 10 ARM in QEMU has used a patched EDK2 to get support for standard VGA back in. It's not clear to me why EDK2 removed support if it was working, but this is not a solution I wanted to use either way.
It turns out [4] that the options on ARM are limited to virtio gpu and ramfb. Virtio graphics are Linux-only so that leaves ramfb.
Attaching disk images
Since the virt
machine has no SATA controller we cannot attach a hard disk
to the VM the usual way, I went with virtio here instead.
It would have been possible to do this over usb-storage
, this works out of the box
and would have saved us all the work with virtio drivers (except for networking [5]).
If you do, EDK2 will boot the Windows CD fine but setup will ask you to load drivers early (because it cannot find its own CD). None of the virtio drivers can fix this situation, leaving you stuck with no clear indication what went wrong.
After installation
The onboarding process has a few hiccups (in particular device detection), if you retry it a few times it'll let you continue anyway.
High CPU Usage
After the first boot I noticed two regsvr32.exe
processes at 100% CPU that
didn't seem to finish in reasonable time.
Further investigation with Process Explorer [6] showed these belonging to Windows' printing service. Since I don't want to print in this VM anyway, the affected service can just be stopped and disabled:
Networking
We're still missing the network driver from the virtio cdrom. Unfortunately the NetKVM driver doesn't seem to be properly signed, so you have to enable loading unsigned drivers first (and reboot!):
Afterwards the right driver can be installed from the device manager (NetKVM/w10/ARM64
on cdrom).
General Performance Tweaks
These aren't specific to Windows 10 ARM or Virtual Machines, but can be pretty useful to stop your VM from acting sluggish.
REM Disable Windows Search Indexing sc stop "WSearch" sc config "WSearch" start= disabled REM Disable Automatic Defragmentation schtasks /Delete /TN "\Microsoft\Windows\Defrag\ScheduledDefrag" /F REM Disable Pagefile wmic computersystem set AutomaticManagedPagefile=FALSE wmic pagefileset delete REM Disable Hibernation powercfg -h off
Higher Display Resolution
The default resolution is 800x600, but you can change it in the UEFI menu (press F2 or Esc during boot).
vars-template-pflash.raw
from the same edk package as earlier as UEFI will store its settings in there.-drive file=vars-template-pflash.raw,if=pflash,index=1
The display resolution can then be increased up to 1024x768 under Device Manager > OVMF Platform Configuration.
Wrapping up
With a bit of preparation it is possible to run Windows 10 ARM in a virtual machine. Although the emulation is somewhat slow you could feasibly use this to test one or two programs.
If you have ARM64 hardware with sufficient specs and KVM support, it should be
possible to use -enable-kvm -cpu host
for native execution speed,
though I haven't had a chance to see how this performs yet.