====== 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.