Skip to content

Instantly share code, notes, and snippets.

@Vogtinator
Last active June 16, 2024 00:50
Show Gist options
  • Save Vogtinator/293c4f90c5e92838f7e72610725905fd to your computer and use it in GitHub Desktop.
Save Vogtinator/293c4f90c5e92838f7e72610725905fd to your computer and use it in GitHub Desktop.
Run Win11 on ARM in QEMU

When following this guide on a host not capable of native arm64 KVM, replace -M virt -cpu host -accel kvm with -M virt,virtualization=on -cpu max.

The reason for virtualization=on is that the Windows bootloader does an smc #0 PSCI call, but without EL2, QEMU's TCG does not handle those because PSCI is in HVC mode and such that instruction is treated as undefined. With KVM enabled, smc #0 is handled properly.

Workaround in QEMU for using TCG without virtualization=on:

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b871350856..de11ff51d1 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2056,7 +2056,7 @@ static void machvirt_init(MachineState *machine)
      */
     if (vms->secure && firmware_loaded) {
         vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
-    } else if (vms->virt) {
+    } else if (1 || vms->virt) {
         vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC;
     } else {
         vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
  1. Download the VM disk image from https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewarm64 and the latest virtio-win.iso from https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/. Build 22589 is known to work, while build 25226 is known not to work (unhandled exception during boot).
  2. Perform the initial boot. For some reason performance is abysmal with the GTK UI, so use VNC: qemu-system-aarch64 -M virt -cpu host -accel kvm -m 2G -smp 2 -device ramfb -bios /usr/share/qemu/qemu-uefi-aarch64.bin -device qemu-xhci -device usb-kbd -device usb-tablet -drive file=Windows11_InsiderPreview_Client_ARM64_en-us_22598.VHDX,format=vhdx,if=none,id=boot -device usb-storage,drive=boot,serial=boot -drive file=virtio-win.iso,media=cdrom,if=none,id=iso -device usb-storage,drive=iso -nic user,model=virtio-net-pci,mac=52:54:98:76:54:32 -vnc :0. On some earlier QEMU/kernel (?) versions, ramfb has some issues with invalidation (?) causing artifacts, you'll have to ignore them until virtio-gpu can be used. At least since build 25931, it's necessary to provide a network connection to finish the initial setup. The default QEMU MAC address will result in a false UUID match with some AutoPilot enrolled devices, forcing an "Intellek" domain login. To avoid that, use a different MAC address, e.g. 52:54:98:76:54:32 from the QEMU man page. To have a higher resolution with ramfb, enter the OVMF setup by pressing F10 during boot, change the preferred resolution to 1024x768 and reset.
  3. This might take a while. If it appears stuck at "Getting ready" for 10min (give it a bit more time without KVM) or you get a BSOD (watchdog timeout), reset. If you get an error message "Windows installation cannot proceed", press Shift-F10 to open a cmd, run regedit and set HKEY_LOCAL_MACHINE\SYSTEM\Setup\Status\ChildCompletion\Setup to 3 and click on Ok to reboot.
  4. When it asks for the initial setup (country, keyboard layout) press Shift-F10 to open a cmd, or (if it does not work) Ctrl-Shift-Esc to open the task manager and launch cmd with admin privs.
  5. Run bcdedit /set TESTSIGNING ON to allow loading some drivers during boot. While virtio drivers are signed, they don't work without this for some reason.
  6. Start explorer.exe, navigate to the virtio drivers in D: and install NetKVM, viogpudo, viostor and vioscsi by right clicking on the .inf file within the w11/ARM64 folders and selecting "Install". If it complains about driver signatures, navigate to the cert folder and install the certificate into the devices Trusted Publishers store.
  7. Complete the setup as usual. To avoid using a Microsoft account, attempt to sign in as "Administrator" with some random string as password, then click "Next" on the "Oops, something went wrong" screen.
  8. Shut down Windows.
  9. Now virtio devices can be used: qemu-system-aarch64 -M virt -cpu host -accel kvm -m 4G -smp 4 -device virtio-gpu-pci -bios /usr/share/qemu/qemu-uefi-aarch64.bin -device qemu-xhci -device usb-kbd -device usb-tablet -drive file=Windows11_InsiderPreview_Client_ARM64_en-us_22598.VHDX,format=vhdx,if=none,id=boot -device virtio-scsi -device scsi-hd,drive=boot -nic user,model=virtio-net-pci,mac=52:54:98:76:54:32 -vnc :0. The first boot will take a while with a disabled display, be patient. If it does not work, try to boot with the previous QEMU command but also add -device virtio-gpu-pci and some virtio-scsi HD, to make sure the driver is properly selected.

openQA expects a resolution of 1024x768. The default is 1280x1024 and for some reason there's no option to change that in the UI, so it has to be done in the registry directly. This needs to be done with a very similar command line to actual QA jobs, otherwise the device doesn't match (based on PCI address).

  1. Ctrl-Shift-Esc to open taskmgr
  2. "Run new task", enter regedit and run it with admin privs
  3. Navigate to HKLM/SYSTEM/CurrentControlSet/Control/GraphicsDrivers/Configuration/RHT*/00
  4. Set PrimSurfSize.cx to 1024, PrimSurfSize.cy to 768 and Stride to 4096 (decimal!)
  5. Reboot

To avoid having to add new needles, switch the desktop wallpaper to the one used by the existing win11 tests and change the terminal in the developer settings to "Windows Console Host". Also set a fixed background picture for the lock and sign in screens.

Windows on Arm has a different model for serial ports, the usual methods to access them no longer work. However, FTDI ported the old serial port bus to Arm and it works with the usb-serial device! Download https://www.ftdicommunity.com/index.php?topic=753.0 and extract it somewhere. The "QEMU USB SERIAL" device needs the driver assigned manually by using the device manager to To use it with openQA, pass -chardev ringbuf,id=usbserial,logfile=serial0,logappend=on -device usb-serial,chardev=usbserial. This uses a bit of a hack as it writes into the same file as the default serial port (pl011, not usable as COM port), but there's no other way as QEMU does not allow using a chardev from multiple devices. Native support for usb-serial in os-autoinst would be the right way. usb-serial also conflicts with -no-migratable, so QEMU_DISABLE_SNAPSHOTS=1 needs to be passed.

If this is build 25267 or newer, SMB guest authentication needs to be enabled (https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/guest-access-in-smb2-is-disabled-by-default), but it appears to be broken even with this, just differently...

  1. Run gpedit.msc
  2. Computer Configuration > Administrative Templates > Network > Lanman Workstation.
  3. Enable insecure guest logons -> Enable

Not specific to Arm: To optimize the qcow2 size, start the VM with discard=unmap on the qcow2 block dev. In a powershell, run Optimize-Volume -Verbose -DriveLetter C -ReTrim and shut down. Run qemu-img convert -pc -O qcow2 for_cleanup.qcow2 Win11ArmBuild25931.qcow2 to discard the unmapped space and perform recompression.

Based on a win11 x86_64 (UEFI) test:

openqa-clone-job --within-instance https://openqa.opensuse.org --skip-chained-deps 3546891 _GROUP=38 ARCH=aarch64 HDD_1=win11_22598.qcow2 QEMUMACHINE=virt QEMUVGA= QEMU_VIDEO_DEVICE=virtio-gpu-pci UEFI_PFLASH_CODE=/usr/share/qemu/aavmf-aarch64-code.bin UEFI_PFLASH_VARS=/usr/share/qemu/aavmf-aarch64-vars.bin WORKER_CLASS=qemu_aarch64 HDDMODEL=scsi-hd QEMU_DISABLE_SNAPSHOTS=1 "QEMU_APPEND=chardev ringbuf,id=usbserial,logfile=serial0,logappend=on -device usb-serial,chardev=usbserial"

It's also possible to run WSL2 inside the Windows VM. However, that uses Hyper-V and thus requires hardware virtualization. Nested virtualization is not supported by existing hardware yet (and might lead to issues in the guest as well), so software emulation is needed.

Just -M virt,virtualization=on -cpu max as used above in the non-KVM case will not work though: Windows no longer boots if the hypervisor is enabled. With WinDbg attached it complains about unexpected register values which indicate that it expects the CPU to have EL3.

Using https://github.com/ARM-software/arm-trusted-firmware in EL3 (following https://trustedfirmware-a.readthedocs.io/en/latest/plat/qemu.html) does not work though, it leads to Windows failing to initialize interrupts. Presumably some of the ATF initialization confuses the Windows kernel.

There's a way around ATF though: QEMU's -kernel option allows to have a CPU with EL3 but boot directly into EL2. To be able to use OVMF with that option (instead of -bios), it has to be built as Linux kernel image. A prebuilt QEMU_EFI.fd is available at http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd.

With -cpu max this still fails though because Windows tries to access HDFGRTR_EL2, which ends up trapping into EL3 which does not exist -> stuck. Fix for QEMU (https://lists.nongnu.org/archive/html/qemu-devel/2023-09/msg03039.html):

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 720f22531a..24fa169060 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -761,6 +761,10 @@ static void do_cpu_reset(void *opaque)
                     if (cpu_isar_feature(aa64_hcx, cpu)) {
                         env->cp15.scr_el3 |= SCR_HXEN;
                     }
+                    if (cpu_isar_feature(aa64_fgt, cpu)) {
+                        env->cp15.scr_el3 |= SCR_FGTEN;
+                    }
+
                     /* AArch64 kernels never boot in secure mode */
                     assert(!info->secure_boot);
                     /* This hook is only supported for AArch32 currently:

As a workaround, -cpu neoverse-n1 can be used, which does not expose the feature with that register. QEMU before 8.1 is missing also SCR_HXEN and probably others, so won't work without code changes.

Full QEMU command with WSL2/Hyper-V support (tested with Build 25931):

qemu-system-aarch64 -M virt,virtualization=on,gic-version=3,secure=on -cpu neoverse-n1 -m 4G -smp 4 -device virtio-gpu-pci -kernel QEMU_EFI.fd -device qemu-xhci -device usb-kbd -device usb-tablet -drive file =Win11ArmBuild25931.qcow2,if=none,id=boot -device virtio-scsi -device scsi-hd,drive=boot,serial=hd0 -nic user,model=virtio-net-pci,mac=52:54:98:76:54:32 -vnc 0

@Scherlac
Copy link

@Vogtinator Hi, Can you please give some hint on which qemu version the description in the README.md could work?

on armbian with ubuntu using the following package I face some issue:

qemu-system-arm/jammy-security,jammy-updates,now 1:6.2+dfsg-2ubuntu6.6 arm64

Issues:

  • the file /usr/share/qemu/qemu-efi-aarch64.bin is not available, I've replaced with /usr/share/qemu-efi-aarch64/QEMU_EFI.fd I have no ide if it would work since afterwards I get an other issue, see below
  • qemu-system-aarch64: failed to find romfile "efi-virtio.rom"

@Vogtinator
Copy link
Author

@Vogtinator Hi, Can you please give some hint on which qemu version the description in the README.md could work?

I tried it on a Tumbleweed system at the time but also on the openqa.opensuse.org infrastructure which runs Leap 15.4 ATM. Should be some QEMU 6.x in both cases. I don't think the version is critical here.

on armbian with ubuntu using the following package I face some issue:

qemu-system-arm/jammy-security,jammy-updates,now 1:6.2+dfsg-2ubuntu6.6 arm64

Issues:

  • the file /usr/share/qemu/qemu-efi-aarch64.bin is not available, I've replaced with /usr/share/qemu-efi-aarch64/QEMU_EFI.fd I have no ide if it would work since afterwards I get an other issue, see below

Yeah, the location of OVMF is not really standardized. Your path probably works.

  • qemu-system-aarch64: failed to find romfile "efi-virtio.rom"

That's part of qemu-ipxe here, but should only be necessary for booting from network. You can try to install pixe-qemu on your system.

@Scherlac
Copy link

Scherlac commented Apr 1, 2023

On armbian using a rk3318 chip based system with 4GB ram I've ended up by rebuilding qemu using the following version:

commit b67b00e6b4c7831a3f5bc684bc0df7a9bfd1bd56 (HEAD, tag: v7.2.0)

I've also built the glib using the following version:

commit 8723aba598c96baa4e8c5cd98ef4677de1ee0780 (HEAD, tag: 2.56.4)

I used the following command to start the qemu (initially with ramfb than with virtio-gpu-pci ):

qemu-system-aarch64 \
        -machine virt -accel kvm -cpu host -m 3.8G -smp 3 \
        -bios /usr/local/share/qemu/edk2-aarch64-code.fd \
        -device virtio-gpu-pci \
        -device qemu-xhci \
        -device usb-kbd \
        -device usb-tablet \
        -drive file=Windows11_InsiderPreview_Client_ARM64_en-us_22598.VHDX,format=vhdx,if=none,id=boot \
        -device usb-storage,drive=boot,serial=boot,bootindex=1 \
        -drive file=virtio-win-0.1.229.iso,media=cdrom,if=none,id=iso \
        -device usb-storage,drive=iso \
        -serial stdio \
        -display vnc=:0

I was able to install Windows 11, kind of. It works, but it is slow :)

@Vogtinator
Copy link
Author

I was able to install Windows 11, kind of. It works,

Ok, so 6.2 was indeed too old for some reason?

but it is slow :)

Yeah, that chip isn't fast at all, same level as a RPi3 with 4 x Cortex-A53.
Those are in-order and in this design run at a relatively low frequency as well.

@Scherlac
Copy link

Scherlac commented Apr 3, 2023

I had no luck with the bios QEMU_EFI.fd. The source ( v7.2.0) I used to rebuild the qemu also installed the file edk2-aarch64-code.fd.

@Vogtinator
Copy link
Author

I had no luck with the bios QEMU_EFI.fd. The source ( v7.2.0) I used to rebuild the qemu also installed the file edk2-aarch64-code.fd.

QEMU_EFI.fd might be in Linux kernel image format instead of plain ROM format. In that case you'll have to use -kernel instead of -bios.

@raspiduino
Copy link

I have a small and might be helpful tip for successfully booting EDK2 on QEMU.

First, go to https://retrage.github.io/edk2-nightly/ and download RELEASEAARCH64_QEMU_EFI.fd or DEBUGAARCH64_QEMU_EFI.fd, it's up to you but just download one file. I will use RELEASEAARCH64_QEMU_EFI.fd for this, but feel free to use the release version.

Then open your shell (on Windows you can use msys2 or Cygwin or even git bash) and run:

dd if=/dev/zero of=QEMU_EFI.bin bs=1M count=64
dd if=RELEASEAARCH64_QEMU_EFI.fd of=QEMU_EFI.bin conv=notrunc
dd if=/dev/zero of=QEMU_VARS.bin bs=1M count=64

Then instead of using -bios /usr/share/qemu/qemu-uefi-aarch64.bin you can use -pflash QEMU_EFI.bin -pflash QEMU_VARS.bin.

Everything else is the same. You will get latest EDK2 boot instantly.

@trungnt2910
Copy link

I tried to follow your guide, but at step 9, I was stuck in some kind of bootloop.

I am sure that I have got the 4 required drivers installed, and with test signing enabled on boot.

However, when trying to boot with a SCSI device, I got a BSOD:

image

@Vogtinator
Copy link
Author

I tried to follow your guide, but at step 9, I was stuck in some kind of bootloop.

I am sure that I have got the 4 required drivers installed, and with test signing enabled on boot.

Did you try what step 9 says?

If it does not work, try to boot with the previous QEMU command but also add -device virtio-gpu-pci and some virtio-scsi HD, to make sure the driver is properly selected.

In the device manager you might have to select the driver manually.

@trungnt2910
Copy link

trungnt2910 commented Jan 20, 2024

For a second machine, which was initially set up using another guide and installed from an .iso file instead of directly from a .vhdx download, I got it booting using a SCSI device. When running Windows 11 with both ramfb and virtio-gpu-pci, the system recognizes the presence of two monitors:

qemu-system-aarch64 \
  -M virt -m 12G -cpu host -smp 8,sockets=1,cores=8 \
  -s \
  -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
  --accel kvm \
  -vnc :0 \
  -device ramfb \
  -device virtio-gpu-pci \
  -device qemu-xhci -device usb-kbd -device usb-tablet \
  -device virtio-scsi \
  -nic user,model=virtio-net-pci,mac=52:54:98:76:54:32,hostfwd=tcp::3389-:3389 \
  -device usb-storage,drive=install \
  -drive if=none,id=install,format=raw,media=cdrom,file=./26020.1000.231214-1452.RS_PRERELEASE_CLIENTPRO_OEMRET_A64FRE_JA-JP.ISO \
  -device usb-storage,drive=virtio-drivers \
  -drive if=none,id=virtio-drivers,format=raw,media=cdrom,file=./virtio-win.iso \
  -device scsi-hd,drive=system \
  -drive if=none,id=system,format=raw,file=./win11.img

image

image

But when I tried to boot it using just virtio-gpu-pci, it just gets stuck.

@trungnt2910
Copy link

If it does not work, try to boot with the previous QEMU command but also add -device virtio-gpu-pci and some virtio-scsi HD, to make sure the driver is properly selected.

In the device manager you might have to select the driver manually.

So, I would need a different virtio-scsi hard drive?

@Vogtinator
Copy link
Author

Yeah, you could use the virtio-win.iso as scsi-cd for instance

@trungnt2910
Copy link

Thanks, that worked!

@trungnt2910
Copy link

So, for some reasons, the mentioned method fails when I attach bootable media of any kind:

  -device usb-storage,drive=install \
  -drive if=none,id=install,format=raw,media=cdrom,file=./26020.1000.231214-1452.RS_PRERELEASE_CLIENTPRO_OEMRET_A64FRE_JA-JP.ISO

Despite not pressing anything at the "Press any key to boot from CD or DVD..." screen, somehow Windows from the main disk just does not load.

Adding normal, non-bootable media works fine.

@rpm-arch
Copy link

Attempting this on Debian Bullseye. QEMU_EFI.fd did work for me, although it took a long time to boot. I do not have KVM acceleration available. Was able to get through step 5 successfully, but not able to start explorer. Any of "explorer", "explorer.exe", or "start explorer" should work, correct? Also tried navigating to C:/Windows so "explorer.exe" was correct path. Thanks for this effort - I am hoping this may be possible to run in cloud once the virtio drivers are loaded up.

@Vogtinator
Copy link
Author

Attempting this on Debian Bullseye. QEMU_EFI.fd did work for me, although it took a long time to boot.

Which boot? The initial "Getting Ready" one or a subsequent one?

I do not have KVM acceleration available. Was able to get through step 5 successfully, but not able to start explorer. Any of "explorer", "explorer.exe", or "start explorer" should work, correct? Also tried navigating to C:/Windows so "explorer.exe" was correct path. Thanks for this effort - I am hoping this may be possible to run in cloud once the virtio drivers are loaded up.

That should all work. Did you try this from a cmd/powershell or taskmanager?

@rpm-arch
Copy link

Attempting this on Debian Bullseye. QEMU_EFI.fd did work for me, although it took a long time to boot.

Which boot? The initial "Getting Ready" one or a subsequent one?

I do not have KVM acceleration available. Was able to get through step 5 successfully, but not able to start explorer. Any of "explorer", "explorer.exe", or "start explorer" should work, correct? Also tried navigating to C:/Windows so "explorer.exe" was correct path. Thanks for this effort - I am hoping this may be possible to run in cloud once the virtio drivers are loaded up.

That should all work. Did you try this from a cmd/powershell or taskmanager?

Tried again using an Intel host instead of ARM as I was not benefitting from KVM accel anyway, and was able to fully install. Thanks again for this guide.

@rpm-arch
Copy link

Any tips for getting virtual block devices recognized? I have viostor installed but with the following qemu cmd the block drive does not appear in Windows (cannot find it in diskmgmt or devmgmt - looked through unknown devices too):

-drive file=virtdisk.qcow2,format=qcow2,if=none,id=disk2 -device virtio-blk-device,drive=disk2

@excelsi
Copy link

excelsi commented Apr 25, 2024

I stuck here on an Azure ARM64 Ubunut VM trying to boot Server Build 26085
image

Tried already many different configs and also the Nightly EDK2 Build from:
https://gist.github.com/Vogtinator/293c4f90c5e92838f7e72610725905fd?permalink_comment_id=4830321#gistcomment-4830321

It always stucks at booting (regardless a fresh ISO from ARM Server / ARM Client)
I also tried to boot an Install from my local Qemu, where this Server ARM Build Installed successfully (on an Intel 8Gen Proc) but it also stucks on the Azure ARM VM after some seconds.

This is my config on Qemu in Azure:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<!-- 
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
  virsh edit W25-A64
or other application using the libvirt API.
 -->
<domain type="qemu">
<name>W25-A64</name>
<uuid>4b1d4e1c-baa5-48a7-85ca-a2501cd1aa95</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://libosinfo.org/unknown"/>
</libosinfo:libosinfo>
</metadata>
<memory unit="KiB">4194304</memory>
<currentMemory unit="KiB">4194304</currentMemory>
<vcpu placement="static">1</vcpu>
<os>
<type arch="aarch64" machine="virt-8.0">hvm</type>
<loader readonly="yes" type="pflash">/VM/QEMU_EFI.bin</loader>
<nvram>/VM/QEMU_VARS.bin</nvram>
<boot dev="hd"/>
</os>
<features>
<acpi/>
<gic version="2"/>
</features>
<cpu mode="custom" match="exact" check="none">
<model fallback="allow">neoverse-n1</model>
</cpu>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-aarch64</emulator>
<disk type="file" device="disk">
<driver name="qemu" type="qcow2"/>
<source file="/VM/W25-A64"/>
<target dev="vda" bus="virtio"/>
<address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
</disk>
<disk type="file" device="cdrom">
<driver name="qemu" type="raw"/>
<target dev="sda" bus="scsi"/>
<readonly/>
<address type="drive" controller="0" bus="0" target="0" unit="0"/>
</disk>
<controller type="usb" index="0" model="qemu-xhci" ports="15">
<address type="pci" domain="0x0000" bus="0x02" slot="0x00" function="0x0"/>
</controller>
<controller type="scsi" index="0" model="virtio-scsi">
<address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
</controller>
<controller type="pci" index="0" model="pcie-root"/>
<controller type="pci" index="1" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="1" port="0x8"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="2" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="2" port="0x9"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x1"/>
</controller>
<controller type="pci" index="3" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="3" port="0xa"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x2"/>
</controller>
<controller type="pci" index="4" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="4" port="0xb"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x3"/>
</controller>
<controller type="pci" index="5" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="5" port="0xc"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x4"/>
</controller>
<controller type="pci" index="6" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="6" port="0xd"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x5"/>
</controller>
<controller type="pci" index="7" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="7" port="0xe"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x6"/>
</controller>
<controller type="pci" index="8" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="8" port="0xf"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x7"/>
</controller>
<controller type="pci" index="9" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="9" port="0x10"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="10" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="10" port="0x11"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
</controller>
<controller type="pci" index="11" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="11" port="0x12"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
</controller>
<controller type="pci" index="12" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="12" port="0x13"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
</controller>
<controller type="pci" index="13" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="13" port="0x14"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
</controller>
<controller type="pci" index="14" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="14" port="0x15"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
</controller>
<controller type="virtio-serial" index="0">
<address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/>
</controller>
<interface type="network">
<mac address="52:54:00:7c:ff:54"/>
<source network="default"/>
<model type="virtio"/>
<address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>
<serial type="pty">
<target type="system-serial" port="0">
<model name="pl011"/>
</target>
</serial>
<console type="pty">
<target type="serial" port="0"/>
</console>
<channel type="unix">
<target type="virtio" name="org.qemu.guest_agent.0"/>
<address type="virtio-serial" controller="0" bus="0" port="1"/>
</channel>
<input type="tablet" bus="usb">
<address type="usb" bus="0" port="1"/>
</input>
<input type="keyboard" bus="usb">
<address type="usb" bus="0" port="2"/>
</input>
<tpm model="tpm-tis">
<backend type="emulator" version="2.0"/>
</tpm>
<graphics type="vnc" port="-1" autoport="yes" listen="0.0.0.0">
<listen type="address" address="0.0.0.0"/>
</graphics>
<audio id="1" type="none"/>
<video>
<model type="ramfb" heads="1" primary="yes"/>
</video>
</devices>
</domain>

This was my local Qemu 9 Config on my Windows PC:

"C:\Program Files\qemu\qemu-system-aarch64.exe" ^
-M virt,virtualization=true ^
-accel tcg,thread=multi ^
-cpu neoverse-n1 ^
-smp 2 ^
-m 8G ^
-bios "C:\Program Files\qemu\share\edk2-aarch64-code.fd" ^
-device ramfb ^
-device qemu-xhci ^
-device usb-kbd ^
-device usb-tablet ^
-netdev user,id=net0,hostfwd=tcp::5555-:3389 -device virtio-net,netdev=net0,disable-legacy=on ^
-drive file=E:\VM\Qemu\disk.qcow2,if=virtio  

The Azure VM has an Neoverse-N1 Proc and i tried "Max" and "Neoverse-N1" Model. KVM is not supported because nested virtualization is not enabled there.

I tried to get logs from the VM by;
https://libvirt.org/kbase/debuglogs.html

But i got:

azureuser@Ubuntu-A64:/VM$ sudo virt-admin -c virtqemud:///system daemon-log-outputs "3:journald 1:file:/VM/logs/libvirtd.log"
error: Failed to connect to the admin server
error: Failed to connect socket to '/run/libvirt/virtqemud-admin-sock': No such file or directory

Tried also to fix this but no luck.

Any help appreciated!

@Vogtinator
Copy link
Author

It always stucks at booting (regardless a fresh ISO from ARM Server / ARM Client)

Where does it get stuck?

KVM is not supported because nested virtualization is not enabled there.

You don't need nested virtualization. Just use -M virt like used in the examples.

@excelsi
Copy link

excelsi commented May 14, 2024

You can ignore my story i used an alternative way ;-)
Thanks!

@SaidTorres3
Copy link

SaidTorres3 commented Jun 3, 2024

A useful note for newbies that may not understand the conversation:

If you are on windows, there is no QEMU_EFI.fd and those that are available on the internet won't work. The solution is to use the C:\Program Files\qemu\share\edk2-aarch64-code.fd file as QEMU_EFI.fd; you can copy that file to your working folder and change the name to QEMU_EFI.fd.

This is the command I used (I allocated 16GB of ram and 8 virtual CPU threads to the VM):

qemu-system-aarch64 -M virt,virtualization=on -cpu max -m 16G -smp 8 ^
-device ramfb -bios edk2-aarch64-code.fd ^
-device qemu-xhci -device usb-kbd -device usb-tablet ^
-drive file=Windows11_InsiderPreview_Client_ARM64_en-us_22598.VHDX,format=vhdx,if=none,id=boot ^
-device usb-storage,drive=boot,serial=boot ^
-drive file=virtio-win.iso,media=cdrom,if=none,id=iso ^
-device usb-storage,drive=iso ^
-nic user,model=virtio-net-pci,mac=52:54:98:76:54:32 -vnc :1

I use TightVNC Viever in order to the screen, the remote host is located at localhost:5901 in my command (declared in -vnc :1).

@Vogtinator
Copy link
Author

If you are on windows, there is no QEMU_EFI.fd and those that are available on the internet won't work.

Why not?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment