Windows 10 KVM with GPU Passthrough
Verify PCI Passthrough Support
Intel systems may need intel_iommu=on added as a kernel parameter. Then verify that IOMMU is enabled:
$ dmesg | grep -i -e DMAR -e IOMMU
Next, use the following shell script to check IOMMU groups. The IOMMU group of the GPU must not include any devices that need to remain connected to the host.
#!/bin/bash
shopt -s nullglob
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
    echo "IOMMU Group ${g##*/}:"
    for d in $g/devices/*; do
        echo -e "\t$(lspci -nns ${d##*/})"
    done;
done;
Prerequisites
Install the following Arch packages:
- libvirt
 - virt-manager
 - qemu-desktop
 - edk2-ovmf
 - iptables-nft
 - dnsmasq
 - looking-glass
 - samba
 
Download the following images:
Add the vfio modules to /etc/mkinitcpio.conf and rebuild initramfs:
MODULES=(... vfio_pci vfio vfio_iommu_type1 vfio_virqfd ...)
Then add a kernel parameter to bind the vfio-pci module to the GPU PCI IDs:
vfio-pci.ids=10de:1c03,10de:10f1
Create Virtual Machine with virt-manager
- Create a new VM with Windows 10 install ISO
 - 16 GB memory (or half available memory)
 - 6 CPUs (or half available CPUs)
 - Custom storage, VM Storage Pool, 500 GB qcow2 disk
 - Network: NAT
 
Customize configuration before install:
- Firmware: UEFI
 - Manually specify CPU topology: 
- sockets = number of physical CPU sockets
 - cores = number of physical CPU cores / 2
 - threads = number of physical CPU threads per core
 
 - Switch disk to virtio
 - Switch NIC to virtio
 - Disable NIC for Windows install
 - Remove console device
 - Add a second CDROM device with the VirtIO driver ISO
 - Set CDROM device 1 as primary boot device
 
Then go through the Windows install procedure. Load the VirtIO storage driver from the amd64/win10 folder on the second CDROM drive.
Configure Passthrough GPU with Looking Glass
- Verify that the display device is set to Spice
 - Remove the Tablet device
 - Add PCI Host devices for the dedicated GPU (video and audio may be separate devices)
 
Make the following edits to the virtual machine XML config, under <devices>:
- Add an IVSHMEM device for Looking Glass, with the correct amount of memory for the display setup:
 
<shmem name='looking-glass'>
  <model type='ivshmem-plain'/>
  <size unit='M'>32</size>
</shmem>
- Under 
<video>, set<model type='vga'/> - Add a 
<input type='mouse' bus='virtio'/>and<input type='keyboard' bus='virtio'/> - Disable the memballoon device: 
<memballoon model="none"/> 
Enable Host File Sharing
Add the QEMU schema to the root <domain> XML tag:
<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">
Then add the following QEMU options after </devices> to enable host file sharing via Samba:
<qemu:commandline>
  <qemu:arg value="-net"/>
  <qemu:arg value="user,smb=/path/to/shared/folder"/>
  <qemu:arg value="-net"/>
  <qemu:arg value="nic,model=virtio"/>
</qemu:commandline>
If the libvirt throws a permission denied error accessing the shared path, edit /etc/libvirt/qemu.conf to run QEMU as root. seccomp must also be disabled or QEMU will crash when trying to launch Samba:
user = "root"
group = "root"
seccomp_sandbox = 0
Configure Windows
Configure Windows using the built-in display in virt-manager:
- Install the VirtIO drivers and virtio-win-guest-tools from the second CDROM drive
 - Install the Looking Glass host application
 - Install the graphics driver for the passthrough GPU
 - In mouse settings, disable “Enhance pointer precision”
 - Download Custom Resolution Utility and add a custom resolution equal to the size of the Looking Glass client window.
 - Map a network drive to 
\\10.0.2.4\qemuto access the host shared folder