Virtualization
Pass the CPU's built-in Intel graphics (iGPU) through to a VM on XCP-ng 8.2 / 8.3. The usual reason is hardware video transcoding (Intel Quick Sync) for Plex, Jellyfin, Frigate or similar in a Linux VM.
Before you start
- In the BIOS/UEFI, enable VT-d and make sure the iGPU is enabled. If the server also has a discrete GPU, turn on the option that keeps the iGPU active (often called iGPU Multi-Monitor), and set the primary display to the discrete card if you want to keep a host console.
- When the iGPU is hidden from the host, the host's local screen goes blank after boot. Make sure SSH or IPMI works before you start.
- A VM with a passed-through device can't be live-migrated.
- Use a recent Linux kernel in the VM (Ubuntu 24.04+, Debian 13, Fedora 40+). 12th-gen Intel and newer need newer
i915/xedrivers.
Find the iGPU
lspci | grep -i vga
00:02.0 VGA compatible controller: Intel Corporation AlderLake-S GT1 (rev 0c)
The Intel iGPU is almost always at 00:02.0. In full form that's 0000:00:02.0.
Hide the iGPU from the host
/opt/xensource/libexec/xen-cmdline --set-dom0 "xen-pciback.hide=(0000:00:02.0)"
reboot
After the reboot, confirm it's ready:
xl pci-assignable-list # should list 0000:00:02.0
Attach it to the VM
Shut the VM down, then:
xe vm-list name-label="jellyfin" params=uuid
xe vm-param-set uuid=<vm-uuid> other-config:pci=0/0000:00:02.0
Keep the VM's normal virtual display. You'll still use the Xen Orchestra console to manage it, and the iGPU works alongside it as a second GPU.
Start the VM.
Set up the VM (Linux)
- Check the iGPU is visible and the driver loaded:
You should see the Intel device withlspci -nnk | grep -A3 -i vga ls -l /dev/driKernel driver in use: i915(orxe), and/dev/dri/renderD128(sometimesrenderD129). - Install the video acceleration drivers and test them:
# Debian / Ubuntu sudo apt install intel-media-va-driver-non-free vainfo intel-gpu-tools # Fedora (intel-media-driver comes from RPM Fusion) sudo dnf install intel-media-driver libva-utils igt-gpu-tools vainfovainfoshould list H.264/HEVC profiles withVAEntrypointEncSlice. - Let your media server use the GPU:
- Native install: add the service user to the
renderandvideogroups:sudo usermod -aG render,video jellyfin - Docker: pass the device through, e.g. in compose:
devices: ["/dev/dri:/dev/dri"]
- Native install: add the service user to the
- Turn on hardware transcoding in the app (Jellyfin: Dashboard → Playback → Transcoding → Intel QuickSync (QSV); Plex: Settings → Transcoder → Use hardware acceleration).
- Play something that needs transcoding and watch the GPU work:
sudo intel_gpu_top
Removing passthrough
xe vm-param-remove uuid=<vm-uuid> param-name=other-config param-key=pci
/opt/xensource/libexec/xen-cmdline --delete-dom0 xen-pciback.hide
reboot
Troubleshooting
- No
/dev/driin the VM – the kernel is too old for the GPU. Checksudo dmesg | grep -i -e i915 -e xe. On 12th-gen and newer with older kernels, try the kernel optioni915.force_probe=<device-id>(the ID is inlspci -nn, e.g.4680), or upgrade the kernel. vainfoerrors with "va_openDriver() returns -1" – the wrong VA driver is installed. Modern Intel iGPUs need theiHDdriver (intel-media-driver), not the olderi965.- VM won't start – check
xl pci-assignable-liston the host and that VT-d is enabled (xl dmesg | grep -i vt-d). - The iGPU disappeared from
lspcion the host – the BIOS disabled it because a discrete GPU is installed. Turn on the iGPU / multi-monitor option in the BIOS.
See also: XCP-ng PCIe NIC Passthrough, Proxmox GPU Passthrough.
