Skip to content

Instantly share code, notes, and snippets.

@safwyls
Last active March 15, 2026 06:29
Show Gist options
  • Select an option

  • Save safwyls/96b6cf4b49e04af2668b7a77502e5ff2 to your computer and use it in GitHub Desktop.

Select an option

Save safwyls/96b6cf4b49e04af2668b7a77502e5ff2 to your computer and use it in GitHub Desktop.

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

sudo vim /etc/sdboot-manage.conf

Find the LINUX_OPTIONS line and set:

LINUX_OPTIONS="intel_iommu=on rd.driver.pre=vfio-pci video=efifb:off"

Then regenerate the boot entries:

sudo sdboot-manage gen

Reboot and verify:

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

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:

sudo mkinitcpio -P

Reboot, then verify both GPU functions are bound to vfio-pci:

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:

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:

<cpu mode='host-model' check='none'>
  <topology sockets='1' dies='1' cores='18' threads='1'/>
</cpu>

What doesn't work:

  • host-passthrough with migratable='on' — causes memory mapping conflicts between the GPU passthrough and IVSHMEM device, crashing QEMU
  • host-passthrough without migratable — may also conflict depending on QEMU version

The host-model mode has libvirt select a compatible CPU model rather than exposing exact CPU features, which avoids the memory region overlap. The migratable attribute must be removed entirely (not set to 'off' — just absent).

Without the topology block, Windows will see an incorrect CPU layout (e.g., 2 sockets instead of 18 cores). The topology line tells Windows exactly how the vCPUs are organized. Note that vCPU allocation is shared, not reserved — your host can still use all 24 cores; the VM just won't use more than 18 at once.

0.7 Bridge Networking

For the VM to be accessible on your LAN (required for SPICE, and useful for general connectivity), set up a network bridge:

sudo nmcli connection add type bridge ifname br0 con-name br0
sudo nmcli connection add type ethernet ifname enp6s0 master br0
sudo nmcli connection up br0

Replace enp6s0 with your actual ethernet interface (check with ip link).

Then configure the VM to use the bridge in its XML:

<interface type='bridge'>
  <mac address='52:54:00:xx:xx:xx'/>
  <source bridge='br0'/>
  <model type='e1000e'/>
</interface>

The VM will get its own IP from your router's DHCP server.

0.8 Install NVIDIA Drivers in the Guest

Once the VM boots with the passed-through GPU, install the NVIDIA drivers manually from nvidia.com. GeForce Experience often fails in VMs due to hardware detection checks, so download the standalone driver instead:

  1. Go to https://www.nvidia.com/Download/index.aspx
  2. Select GeForce → 10 Series → GTX 1080 → Windows 11
  3. Download and install the driver directly

Why Not Moonlight/Sunshine?

Before arriving at Looking Glass, Moonlight/Sunshine was tested as an alternative. The results for this particular use case (CAD work at 3440×1440) were not satisfactory:

  • At 165 FPS (native refresh rate), massive compression artifacts appeared — NVENC on the GTX 1080 can't keep up at that frame rate
  • At 60 FPS with 150 Mbps bitrate, image quality was acceptable but mouse input felt sluggish — unacceptable for precision CAD work in Fusion 360
  • HEVC encoding wasn't available (Moonlight client-side decoding issues on CachyOS)
  • Even with optimized settings, the encode/decode pipeline adds perceptible latency compared to raw framebuffer sharing

For gaming or media consumption, Moonlight/Sunshine is excellent. For daily-driver CAD/productivity work where you need pixel-perfect rendering and zero input lag, Looking Glass is the correct tool.

Approaches That Were Tried and Abandoned

GL.iNet Comet Pro (IP KVM): Hardware-based HDMI capture from the GTX 1080. Works for remote access and BIOS-level troubleshooting, but adds its own compression and latency. Useful as a fallback but not a primary display solution for productivity work.

Intel iGPU passthrough (GVT-d): The i9-12900K has a UHD 770 iGPU, but 12th gen Alder Lake does not support GVT-g (mediated/shared GPU). GVT-d requires full passthrough, meaning the host loses the iGPU entirely (must blacklist i915). Combined with known Code 43 errors, missing VBIOS issues, and special OpROM requirements, this was not worth pursuing when the GTX 1080 is vastly more capable for Fusion 360.



Part 1: KVMFR Kernel Module

The KVMFR module creates a character device (/dev/kvmfr0) that provides a high-performance shared memory interface between host and guest.

1.1 Build and Install via DKMS

Clone the Looking Glass B7 stable release (not git master — the client and host versions must match):

cd ~/source
git clone --branch B7 --single-branch https://github.com/gnif/LookingGlass.git looking-glass-B7
cd looking-glass-B7/module

Install via DKMS so the module rebuilds automatically on kernel updates:

sudo dkms install "."

1.2 Calculate Shared Memory Size

The formula from the Looking Glass docs:

width × height × 4 × 2 = frame bytes
round up to nearest power of 2 in MB

For 3440×1440:

3440 × 1440 × 4 × 2 = 39,628,800 bytes ≈ 37.8 MB
Round up to nearest power of 2 → 64 MB

However, 64 MB can be tight for ultrawide resolutions. We used 128 MB to provide headroom and avoid any frame corruption issues.

1.3 Configure the Module

Create /etc/modprobe.d/kvmfr.conf:

options kvmfr static_size_mb=128

Create /etc/modules-load.d/kvmfr.conf to auto-load at boot:

kvmfr

1.4 Set Up udev Rules

Create /etc/udev/rules.d/99-kvmfr.rules:

SUBSYSTEM=="kvmfr", OWNER="your_username", GROUP="kvm", MODE="0660"

Replace your_username with your actual Linux username.

Reload and trigger:

sudo udevadm control --reload-rules
sudo udevadm trigger

1.5 Load the Module

sudo modprobe kvmfr

Verify it's working:

ls -l /dev/kvmfr0

You should see a character device (permissions start with c) owned by your user:

crw-rw---- 1 your_username kvm 508, 0 Feb  8 15:32 /dev/kvmfr0

Troubleshooting: /dev/kvmfr0 Permissions

Problem: After loading the module, /dev/kvmfr0 is owned by root with mode 600.

Cause: The udev rule didn't trigger, or the module was reloaded after creating the device (which creates a fresh device node without re-triggering udev).

Fix: Apply permissions manually for the current session, then fix the udev rule for persistence:

sudo chown your_username:kvm /dev/kvmfr0
sudo chmod 660 /dev/kvmfr0

Troubleshooting: /dev/kvmfr0 is a Regular File

Problem: ls -l /dev/kvmfr0 shows a regular file (permissions start with -) instead of a character device (c).

Cause: The VM was started before the KVMFR module was loaded. QEMU creates a regular file as a fallback.

Fix: Stop the VM, remove the file, load the module, then start the VM:

virsh destroy win11
sudo rm /dev/kvmfr0
sudo modprobe kvmfr
virsh start win11

Part 2: libvirt / QEMU Configuration

2.1 Add QEMU Namespace to Domain XML

The <domain> tag needs the QEMU namespace for the commandline passthrough:

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

This must be done in the same virsh edit session as adding the QEMU commandline block.

2.2 Add KVMFR Shared Memory Device

Add this block at the bottom of your VM XML, just before </domain>:

<qemu:commandline>
  <qemu:arg value="-device"/>
  <qemu:arg value="{'driver':'ivshmem-plain','id':'shmem0','memdev':'looking-glass'}"/>
  <qemu:arg value="-object"/>
  <qemu:arg value="{'qom-type':'memory-backend-file','id':'looking-glass','mem-path':'/dev/kvmfr0','size':134217728,'share':true}"/>
</qemu:commandline>

The size is in bytes: 128 MB × 1024 × 1024 = 134,217,728.

Important: This is JSON-style syntax required for QEMU 6.2+ / libvirt 7.9+. Using the older comma-separated syntax on newer versions will cause a "PCI slot not available" error.

