Setting Up Single GPU Passthrough with Libvirt and Virt-Manager on Arch Linux for a Windows 11 Guest
This article will cover the process of setting up single GPU passthrough with Libvirt and Virt-Manager on Arch Linux for a Windows 11 guest. GPU passthrough allows a virtual machine to have direct access to a physical GPU, enabling hardware-accelerated graphics and improving performance for graphics-intensive workloads. We will go through the key concepts, steps, and configurations needed to successfully set up GPU passthrough.
Prerequisites
Before starting, ensure that your system meets the following requirements:
- Arch Linux installed and up-to-date
- A dedicated NVIDIA or AMD GPU with sufficient capabilities for running Windows 11
- An Intel or AMD CPU with VT-d or AMD-Vi support
- IOMMU enabled in the BIOS
Step 1: Installing Libvirt and Virt-Manager
Begin by installing Libvirt and Virt-Manager on your Arch Linux system:
# sudo pacman -S libvirt virt-manager qemu vde2 dnsmasq bridge-utils openbsd-netcat
After installation, start and enable the Libvirt daemon:
# sudo systemctl start libvirtd
# sudo systemctl enable libvirtd
Step 2: Adding the Host GPU to the IOMMU Group
Identify the PCI address of your dedicated GPU using the following command:
# lspci -nn | grep -E 'VGA|3D'
Take note of the vendor and device ID, typically in the format "xxxx:xxxx". Next, edit the bootloader configuration:
# sudo nano /etc/default/grub
Locate the GRUB\_CMDLINE\_LINUX line and append the following options:
GRUB_CMDLINE_LINUX="intel_iommu=on video=efifb:off"
For AMD systems, use "amd_iommu=on" instead of "intel_iommu=on". Save the file and update the GRUB bootloader:
# sudo grub-mkconfig -o /boot/grub/grub.cfg
Reboot the system.
Step 3: Creating an XML Configuration for the VM
Create an XML file for the virtual machine specifying the GPU device to be passed through:
# sudo nano /etc/libvirt/qemu/windows11.xml
Copy the following XML template into the file:
<domain type='kvm' id='<your-domain-id>'>
<name>windows11</name>
<memory unit='KiB'>16777216</memory>
<currentMemory unit='KiB'>16777216</currentMemory>
<vcpu placement='static'>8</vcpu>
<os>
<type arch='x86_64' machine='pc-q35-5.2'/>
<boot menu='menu' order='cdn'/>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic>
<pae/>
</features>
<cpu>
<topology sockets='1' cores='4' threads='2'/>
<model fallback='forbid'>Haswell</model>
<feature policy='require' name='vmx'/>
</cpu>
<clock offset='localtime'>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
<timer name='rtcfreq' present='no'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>
<name>qemu</name>
<features>
<acpi>
<apic>
</features>
</emulator>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/path/to/windows11.iso'/>
<target dev='hdc' bus='ide'/>
<readonly boot='on'/>
<address type='drive' controller='ide' bus='1' target='0' unit='0'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/path/to/windows11-vm.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>
<interface type='bridge'>
<mac address='<your-mac-address>'/>
<source bridge='virbr0'/>
<model type='virtio'/>
</interface>
<serial type='stdio'>
<target type='serial' port='0'/>
</serial>
<console type='serial'>
<target type='serial' port='0'/<target>
<handler>
<params Lnx>
<param name='vga'/>
<param name='efifb'/>
<param name='fbdev'/>
<param name='keymap'/>
<param name='font'/>
<param name='tcp'/>
<param name='telnet'/>
</params>
</handler>
</console>
<video>
<model type='qxl' vram='65536' head='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</video>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x0<your-bus-number>' slot='0x0<your-slot-number>' function='0'/>
</source>
<rom file='/usr/share/kvm/ <your-gpu-vendor>.rom'/>
<boot order='boot2'/>
<address type='pci' slot='0x05' function='0'/>
</hostdev>
</devices>>
</domain>
Replace the placeholders with the appropriate values. After editing the XML, import it into Libvirt:
# virsh define /etc/libvirt/qemu/windows11.xml
Step 4: Booting the VM
Start the virtual machine, ensuring that the OVMF boot screen appears, signifying successful GPU passthrough:
# virsh start windows11
- Installed Libvirt and Virt-Manager on Arch Linux
- Enabled IOMMU in the BIOS and passed the host GPU to the VM through Libvirt XML configuration
- Successfully booted a Windows 11 guest with single GPU passthrough