looking-glass-setup-guide.md Comprehensive guide for setting up a Windows 11 virtual machine with GPU passthrough and Looking Glass on an Arch-based Linux system using a Wayland compositor. It explains the architecture behind Looking Glass, which achieves near-zero latency by sharing raw GPU framebuffer data between the VM and host through IVSHMEM shared memory instead of encoding video. The guide also includes troubleshooting for common issues, such as enabling IOMMU in BIOS, configuring persistent kernel parameters via `/etc/sdboot-manage.conf` on CachyOS, and avoiding the problematic `iommu=pt` kernel parameter. Looking Glass B7 + GPU Passthrough on CachyOS Hyprland/Wayland A complete guide to running a Windows 11 VM with GPU passthrough and Looking Glass on an Arch-based Linux system with a Wayland compositor. This setup allows you to run Windows-only software like Fusion 360 in a native-feeling window on your Linux desktop, with near-zero latency and no compression artifacts. This guide was written from a real setup session, including every issue encountered and how it was resolved. If you're running into problems, there's a good chance the answer is in here. --- System Specifications | Component | Detail | |-----------|--------| | Host OS | CachyOS Arch-based with Hyprland Wayland | | Host GPU | NVIDIA GeForce RTX 3080 Ti | | Guest GPU | NVIDIA GeForce GTX 1080 passed through to VM | | CPU | Intel i9-12900K 16 cores, 24 threads | | RAM | 64 GB total, 32 GB allocated to VM | | QEMU | 6.2+ JSON-style configuration | | libvirt | 7.9+ | | NVIDIA driver | 590.48.01 | | Looking Glass | B7 stable release | | Target resolution | 3440×1440 ultrawide | --- How Looking Glass Works Before diving into configuration, it helps to understand the architecture. Looking Glass works by sharing GPU framebuffer data between the Windows VM and your Linux host through shared memory, completely bypassing the normal display output path. The host application runs inside the Windows VM. It uses the Desktop Duplication API D12 on Windows 10+ to capture frames the GPU is rendering — the same way screen recording works. Instead of encoding those frames into a video stream like RDP or VNC, it writes raw, uncompressed frame data directly into a shared memory region. That shared memory region is the IVSHMEM device — a virtual PCI device that both the VM and the host can access simultaneously. It's a chunk of RAM that exists at the same physical memory addresses for both sides. The KVMFR kernel module manages this on the Linux side, and the IVSHMEM PCI driver handles it on the Windows side. The client application runs on your Linux desktop. It maps that same shared memory region and reads the frame data directly. Because there's no encoding, decoding, or network transport involved, the latency is extremely low — essentially the time it takes to copy pixels from GPU memory into shared memory, plus one DMA transfer. SPICE runs alongside as a separate channel purely for input — keyboard, mouse, clipboard sync, and audio. The actual video frames never touch SPICE. --- Part 0: VFIO GPU Passthrough Setup This section covers everything needed to get the guest GPU claimed by VFIO and passed through to the VM. If you already have a working passthrough setup, skip to Part 1. 0.1 Enable VT-d in BIOS This is the number one thing people miss. The kernel parameter intel iommu=on does nothing if the CPU feature isn't enabled in firmware. Reboot into BIOS/UEFI and look for one of these settings varies by motherboard manufacturer : - VT-d - Intel Virtualization Technology for Directed I/O - IOMMU Enable it, save, and exit. Also confirm VT-x CPU virtualization is enabled while you're there. 0.2 Kernel Parameters CachyOS uses systemd-boot. The correct way to set persistent kernel parameters is through /etc/sdboot-manage.conf , not by editing boot entries directly those get overwritten on kernel updates . bash sudo vim /etc/sdboot-manage.conf Find the LINUX OPTIONS line and set: bash LINUX OPTIONS="intel iommu=on rd.driver.pre=vfio-pci video=efifb:off" Then regenerate the boot entries: bash sudo sdboot-manage gen Reboot and verify: bash cat /proc/cmdline You should see your parameters in the output. Troubleshooting: iommu=pt Causes Empty IOMMU Groups Problem: ls /sys/kernel/iommu groups/ shows an empty directory despite VT-d being enabled and intel iommu=on in the kernel parameters. Cause: iommu=pt passthrough mode can prevent IOMMU groups from being populated. The dmesg output will show Default domain type: Passthrough — meaning devices aren't being isolated. Fix: Remove iommu=pt from your kernel parameters entirely, or change it to iommu=1 . Despite being commonly recommended in guides, passthrough mode defeats the purpose of VFIO isolation. The rd.driver.pre=vfio-pci parameter is what actually matters for early VFIO binding. Troubleshooting: Kernel Parameters Disappear After Updates Problem: After a system update, cat /proc/cmdline no longer shows your VFIO parameters. Cause: CachyOS regenerates systemd-boot entries during kernel updates, overwriting manual edits to /boot/loader/entries/ .conf . Fix: Use /etc/sdboot-manage.conf as described above — this is the CachyOS-specific mechanism for persistent kernel parameters. Never edit boot entries directly; always use LINUX OPTIONS in the config file and run sudo sdboot-manage gen to apply. 0.3 Identify Your GPUs bash lspci -nn | grep -E "VGA|Audio" | grep -i nvidia Example output for a dual-GPU system: 01:00.0 VGA compatible controller 0300 : NVIDIA Corporation GA102 GeForce RTX 3080 Ti 10de:2208 rev a1 01:00.1 Audio device 0403 : NVIDIA Corporation GA102 High Definition Audio Controller 10de:1aef rev a1 08:00.0 VGA compatible controller 0300 : NVIDIA Corporation GP104 GeForce GTX 1080 10de:1b80 rev a1 08:00.1 Audio device 0403 : NVIDIA Corporation GP104 High Definition Audio Controller 10de:10f0 rev a1 Note the device IDs in brackets. In this case, the GTX 1080 guest GPU has IDs 10de:1b80 GPU and 10de:10f0 audio . 0.4 Bind the Guest GPU to VFIO Create /etc/modprobe.d/vfio.conf : options vfio-pci ids=10de:1b80,10de:10f0 softdep snd hda intel pre: vfio-pci The softdep line ensures VFIO loads before the audio driver, which otherwise races to claim the GPU's audio device first. Add VFIO modules to the initramfs so they load early enough. Edit /etc/mkinitcpio.conf : MODULES= vfio pci vfio vfio iommu type1 Rebuild the initramfs: bash sudo mkinitcpio -P Reboot, then verify both GPU functions are bound to vfio-pci: bash lspci -nnk -s 08:00 Expected output: 08:00.0 VGA compatible controller 0300 : NVIDIA Corporation GP104 GeForce GTX 1080 10de:1b80 rev a1 Kernel driver in use: vfio-pci 08:00.1 Audio device 0403 : NVIDIA Corporation GP104 High Definition Audio Controller 10de:10f0 rev a1 Kernel driver in use: vfio-pci Troubleshooting: VFIO Not Binding No Driver Shown Problem: After configuring everything, lspci -nnk shows no driver in use for the GPU. Cause: The VFIO modules aren't in the initramfs, so they don't load early enough. Fix: Verify the modules are actually present: bash sudo lsinitcpio /boot/initramfs-linux-cachyos.img | grep vfio Note: CachyOS names its initramfs differently linux-cachyos or linux-cachyos-lts . If the modules aren't listed, re-check /etc/mkinitcpio.conf and rebuild with sudo mkinitcpio -P . 0.5 Create the VM and Add the GPU Create a Windows 11 VM in virt-manager with Q35 machine type and UEFI firmware OVMF . Then add the GPU: 1. Add Hardware → PCI Host Device → select 0000:08:00.0 GPU 2. Add Hardware → PCI Host Device → select 0000:08:00.1 Audio 0.6 CPU Configuration Critical The CPU mode configuration is surprisingly important for VFIO + shared memory compatibility. Using the wrong mode causes QEMU crashes with vfio container region add errors when shared memory devices are present. Working configuration: xml