2.3 Remove Conflicting shmem Block

If you previously tried the standard shared memory approach, remove any <shmem> block like this:

<!-- REMOVE THIS if present -->
<shmem name='looking-glass'>
  <model type='ivshmem-plain'/>
  <size unit='M'>128</size>
</shmem>

The QEMU commandline block replaces it. Having both will cause conflicts.

2.4 Disable Memory Ballooning

Change the memballoon device from virtio to none:

<memballoon model="none"/>

The virtio balloon driver causes performance issues with VFIO passthrough.

2.5 Remove USB Tablet Device

Looking Glass is incompatible with absolute pointing devices. Remove the USB tablet:

<!-- REMOVE THIS -->
<input type="tablet" bus="usb">
  <address type="usb" bus="0" port="1"/>
</input>

Without removing this, you'll get mouse input issues and the Looking Glass FAQ explicitly calls this out.

2.6 Configure SPICE for Input

SPICE provides keyboard, mouse, and clipboard sync to the VM (video is handled by Looking Glass, not SPICE):

<graphics type="spice" autoport="yes">
  <listen type="address" address="127.0.0.1"/>
</graphics>

Install SPICE guest tools inside Windows for clipboard sync and proper integration.

2.7 Configure cgroups for /dev/kvmfr0

Edit /etc/libvirt/qemu.conf and find the cgroup_device_acl block. Uncomment it and add /dev/kvmfr0:

cgroup_device_acl = [
    "/dev/null", "/dev/full", "/dev/zero",
    "/dev/random", "/dev/urandom",
    "/dev/ptmx", "/dev/kvm",
    "/dev/kvmfr0"
]

Then restart libvirtd:

sudo systemctl restart libvirtd

Troubleshooting: "Permission denied" on /dev/kvmfr0

Problem: VM fails to start with can't open backing store /dev/kvmfr0 for guest RAM: Permission denied.

Cause: cgroups policy is blocking QEMU from accessing the device, even if file permissions are correct.

Fix: Ensure /dev/kvmfr0 is in the cgroup_device_acl list in /etc/libvirt/qemu.conf and restart libvirtd.


Part 3: Building the Looking Glass Client

Critical: The client and host must be built from the same release. If you install the B7 host in Windows, you must build the B7 client on Linux. Mixing versions (e.g., a B7 host with a git master client, or vice versa) will cause connection failures or protocol mismatches. Always download the same tagged release for both sides.

3.1 Install Dependencies (Arch/CachyOS)

sudo pacman -S cmake gcc libgl libegl fontconfig spice-protocol make nettle \
  pkgconf binutils libxi libxinerama libxss libxcursor libxpresent \
  libxkbcommon wayland-protocols ttf-dejavu libsamplerate

3.2 Build the Client

Build from the B7 stable release source (must match the Windows host version):

cd ~/source/looking-glass-B7/client
mkdir build
cd build
cmake ..
make -j$(nproc)

Verify X11 support is enabled (required for XWayland rendering with OpenGL):

grep ENABLE_X11 CMakeCache.txt
# Should show: ENABLE_X11:BOOL=ON

3.3 Install

sudo cp looking-glass-client /usr/local/bin/

Part 4: Windows Guest Configuration

4.1 Install Looking Glass Host

Download the B7 host installer from the Looking Glass releases page and install it in the Windows VM.

The host runs as a Windows service under the SYSTEM account. This is important because it needs to capture the desktop even at the login screen.

Host application location: C:\Program Files\Looking Glass (host)\looking-glass-host.exe Log file: %ProgramData%\Looking Glass (host)\looking-glass-host.txt

4.2 Install IddSampleDriver (Virtual Display)

If you don't have a physical monitor connected to the passed-through GPU, you need a virtual display driver. IddSampleDriver creates a virtual monitor that the GPU renders to, which Looking Glass then captures.

Download IddSampleDriver from its GitHub repository and install it in the Windows VM. Configure it with your desired resolution (e.g., 3440×1440).

