I managed to finally get windows 11 working on my qemu and it seems reliable. Its quite an adventure. Here are the highlights that I learned
- Windows 11 is VERY picky about settings. I had to fiddle with them. Basically I needed to add a 'pass through' tpm chip which is 2.0 (alas you have to enable this on your mothernboard
- You need to load ALL the interesting libvirt drivers (mount the libvirt drivers cdrom as part of the initial install). I loaded video, disk, network. I found that doing this AFTER the install made windows very angry. When choosing the initial setup, just choose 'load from disk' and repeat for each drivers NONE of the howtos told me to do this.
- DO NOT use shared memory
- DO NOT use video other than qxl, which seems to be the nicest. No point in using virtio (although I did load the qxl and virtio video drivers for fun on step 1). Virtio video makes little sense since
- For best perfomance I dedicate an NVME drive to windows. I find out what PCI id its on by going to the /dev/disk/by-path
- It is CRITICAL to not use the wrong device as it will ERASE whats ever on it. YOU HAVE BEEN WARNED
- Once this is done, be sure to get the windows 11 dvd (download from ms) and have your key handy it makes building it much easier). Interestingly, I didn't have re-activate my failed windows 11 direct install it must save it on the disk or something)
- You need to add the right NVME drive to 'passthrough' devices for this to work YOU DONT WANT STORAGE.
- I haven't figured out how to get the pci IDS to be stable, so occasionally I have to re-add the right drive (I might figure this out sometime)
- SAVE YOURSELF A LOT OF TIME DO NOT USE THE QEMU-GUEST AGENT, JUST USE the spice-guest-agent!!!!!!!
Here is my vm config which may or may not be of use to you
<domain type="kvm">
<name>win11</name>
<uuid>3b60989c-b4b1-4c90-859b-beb2f07a2a53</uuid>
<title>Windows 11 base image on nvme drive</title>
<description>My home windows 11 vm. Scary that it works better in vm that it does in actual life!</description>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/11"/>
</libosinfo:libosinfo>
</metadata>
<memory unit="KiB">32854016</memory>
<currentMemory unit="KiB">32854016</currentMemory>
<vcpu placement="static">8</vcpu>
<os firmware="efi">
<type arch="x86_64" machine="pc-q35-8.0">hvm</type>
<firmware>
<feature enabled="no" name="enrolled-keys"/>
<feature enabled="yes" name="secure-boot"/>
</firmware>
<loader readonly="yes" secure="yes" type="pflash">/usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd</loader>
<nvram template="/usr/share/edk2/x64/OVMF_VARS.4m.fd">/var/lib/libvirt/qemu/nvram/win11_VARS.fd</nvram>
<boot dev="hd"/>
<bootmenu enable="no"/>
</os>
<features>
<acpi/>
<apic/>
<hyperv mode="custom">
<relaxed state="on"/>
<vapic state="on"/>
<spinlocks state="on" retries="8191"/>
</hyperv>
<vmport state="off"/>
<smm state="on"/>
</features>
<cpu mode="host-passthrough" check="none" migratable="on"/>
<clock offset="localtime">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
<timer name="hypervclock" present="yes"/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled="no"/>
<suspend-to-disk enabled="no"/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type="file" device="cdrom">
<driver name="qemu" type="raw"/>
<source file="/home/tmunn/iso/win11iso.iso"/>
<target dev="sda" bus="sata"/>
<readonly/>
<address type="drive" controller="0" bus="0" target="0" unit="0"/>
</disk>
<disk type="file" device="cdrom">
<driver name="qemu" type="raw"/>
<source file="/home/tmunn/Downloads/virtio-win-0.1.229.iso"/>
<target dev="sdb" bus="sata"/>
<readonly/>
<address type="drive" controller="0" bus="0" target="0" unit="1"/>
</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="pci" index="0" model="pcie-root"/>
<controller type="pci" index="1" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="1" port="0x10"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="2" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="2" port="0x11"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
</controller>
<controller type="pci" index="3" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="3" port="0x12"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
</controller>
<controller type="pci" index="4" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="4" port="0x13"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
</controller>
<controller type="pci" index="5" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="5" port="0x14"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
</controller>
<controller type="pci" index="6" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="6" port="0x15"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
</controller>
<controller type="pci" index="7" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="7" port="0x16"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x6"/>
</controller>
<controller type="pci" index="8" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="8" port="0x17"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x7"/>
</controller>
<controller type="pci" index="9" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="9" port="0x18"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="10" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="10" port="0x19"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x1"/>
</controller>
<controller type="pci" index="11" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="11" port="0x1a"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x2"/>
</controller>
<controller type="pci" index="12" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="12" port="0x1b"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x3"/>
</controller>
<controller type="pci" index="13" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="13" port="0x1c"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x4"/>
</controller>
<controller type="pci" index="14" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="14" port="0x1d"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x5"/>
</controller>
<controller type="scsi" index="0" model="virtio-scsi">
<address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
</controller>
<controller type="sata" index="0">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1f" function="0x2"/>
</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:58:8d:46"/>
<source network="br0-munn"/>
<model type="virtio"/>
<address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>
<serial type="pty">
<target type="isa-serial" port="0">
<model name="isa-serial"/>
</target>
</serial>
<console type="pty">
<target type="serial" port="0"/>
</console>
<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.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="mouse" bus="ps2"/>
<input type="keyboard" bus="ps2"/>
<tpm model="tpm-crb">
<backend type="passthrough">
<device path="/dev/tpm0"/>
</backend>
</tpm>
<graphics type="spice" autoport="yes">
<listen type="address"/>
<image compression="off"/>
</graphics>
<sound model="ich9">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1b" function="0x0"/>
</sound>
<audio id="1" type="spice"/>
<video>
<model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x0000" bus="0x76" slot="0x00" function="0x0"/>
</source>
<address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
</hostdev>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="2"/>
</redirdev>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="3"/>
</redirdev>
<watchdog model="itco" action="reset"/>
<memballoon model="virtio">
<address type="pci" domain="0x0000" bus="0x06" slot="0x00" function="0x0"/>
</memballoon>
</devices>
</domain>
Things to do on the guest
There are lots of things to do on the guest. I didnt' feel any benefit to using the qemu guest utilities, but I did find the 'spice' vdagent VERY useful. It lets me resize the windows successfully, and enabled both cut and paste bidirectionally. You have to run the vdagent on the host and guest.
I installed the spice vdagent I used the windows and native ones in manjaro, spice-vdagent, which doesn't seem to run by default FYI!). I installed them on the windows 11 box.
I also made sure that I chose 'virtio' for most of the interesting devices, such as network, etc. Doing the nice trick in loading them first makes the journey MUCH easier.
The updates take forever. DO NOT activate until your image is stable, since you may experience sadness like I did. I installed like 4 times before it finally worked out all the kinks in the process. NO ONE documented this well, hence my postings here.
Getting Files Sharing between host and guest
If you are using a reasonably modern arch install, you already have the necessary daemons installed. The windows guest also needs some changes to work better. This page describes how to install the necessary drivers. Basically it 'just works' if you use the gui, follow the directions, and install the necessary virtiofsd drivers. Be sure to use the mounted cdrom (the win virtio ones). I also missed the 'random number generator'. I didn't bother editing the xml, just used the virt-manager gui and added a 'filesystem' and chose virtfs
Getting video to do 4k
I just edited my configuration, looked for the qxl settings and increased the memory to 65535. Tjhis gives me FULL 4k in fullscreen. I use 2x for the increase in size.
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='65536' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
General observations
If one wanted to do 'no dual boot' systems, one could use looking glass for a very cool 'native' performance using 2 graphics cards. The linux one is amd, and the windows one is nvidia. Looking Glass seems to be a very promising project for those who don't want to dual boot but have a spare monitor for windows.
Once I got this working, I installed 'clonezilla' on my computer and saved the 'working' installation to a save file. This backed up the physical disk in ONLY 7GB! I can restore if windows decides to destroy itself (which my 'real' installation did). I might use p9fs to share files between, but with this being a PHYSICAL disk I can just mount and look at it.
Nice medium article with some additional details
Here is a nice link that shows some additional infos.
Enabling Transparent Hugepages (seems to help performance)
This link describes the process. Optional. I just decided to use TRANSPARENT huge pages which works without permanently losing memory. YMMV might be sad. Rather than make it permanent, I just made a script. You can permanently reserve them but I don't always want to do it that way.
#!/usr/bin/env bash
echo always > /sys/kernel/mm/transparent_hugepage/enabled