====== Windows VM Tips ======
For using a windows VM via libvirt/KVM/qemu/virt-manager
FIXME
See also [[https://forums.guru3d.com/threads/windows-line-based-vs-message-signaled-based-interrupts-msi-tool.378044/|this guru3d thread]] for something to investigate about interrupts.
[[http://forum.proxmox.com/threads/5770-Windows-guest-high-context-switch-rate-when-idle|Here is a thread about excessive context switching]]. There is a solution [[https://docs.microsoft.com/en-GB/troubleshoot/windows-server/performance/programs-queryperformancecounter-function-perform-poorly|here]] (supposedly). Additionally it is proposed in this thread to remove the USB tablet device to reduce context switching (so I did that).
===== Installation =====
Only packages really needed (Ubuntu Server 22.04) are ''libvirt'', ''qemu-kvm'', ''libvirt-daemon-system''.
Add users who will use the VM to ''libvirt'' group.
==== Creating VM ====
If ''libvirtd.service'' is running (it should be) then just connect and create using ''virt-manager'' (either locally or remotely via ssh, e.g. ''virt-manager -c qemu+ssh:%%//%%[ip]/system'')
I also needed the [[https://github.com/virtio-win/virtio-win-pkg-scripts/blob/master/README.md|virtio Windows drivers]] to add as a disc when booting so that Windows could see the virtio hard drive. After install I ran the setup file inside which enabled some GPU stuff.
Install [[https://www.spice-space.org/download.html|SPICE guest tools]] to allow console resizing on Window resizing, and clipboard integration.
I found that virtio video driver still has some bugs - SPICE will stop resizing after rebooting after installing spice guest tools and will never work again. QXL video works perfectly.
=== Install location ===
By default libvirt/virt-manager/something puts the disk .qcow2s in ''/var/lib/libvirt/images'' (root access required to read).
===== CPU usage =====
Windows is a nightmare and sucks up craploads of CPU all the time because of course it does.
Useful commands to debug some of this:
* ''# perf kvm %%--%%host top -p `pidof qemu-system-x86_64`''
* Shows how often qemu is executing various functions, ''[k]'' for kernel space and ''[.]'' for user space.
* There is also one function used for making the switch to guest space and it accounts for all time spent there. On a 4.14 kernel with intel cpu that function is ''vmx_vcpu_run'' but it might differ.
* ''# perf stat -e 'kvm:*' -a %%--%% sleep 1''
* This should show the reason a VM is doing ''VM_EXIT''. Values should be roughly "less than 1000".
* ''# perf kvm %%--%%host stat live''
* This one should show what the VM is doing? Apparently most time % should be ''HLT'' otherwise it's not idle.
* High ''HLT'' time indicates the machine is waking up and going to sleep a lot (context switching?).
It may also be a good idea to use ''powercfg'' to find out why the OS is waking up lots, if it is.
===== Tweaks for performance =====
See https://libvirt.org/formatdomain.html and [[https://leduccc.medium.com/improving-the-performance-of-a-windows-10-guest-on-qemu-a5b3f54d9cf5|this guide]].
==== CPU Topology & Configuration ====
Match the host CPU topology with the VM (cores can be changed as desired). Enable ''host-passthrough'' to disable CPU emulation as much as possible.
...
...
Add one or more threads dedicated to I/O (libvirt recommends max 1 per core).
...
1
...
Set up the vCPUs for the guest by pinning them to the host. See ''virsh capabilities''. Note that Intel CPU sets are specified as e.g. (0,4); (1,5); (2,6); (3,7) for a 4-core CPU (i.e. the threading is split across the bottom and top halves of the cpuset range). For example this is how I set up the i7-3770 keeping core 0 for emulation/io/host.
...
6
...
==== Enlightenments ====
These tell Windows it's running in a VM.
In the XML for the machine, change the '''' and '''' sections to the following:
Features:
Clock:
Some sources say setting ''hpet'' as ''yes'' causes higher idle usage, so I opted for ''no''.
Additionally, some sources say to keep the following lines:
However, some recommend removing them, which I opted for.
For me these enlightenments reduced idle CPU by 4-5x (from 45%+ to ~10-12% while running Milestone XProtect in the background, with no cams set up).
===== Networking =====
Modify the netplan configuration to add a bridge, as I understand it the host will now connect via the bridge rather than directly through the interface:
''/etc/netplan/01-netcfg.yaml'':
network:
version: 2
renderer: networkd
ethernets:
enp2s0:
dhcp4: no
dhcp6: no
#addresses: [192.168.0.20/24]
#gateway4: 192.168.0.1
#nameservers:
# addresses: [192.168.0.10,1.1.1.1]
bridges:
br0:
dhcp4: no
dhcp6: yes
addresses: [192.168.0.20/24]
gateway4: 192.168.0.1
nameservers:
addresses: [192.168.0.10,1.1.1.1]
parameters:
stp: true
forward-delay: 4
interfaces:
- enp2s0
Apply with ''# netplan apply''
Configuration to disable netfilter for bridges:
''/etc/sysctl.d/99-netfilter-bridge.conf''
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
Also ensure ''br_netfilter'' is loaded at boot:
''/etc/modules-load.d/br_netfilter.conf''
br_netfilter
Apply with:\\
''# modprobe br_netfilter''\\
''# sysctl -p /etc/sysctl.d/99-netfilter-bridge.conf''
FIXME Removed networks and replaced with bridge to device directly.
Create a new network in virt-manager (right click connection, details, virtual networks) and replace the xml with:
bridged-network
Start it and set it to autostart. Now in guests just set the network to "Virtual network 'bridged-network'".
===== Updates =====
Apparently Windows Server doesn't auto-update by default (just downloads). Run ''sconfig'' to configure this behaviour.