Critical: Do not set the IddSampleDriver display as the primary display if you're still using SPICE or RDP for initial setup. If the GPU can't output to the virtual display before Looking Glass is connected, you may lose access to the VM entirely. Set it as a secondary display first, then make it primary only after confirming Looking Glass captures it.

Troubleshooting: Locked Out After IddSampleDriver Misconfiguration

Problem: Set IddSampleDriver as primary display, can't see the login screen via SPICE or any other method.

Fix: Mount the VM's disk from the Linux host and remove the driver:

# Ensure VM is stopped
virsh destroy win11

# Mount the QCOW2 disk
sudo modprobe nbd max_part=8
sudo qemu-nbd --connect=/dev/nbd0 /path/to/win11.qcow2
sudo fdisk -l /dev/nbd0  # Identify the Windows NTFS partition (usually p3)
sudo mount -t ntfs-3g -o rw,remove_hiberfile /dev/nbd0p3 /mnt

The remove_hiberfile option is needed because Windows Fast Startup leaves the filesystem dirty. Navigate to the IddSampleDriver installation directory and remove or rename the driver files:

# Remove or rename the driver directory
sudo mv /mnt/path/to/IddSampleDriver /mnt/path/to/IddSampleDriver.bak

Unmount and disconnect:

sudo umount /mnt
sudo qemu-nbd --disconnect /dev/nbd0

Start the VM again, and it should fall back to the SPICE display.


Part 5: Running Looking Glass

5.1 Basic Launch

looking-glass-client

The client will automatically find /dev/kvmfr0 and connect to the shared memory region. SPICE integration provides keyboard/mouse input.

5.2 The Critical Fix: OpenGL Renderer on NVIDIA + Wayland

This is the most important section in this guide. If you're running NVIDIA + Hyprland (or any Wayland compositor), you will almost certainly encounter flickering black rectangles in the Looking Glass output.

Problem: Occasional flickering black boxes/rectangles appearing in the Looking Glass window.

Root cause: The default EGL renderer has a compositing incompatibility with the NVIDIA driver under Wayland. This is not a Looking Glass bug, not a D12 capture issue, and not an IddSampleDriver problem.

Solution: Force the OpenGL renderer instead of EGL.

Create ~/.looking-glass-client.ini:

[app]
renderer=opengl

That's it. The OpenGL renderer completely eliminates the flickering without any performance penalty.

What doesn't fix it (so you don't waste time):

  • Disabling D12 damage tracking (trackDamage=false in the Windows host config)
  • Switching to DXGI capture
  • Downgrading egl-wayland
  • Disabling explicit sync (__NV_DISABLE_EXPLICIT_SYNC=1)
  • Enabling double buffering (egl:doubleBuffer=true)
  • Disabling DMA (app:allowDMA=no)
  • Unsetting WAYLAND_DISPLAY (this forces XWayland, which works but is unnecessary)

The OpenGL renderer is the clean, correct fix.

5.3 VM Autostart

To have the Windows VM start automatically at boot:

virsh autostart win11

To disable later:

virsh autostart --disable win11

Complete Configuration Reference

VM XML Key Sections

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  <name>win11</name>
  <memory unit='GiB'>32</memory>
  <vcpu placement='static'>18</vcpu>

  <!-- CPU mode: host-model WITHOUT migratable (critical for VFIO + shmem) -->
  <cpu mode='host-model' check='none'>
    <topology sockets='1' dies='1' cores='18' threads='1'/>
  </cpu>
	
  <!-- GPU Passthrough -->
  <hostdev mode='subsystem' type='pci' managed='yes'>
    <source>
      <address domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>
    </source>
  </hostdev>
  <hostdev mode='subsystem' type='pci' managed='yes'>
    <source>
      <address domain='0x0000' bus='0x08' slot='0x00' function='0x1'/>
    </source>
  </hostdev>

  <!-- SPICE for input only -->
  <graphics type="spice" autoport="yes">
    <listen type="address" address="127.0.0.1"/>
  </graphics>

  <!-- No memory ballooning -->
  <memballoon model="none"/>

  <!-- NO USB tablet device -->

  <!-- KVMFR shared memory -->
  <qemu:commandline>
    <qemu:arg value="-device"/>
    <qemu:arg value="{'driver':'ivshmem-plain','id':'shmem0','memdev':'looking-glass'}"/>
    <qemu:arg value="-object"/>
    <qemu:arg value="{'qom-type':'memory-backend-file','id':'looking-glass','mem-path':'/dev/kvmfr0','size':134217728,'share':true}"/>
  </qemu:commandline>
