Denis Machard

My technical gists

Infrastructure background, developer mindset. I build things for pleasure.
    @github @mastodon @rss

    🎮 GPU Passthrough + Looking Glass Guide

    This guide explains how to set up a Windows VM with GPU passthrough and Looking Glass on Ubuntu 25.04.

    Prerequisites

    • CPU with VT-d/AMD-Vi enabled in BIOS:

      lscpu | grep "Virtualization"
      Virtualization: VT-x   # Intel
      Virtualization: AMD-V  # AMD
      
    • Two GPUs (one for Linux, one for the VM):

      lspci -nn | grep VGA
      00:02.0 VGA compatible controller [0300]: Intel Corporation Meteor Lake-P [Intel Arc Graphics] [8086:7d55] (rev 08)
      01:00.0 VGA compatible controller [0300]: NVIDIA Corporation AD106M [GeForce RTX 4070 Max-Q / Mobile] [10de:2820] (rev a1)
      

      Note the IDs in square brackets for the GPU you want to passthrough — in this case: 10de:2820.

    • Two audio controllers:

      lspci -nn | grep -i audio
      00:1f.3 Multimedia audio controller [0401]: Intel Corporation Meteor Lake-P HD Audio Controller [8086:7e28] (rev 20)
      01:00.1 Audio device [0403]: NVIDIA Corporation AD106M High Definition Audio Controller [10de:22bd] (rev a1)
      

      Again, note the IDs — in this case: 10de:22bd.

    • HDMI Dummy Plug (optional): helpful for Looking Glass to trick the guest GPU into enabling display output.

    Isolating your GPU

    Install QEMU/KVM

    QEMU is an open-source hypervisor that works with KVM to take advantage of hardware acceleration.

    sudo apt update
    sudo apt install qemu-kvm virt-manager bridge-utils linux-headers-$(uname -r) dkms
    sudo reboot now
    

    Enable libvirtd and add your user to the libvirt group:

    sudo systemctl enable libvirtd.service
    sudo systemctl start libvirtd.service
    sudo usermod -aG libvirt $USER
    

    Enable IOMMU in GRUB

    IOMMU (Input-Output Memory Management Unit) is required to isolate and assign hardware devices to VMs securely.

    Edit the GRUB configuration to enable IOMMU and specify the device IDs:

    sudo vim /etc/default/grub
    

    For Intel CPUs:

    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on iommu=pt vfio-pci.ids=10de:2820,10de:22bd"
    

    For AMD CPUs, replace intel_iommu=on with amd_iommu=on.

    Update GRUB:

    sudo grub-mkconfig -o /boot/grub/grub.cfg
    sudo reboot now
    

    Bind the GPU to VFIO

    VFIO allows direct and secure assignment of devices to VMs.

    Create the config:

    sudo vim /etc/modprobe.d/vfio.conf
    

    Add:

    options vfio-pci ids=10de:2820,10de:22bd
    

    Blacklist other drivers to prevent them from binding to the GPU:

    sudo tee /etc/modprobe.d/blacklist-nvidia.conf > /dev/null <<EOF
    blacklist nouveau
    blacklist nvidia
    blacklist nvidiafb
    blacklist rivafb
    blacklist nvidia_drm
    blacklist nvidia_uvm
    blacklist nvidia_modeset
    EOF
    

    Update the initramfs:

    sudo update-initramfs -c -k $(uname -r)
    

    Enable DMA GPU transfers (Looking Glass)

    IVSHMEM (Inter-VM Shared Memory) is a QEMU feature allowing memory segments to be shared between the host and guest. Looking Glass uses it to facilitate high-speed, low-latency frame sharing via DMA (Direct Memory Access).

    Download the Looking Glass source: https://looking-glass.io/artifact/B7/source

    Extract the archive and navigate to the module/ directory:

    cd looking-glass-B7/module
    

    Install the kernel module:

    dkms install .
    

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

    options kvmfr static_size_mb=128
    

    Create /etc/modules-load.d/kvmfr.conf:

    kvmfr
    

    Create a udev rule to allow your user access to /dev/kvmfr0 (replace user with your username):

    sudo tee /etc/udev/rules.d/99-kvmfr.rules > /dev/null <<EOF
    SUBSYSTEM=="kvmfr", OWNER="user", GROUP="kvm", MODE="0660"
    EOF
    

    Verify GPU Isolation

    Reboot and verify

    Run:

    lspci -k | grep -E "Audio|VGA|vfio-pci"
    

    Expected output:

    01:00.0 VGA compatible controller: NVIDIA Corporation AD106M [...]
        Kernel driver in use: vfio-pci
    01:00.1 Audio device: NVIDIA Corporation AD106M High Definition Audio [...]
        Kernel driver in use: vfio-pci
    

    vfio-pci should be listed as the kernel driver in use.

    You should now also have the character device /dev/kvmfr0

    ls -l /dev/kvmfr0
    

    Expected:

    crw------- 1 user kvm 242, 0 Jun 16 12:00 /dev/kvmfr0
    

    Create your dedicated gaming VM

    Download the Windows ISO

    Get a copy of Windows from:

    Download the virtio-win ISO from the official repository

    and move all ISO to /var/lib/libvirt/images/

    sudo chown libvirt-qemu:kvm /var/lib/libvirt/images/*.iso
    

    Launch the VM with virt-install

    sudo virt-install --name=Win10-gaming --vcpus=8 --memory=16384 --os-variant=win10 --features kvm_hidden=on --machine q35 --cdrom=/var/lib/libvirt/images/Win10_22H2_French_x64v1.iso --disk path=/var/lib/libvirt/images/win10.qcow2,size=100,bus=virtio,format=qcow2 --disk path=/var/lib/libvirt/images/virtio-win-0.1.271.iso,device=cdrom,bus=sata --graphics spice,listen=127.0.0.1 --video virtio --network network=default,model=virtio --hostdev pci_0000_01_00_0 --hostdev pci_0000_01_00_1 --wait -1
    

    Command details

    OptionPurposeExample Value
    --nameName of the VMWin10-gaming
    --vcpusNumber of virtual CPUs exposed to the guest8
    --memoryGuest RAM in MiB (16 384 MiB ≈ 16 GB)16384
    --os-variantOptimised defaults for the guest OSwin10
    --features kvm_hidden=onHides KVM from the guest to avoid DRM/anti‑cheat issueskvm_hidden=on
    --machineChipset / machine typeq35
    --cdromWindows installation ISOWin10_22H2_French_x64v1.iso
    --disk (1)System disk: path, size (GiB), virtio buswin10.qcow2,size=100
    --disk (2)VirtIO driver ISO attached as CD‑ROMvirtio-win-0.1.271.iso,device=cdrom
    --graphicsUses SPICE on localhost for displayspice,listen=127.0.0.1
    --videoVideo adapter model inside the VMvirtio
    --networkConnects to default virtual network, virtio modelnetwork=default,model=virtio
    --hostdev pci_0000_01_00_0GPU passthrough – PCIe address 0000:01:00.0 (NVIDIA RTX 4070)
    --hostdev pci_0000_01_00_1Audio controller passthrough – PCIe address 0000:01:00.1 (HD Audio)
    --wait -1Waits until installation completes before returning-1

    Install Windows

    Use SPICE to connect and install Windows:

    virt-viewer Win10-gaming
    

    During installation:

    • Browse to the VirtIO drive to load storage drivers when prompted.

    Install Drivers

    Once inside Windows:

    • Run virtio-win-guest-tools.exe from the VirtIO ISO.
    • Install GPU drivers: Nvidia, AMD, or Intel.

    Install LookingGlass

    Looking Glass is an open source application that allows the use of a KVM (Kernel-based Virtual Machine) configured for VGA PCI Pass-through without an attached physical monitor, keyboard or mouse.

    On your VM, install Windows binary from https://looking-glass.io/artifact/B7/host

    On your host, install the application client

    mkdir host/build
    cd host/build
    cmake ..
    make
    make install
    

    Tune the VM

    To optimize performance, edit the XML:

    <cpu mode='host-passthrough' check='none' migratable='on'>
        <topology sockets='1' dies='1' clusters='1' cores='4' threads='2'/>
        <maxphysaddr mode='passthrough' limit='40'/>
        <feature policy='disable' name='hypervisor'/>
    </cpu>
    

    Modifying the XML domain namespace to support qemu:commandline block

    Add the following qemu:commandline block under devices

      <qemu:commandline>
        <qemu:arg value='-device'/>
        <qemu:arg value='ivshmem-plain,id=shmem0,memdev=looking-glass,bus=pcie.0,addr=0x11'/>
        <qemu:arg value='-object'/>
        <qemu:arg value='memory-backend-file,id=looking-glass,mem-path=/dev/kvmfr0,size=128M,share=yes'/>
      </qemu:commandline>
    

    Then restart your VM.

    Final test

    Connect your HDMI Dummy Plug On your host, connect to your VM with ./looking-glass-client -F

    propulsed by hugo and hugo-theme-gists