Hot-switch discrete GPU between host and VFIO passthrough for KVM virtual machines — no reboot required.
Designed for hybrid GPU laptops (NVIDIA/AMD discrete + integrated GPU) to dynamically bind/unbind the discrete GPU to vfio-pci for VM passthrough.
- Auto-detection of discrete GPU (NVIDIA or AMD) and IOMMU groups
- Safe process management — automatically stops systemd services using the GPU; interactively lists user applications; NVIDIA users may be terminated after confirmation, while AMD clean detach refuses forced kills
- Compositor integration — auto-configures niri to ignore dGPU DRM devices and render on iGPU
- Hugepage management — separate subcommands for allocating/releasing hugepages with OOM safety checks
- Timeout protection — all sysfs operations have timeouts to prevent kernel deadlocks
- Service lifecycle — stopped services are restarted after passthrough enable/disable; services that fail to start on iGPU are reported and retried on restore
sudo make installparu -S gpu-hotswitch-vfio# Enable GPU passthrough (binds dGPU to vfio-pci)
sudo gpu-hotswitch-vfio on
# Enable GPU passthrough from a clean non-graphical target
# (recommended for fragile AMD hot-switch systems)
sudo gpu-hotswitch-vfio on-clean
# Allocate hugepages for VM (optional, run before starting VM)
sudo gpu-hotswitch-vfio hugepages-alloc
# Start your VM...
# After VM shutdown, release hugepages
sudo gpu-hotswitch-vfio hugepages-free
# Disable GPU passthrough (restores original driver)
sudo gpu-hotswitch-vfio off
# Disable from a clean non-graphical target
sudo gpu-hotswitch-vfio off-clean
# Check current status
sudo gpu-hotswitch-vfio statuson → hugepages-alloc → start VM → stop VM → hugepages-free → off
On AMD systems where amdgpu hot unbind/rebind is fragile, prefer:
on-clean → hugepages-alloc → start VM → stop VM → hugepages-free → off-clean
on-clean and off-clean run the switch in a transient systemd unit with IgnoreOnIsolate=yes, isolate to multi-user.target, perform the normal on/off operation, then restore graphical.target. This avoids compositor and desktop processes holding dGPU DRM/i2c nodes during amdgpu detach.
Hugepage allocation is optional. If your VM XML does not include <hugepages/> in <memoryBacking>, you can skip the hugepages steps entirely.
- Linux kernel with IOMMU and vfio-pci support (module or built-in)
iommu=ptkernel parameter (AMD IOMMU is auto-enabled; Intel needsintel_iommu=on)- Hybrid GPU system (integrated + discrete)
psmisc(providesfuser)
- Detects discrete GPU and all devices in its IOMMU group
- Configures compositor (niri) to ignore dGPU DRM devices and use iGPU for rendering
- Identifies processes using the GPU:
- Systemd services are stopped automatically (tracked for restart)
- User processes are listed interactively for confirmation
- Unloads GPU driver modules (nvidia/amdgpu)
- Unbinds remaining devices (e.g., HDMI audio) from their drivers
- Loads vfio-pci (handles both loadable module and built-in) and binds all IOMMU group devices
- Advises on hugepage allocation if VM is configured for it
- Restarts stopped services (they rebind to iGPU if possible; failures reported)
- Checks if passthrough is active (exits early if not)
- Stops services that were restarted on iGPU
- Unbinds devices from vfio-pci
- Reloads original GPU driver modules
- Reprobes devices
- Releases hugepages if any are allocated
- Restarts all tracked services (now with dGPU available)
Runs the corresponding on or off switch from multi-user.target and restores graphical.target afterward. The command is scheduled through systemd-run, so it survives the graphical session being stopped. Follow progress with:
journalctl -fu gpu-hotswitch-vfio-clean-on
journalctl -fu gpu-hotswitch-vfio-clean-offThe restarted display manager may appear on a different virtual terminal depending on the display manager and compositor.
- Checks if any VM in
/etc/libvirt/qemu/is configured with<hugepages/> - Verifies sufficient available memory (leaves 2GB headroom for host)
- Allocates 2MB hugepages on demand for the VM memory size
- Skips allocation if no VM uses hugepages
Releases all allocated hugepages (both 1GB and 2MB).
gpu-select provides per-app GPU assignment. Use it to prevent applications from accessing the NVIDIA GPU before hotswitch:
# Prevent apps from using NVIDIA (full isolation)
gpu-select set QQ igpu
gpu-select set valent igpu
gpu-select applyApps configured with gpu-select set <app> igpu will not hold /dev/nvidia* devices, making gpu-hotswitch-vfio on seamless without needing to kill them.
- Compositor config is persistent — after the first
on, niri'srender-drm-deviceandignore-drm-devicesettings remain in your config. This ensures niri always uses the iGPU for rendering, making future hotswitch operations safe. - NVIDIA support is more mature than AMD — NVIDIA path includes full retry logic, interactive process confirmation, and module unload verification. AMD path has basic process detection but less robust error handling.
- vfio-pci built-in — on kernels where vfio-pci is compiled in (not a loadable module), the tool detects this and proceeds without
modprobe.
- gpu-select — per-app GPU selection for hybrid GPU laptops
- gpu-passthrough-manager — GUI tool for static VFIO driver binding (requires reboot)
- Arch Wiki: PCI passthrough via OVMF
- Looking Glass — low-latency VM display for GPU passthrough
MIT