This guide provides a comprehensive walkthrough for setting up a high-performance Windows 11 virtual machine on a Fedora Workstation host, with a focus on GPU passthrough and system optimization. It is intended for users with a moderately technical background.
Before starting, ensure you have the required components and gather critical information about your hardware.
- A modern CPU with virtualization support (
Intel VT-xorAMD SVM/AMD-V). - A dedicated, non-boot GPU to pass through to the VM.
- A Windows 11 Installation ISO.
- The latest VirtIO driver ISO. Download from the Fedora Project.
Open a terminal and run:
lscpu | grep "Virtualization"The output must include VT-x for Intel or SVM for AMD.
This command lists all PCI devices. You will need this information throughout the guide.
lspci -nnkFind the "VGA compatible controller" entry for the GPU you intend to pass through. Note its address (e.g., 0c:00.0) and its vendor/device ID (e.g., [10de:2489]). Also, note any other devices that share the same base address (e.g., 0c:00.1 for Audio), as they must all be passed through together.
This revised section replaces the manual GRUB editing and driver blacklisting with the QuickPassthrough script for a more modern and less error-prone setup.
This step is a mandatory prerequisite and cannot be automated. Reboot your computer and enter the BIOS/UEFI setup to enable virtualization and IOMMU.
- Intel: Enable VT-d.
- AMD: Enable AMD-V, SVM, and IOMMU (or AMD-Vi).
Reboot your computer and enter your motherboard's BIOS/UEFI settings.
Find the option to enable IOMMU (it might be labeled as AMD-Vi, IOMMU, or SVM Mode) and set it to Enabled.
Locate the /etc/default/grub file on your Linux system:
sudo nano /etc/default/grub
amd_iommu=on is often redundant because the kernel already enables IOMMU on AMD systems by default when it's in the BIOS, but you can add it for clarity if you wish.
To GRUB_CMDLINE_LINUX add the following:
iommu=pt or amd_iommu=on iommu=pt
After saving the changes to /etc/default/grub, you must update the GRUB configuration.
Run the command:
grub2-mkconfig -o /boot/grub2/grub.cfg
sudo reboot
To check if iommu=pt is active, you can verify the kernel command line and examine the kernel's boot messages.
The iommu=pt parameter is added to the kernel command line during boot. You can check if it's present by examining the contents of /proc/cmdline.
cat /proc/cmdline
The output should include iommu=pt among other kernel parameters. For example:
initrd=\EFI\proxmox\5.4.73-1-pve\initrd.img-5.4.73-1-pve root=ZFS=rpool/ROOT/pve-1 boot=zfs intel_iommu=on iommu=pt
The kernel's boot messages (dmesg) will provide information about IOMMU initialization. You can filter these messages to look for IOMMU-related entries.
sudo dmesg | grep -e DMAR -e IOMMU -e AMD-Vi
If IOMMU is enabled and active, you should see lines indicating its status, such as DMAR: IOMMU enabled or similar messages related to IOMMU groups and device assignments. For example:
[ 0.464468] DMAR: IOMMU enabled
[ 0.794628] DMAR-IR: IOAPIC id 12 under DRHD base 0xc5ffc000 IOMMU 6
If both of these checks confirm the presence of iommu=pt in the kernel command line and the kernel messages indicate IOMMU enablement, then iommu=pt is active on your system.
This script automates checking your system, identifying passthrough devices, configuring kernel parameters, and setting up the vfio-pci driver.
You can use it by simply downloading the latest release and run it inside a terminal or by downloading and compiling it yourself with the commands below.
-
Option A - Download and Run:
# Download from https://github.com/HikariKnight/quickpassthrough/releases/, then: cd quickpassthrough_Linux_x86_64 chmod +x quickpassthrough sudo ./quickpassthrough
-
Option B - Build with current dependencies:
git clone https://github.com/HikariKnight/quickpassthrough.git cd quickpassthrough go mod download CGO_ENABLED=0 go build -ldflags="-X github.com/HikariKnight/quickpassthrough/internal/version.Version=$(git rev-parse --short HEAD)" -o quickpassthrough cmd/main.go
The script will modify system files and rebuild the initramfs. You must reboot your computer for these changes to take effect.
After rebooting, it is crucial to verify that the script was successful and your GPU is now bound to the vfio-pci driver.
Run lspci -nnk and find your GPU. The output must now show:
Kernel driver in use: vfio-pci
Once you've confirmed this, your host is fully prepared.
sudo dnf groupinstall --with-optional "Virtualization"sudo systemctl enable --now libvirtdThis allows you to manage VMs without sudo. You must log out and log back in for this to take effect.
sudo usermod -aG libvirt $(whoami)-
For Wi-Fi / Laptops (Recommended): Use the default NAT network. It works without any configuration. When creating the VM, simply select "Virtual network 'default': NAT".
-
For Wired Ethernet (Optional): To give your VM an IP on your home network, you can create a network bridge. Use
nm-connection-editor(GUI) ornmcli(command line) to create a bridge (br0) and add your physical Ethernet port as a slave to it.
Use the Virtual Machine Manager application for the initial setup.
- Click File -> New Virtual Machine.
- Select your Windows 11 ISO.
- Allocate CPU and Memory.
- Create a virtual disk (
qcow2format is recommended). - On the final screen, check the "Customize configuration before install" box before clicking Finish.
- In the customization view, make these critical changes:
- Overview: Set Firmware to UEFI x86_64 with Secure Boot (e.g.,
OVMF_CODE_4M.secboot.qcow2). - CPUs: Check the box for Copy host CPU configuration.
- SATA Disk: Change the Disk bus to VirtIO SCSI.
- Add Hardware:
- Add a Storage device (CD-ROM) and attach the
virtio-win.isofile. - Add PCI Host Device and select your GPU's VGA controller.
- Add another PCI Host Device for your GPU's Audio controller (and any other GPU functions).
- Add a Storage device (CD-ROM) and attach the
- Overview: Set Firmware to UEFI x86_64 with Secure Boot (e.g.,
- Click Begin Installation. Proceed with the Windows setup, loading the
viostordriver from the VirtIO CD when prompted.
After installing Windows, the NVIDIA drivers, and the VirtIO Guest Tools, the final step is to apply advanced tunings for maximum performance. Shut down the VM and edit its configuration.
sudo EDITOR=nano virsh edit win11-workstationHere are the key sections to add or modify.
This locks the VM's virtual CPUs to your physical CPU threads, eliminating stutter.
- Find your CPU layout:
lscpu --extended. Note your physical core and thread numbers. - Decide which threads to dedicate to the VM. It's best practice to leave the first few threads (e.g., 0-3) for the host.
- Add the
<cputune>block after the<vcpu>line in your XML.
Example for an 8-core/16-thread CPU (0-15) with a 12-thread VM:
<vcpu placement='static'>12</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='4'/>
<vcpupin vcpu='1' cpuset='5'/>
<vcpupin vcpu='2' cpuset='6'/>
<vcpupin vcpu='3' cpuset='7'/>
<vcpupin vcpu='4' cpuset='8'/>
<vcpupin vcpu='5' cpuset='9'/>
<vcpupin vcpu='6' cpuset='10'/>
<vcpupin vcpu='7' cpuset='11'/>
<vcpupin vcpu='8' cpuset='12'/>
<vcpupin vcpu='9' cpuset='13'/>
<vcpupin vcpu='10' cpuset='14'/>
<vcpupin vcpu='11' cpuset='15'/>
<emulatorpin cpuset='0-3'/>
</cputune>This improves memory performance.
- Enable huge pages on the host. For a 32GB VM, you would run:
# Formula: <VM_RAM_in_GB> * 512 # 32 * 512 = 16384 sudo sysctl -w vm.nr_hugepages=16384
- Modify the
<memoryBacking>section in your XML:<memoryBacking> <hugepages/> <nosharepages/> </memoryBacking>
Modify your XML to include these sections for better performance and driver compatibility.
<features>
<acpi/>
<apic/>
<kvm>
<hidden state='on'/>
</kvm>
<hyperv mode='custom'>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
</hyperv>
</features>
<cpu mode='host-passthrough' check='none'>
</cpu>
<devices>
<controller type='scsi' index='0' model='virtio-scsi'>
<driver queues='12'/>
</controller>
</devices>After making these changes, save the file. Start your VM to enjoy the full performance benefits.