</domain>

Host Configuration Files

File Contents
/etc/modprobe.d/kvmfr.conf options kvmfr static_size_mb=128
/etc/modules-load.d/kvmfr.conf kvmfr
/etc/udev/rules.d/99-kvmfr.rules SUBSYSTEM=="kvmfr", OWNER="your_username", GROUP="kvm", MODE="0660"
/etc/libvirt/qemu.conf Add /dev/kvmfr0 to cgroup_device_acl
~/.looking-glass-client.ini [app] / renderer=opengl

Windows Guest Configuration

Component Location
Looking Glass host C:\Program Files\Looking Glass (host)\looking-glass-host.exe
Host log %ProgramData%\Looking Glass (host)\looking-glass-host.txt
Capture method D12 (default, fastest for Windows 10+)
IddSampleDriver Virtual display at 3440×1440
SPICE guest tools Installed for clipboard sync

Troubleshooting Quick Reference

Symptom Cause Fix
VM won't start: "Permission denied" on /dev/kvmfr0 cgroups blocking access Add /dev/kvmfr0 to cgroup_device_acl in qemu.conf, restart libvirtd
/dev/kvmfr0 owned by root udev rule not applied sudo chown user:kvm /dev/kvmfr0 && sudo chmod 660 /dev/kvmfr0; fix udev rule
/dev/kvmfr0 is regular file, not char device VM started before module loaded Stop VM, rm /dev/kvmfr0, modprobe kvmfr, start VM
VM won't start: "PCI slot not available" Using legacy QEMU syntax on new QEMU Use JSON-style qemu:commandline syntax
Flickering black boxes in LG output EGL renderer + NVIDIA + Wayland Set renderer=opengl in ~/.looking-glass-client.ini
No display in Looking Glass Host not running / wrong display captured Check host log; ensure IddSampleDriver is configured
Locked out of VM after display change IddSampleDriver set as primary with no way to view it Mount QCOW2 via qemu-nbd, remove driver files
Mouse issues in Looking Glass USB tablet device present Remove <input type="tablet"> from VM XML
No clipboard sync SPICE tools not installed Install SPICE guest tools in Windows

Useful Commands

# Check KVMFR module status
lsmod | grep kvmfr
dmesg | grep kvmfr

# Check device permissions
ls -la /dev/kvmfr0

# VM management
virsh start win11
virsh destroy win11     # force stop
virsh shutdown win11    # graceful shutdown
virsh autostart win11

# Mount VM disk for emergency access
sudo modprobe nbd max_part=8
sudo qemu-nbd --connect=/dev/nbd0 /path/to/win11.qcow2
sudo mount -t ntfs-3g -o rw,remove_hiberfile /dev/nbd0p3 /mnt
# ... do your work ...
sudo umount /mnt
sudo qemu-nbd --disconnect /dev/nbd0

# Launch Looking Glass with verbose output
looking-glass-client -d
@pdsmike
Copy link

pdsmike commented Feb 11, 2026

Fantastic guide! I've spent hours finding information on how to set this up. I'll try this on my Ubuntu 24.04.3 LTS and will give you my feedback.

@brenthl88
Copy link

brenthl88 commented Feb 18, 2026

looking-glass-client
looking-glass-client: error while loading shared libraries: libsframe.so.2: cannot open shared object file: No such file or directory

Currently trying to check why my looking glass can't find the library
Windows at B7 but Endeavour wants me to update to 2:B7-6 when I tried rebuilding looking glass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment