Skip to content

Instantly share code, notes, and snippets.

@iamchriswick
Last active November 9, 2025 22:38
Show Gist options
  • Select an option

  • Save iamchriswick/55a6a14a054010b10a9330135f7858a8 to your computer and use it in GitHub Desktop.

Select an option

Save iamchriswick/55a6a14a054010b10a9330135f7858a8 to your computer and use it in GitHub Desktop.

High-Performance Windows 11 KVM Guide for Fedora

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.


Part 0: System Information & Prerequisites

Before starting, ensure you have the required components and gather critical information about your hardware.

Prerequisites:

  • A modern CPU with virtualization support (Intel VT-x or AMD 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.

1. Check CPU Virtualization Support

Open a terminal and run:

lscpu | grep "Virtualization"

The output must include VT-x for Intel or SVM for AMD.


2. Identify Hardware for Passthrough

This command lists all PCI devices. You will need this information throughout the guide.

lspci -nnk

Find 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.


Part 1: Automated Host Preparation with QuickPassthrough

This revised section replaces the manual GRUB editing and driver blacklisting with the QuickPassthrough script for a more modern and less error-prone setup.

1. Enable IOMMU in BIOS/UEFI

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).

2. Enable IOMMU in BIOS/UEFI:

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.

3. Modify GRUB Configuration:

Locate the /etc/default/grub file on your Linux system:

sudo nano /etc/default/grub

Edit the GRUB_CMDLINE_LINUX line to include iommu=pt.

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

Update GRUB:

After saving the changes to /etc/default/grub, you must update the GRUB configuration.

Run the command:

grub2-mkconfig -o /boot/grub2/grub.cfg

Then reboot:

sudo reboot

4. Check if iommu=pt is active

To check if iommu=pt is active, you can verify the kernel command line and examine the kernel's boot messages.

Check the kernel command line.

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

Examine kernel boot messages

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.


3. Download and Run quickpassthrough

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
    

4. Reboot the Host

The script will modify system files and rebuild the initramfs. You must reboot your computer for these changes to take effect.


5. Verify the VFIO Driver

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.


Part 2: KVM Installation & Networking

1. Install Virtualization Packages

sudo dnf groupinstall --with-optional "Virtualization"

2. Start and Enable libvirt Service

sudo systemctl enable --now libvirtd

3. Add User to libvirt Group

This 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)

4. Configure Networking

  • 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) or nmcli (command line) to create a bridge (br0) and add your physical Ethernet port as a slave to it.


Part 3: Initial Windows 11 VM Creation

Use the Virtual Machine Manager application for the initial setup.

  1. Click File -> New Virtual Machine.
  2. Select your Windows 11 ISO.
  3. Allocate CPU and Memory.
  4. Create a virtual disk (qcow2 format is recommended).
  5. On the final screen, check the "Customize configuration before install" box before clicking Finish.
  6. 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.iso file.
      • 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).
  7. Click Begin Installation. Proceed with the Windows setup, loading the viostor driver from the VirtIO CD when prompted.

Part 4: Post-Installation Performance Tuning

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-workstation

Here are the key sections to add or modify.

1. CPU Pinning (cputune)

This locks the VM's virtual CPUs to your physical CPU threads, eliminating stutter.

  1. Find your CPU layout: lscpu --extended. Note your physical core and thread numbers.
  2. 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.
  3. 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>

2. Huge Pages

This improves memory performance.

  1. 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
  2. Modify the <memoryBacking> section in your XML:
      <memoryBacking>
        <hugepages/>
        <nosharepages/>
      </memoryBacking>

3. Other Optimizations

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment