libvirt_win10_vm icon indicating copy to clipboard operation
libvirt_win10_vm copied to clipboard

  • Virtual Machine with vGPU Unlock for single GPU desktop This document catalogs my working setup for configuring an Arch Linux host OS to run a Windows 10 VM while passing through a virtualized GPU.

** Sources The resources I used during my own install. This document is a compilation of the instructions and files provided by these people.

*** Guides - [[https://docs.google.com/document/d/1pzrWJ9h-zANCtyqRgS7Vzla0Y8Ea2-5z2HEi4X75d2Q][vGPU Wiki]] - [[https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF][PCI passthrough via OVMF]] - [[https://wvthoog.nl/proxmox-7-vgpu/][Proxmox 7 vGPU]] by wvthoog - [[https://www.youtube.com/watch?v=cPrOoeMxzu0][vGPU YouTube guide]] by Craft Computing - [[https://looking-glass.io/docs/stable/install/][Looking Glass]] - [[https://www.youtube.com/watch?v=wEhvQEyiOwI][Looking Glass YouTube guide]] by Pavol Elsig

*** Sources - [[https://github.com/DualCoder/vgpu_unlock][vGPU unlock scripts]] by DualCoder - [[https://github.com/KrutavShah/vGPU_LicenseBypass][vGPU_LicenseBypass]] by KrutavShah - [[https://github.com/rupansh/vgpu_unlock_5.12][vGPU unlock patch for kernel 5.12]] by rupansh

** Configuration The what and how. Mostly described in suggested installation order unless otherwise stated. *** Host **** Operating system Configuration of the host OS for virtualization using KVM and device passthrough using OVMF, IOMMU, and VFIO.

***** Arch Linux

***** Kernel 5.12.15-arch1-1

***** Kernel modules - vfio - vfio_iommu_type1 - vfio_pci - vfio_virqfd ****** How to add 1. Edit [[file:/etc/mkinitcpio.conf]] 2. Add ~MODULES=(... vfio vfio_iommu_type1 vfio_pci vfio_virqfd ...)~ to the MODULES line. 3. Add ~HOOKS=(... modconf ...)~ to the HOOKS line. 4. Update ~update-initramfs -P~ (use ~mkinitpico -P~ for manjaro)

***** Boot parameters - amd_iommu=on - iommu=pt - vfio_iommu_type1.allow_unsafe_interrupts=1 - kvm.ignore_msrs=1 - blacklist=nouveau ****** How to add 1. edit [[file:/etc/default/grub]] 2. Add to GRUB_CMDLINE_LINUX_DEFAULT: #+begin_src GRUB_CMDLINE_LINUX_DEFAULT="amd_iommu=on iommu=pt vfio_iommu_type1.allow_unsafe_interrupts=1 kvm.ignore_msrs=1 blacklist=nouveau ..." #+end_src 3. Update GRUB ~update-grub~

**** Hardware The physical devices present on my system.

 - CPU: AMD Ryzen 7 5800X (16) @ 3.800GHz
 - GPU: NVIDIA GeForce GTX 1060 6GB
 - Memory: 16MiB
 - 1440p Monitor

**** Software What needs to be installed.

***** Arch Packages :PROPERTIES: :ID: 94df3230-029b-42c2-a7bc-db75af7fb82a :END: Packages installed using =pacman=.

****** linux

The OS kernel.

  • Version: 5.12.15

******* How to install: First option 1. Install ~downgrade~ from AUR (using ~yay~ or other AUR helper) 2. ~downgrade linux~ 3. Select 5.12.15

******* How to install: From Arch archive 1. Download package ~curl -O https://archive.archlinux.org/packages/l/linux/linux-5.12.15.arch1-1-x86_64.pkg.tar.zst~ 2. Install with ~pacman -U linux-5.12.15.arch1-1-x86_64.pkg.tar.zst~

****** linux-headers

   Needed to build kernel modules, particularly the Nvidia driver.
  • Version: 5.12.15

******* How to install: First option 1. Install ~downgrade~ from AUR (using ~yay~ or other AUR helper) 2. ~downgrade linux-headers~ 3. Select 5.12.15

******** From Arch archive 1. Download package ~curl -O https://archive.archlinux.org/packages/l/linux-headers/linux-headers-5.12.15.arch1-1-x86_64.pkg.tar.zst~ 2. Install with ~pacman -U linux-headers-5.12.15.arch1-1-x86_64.pkg.tar.zst~

****** virt-manager

  Used to create and run virtual machines.

****** libvirt

****** kvm

 (Kernel-based Virtual Machine). A hypervisor. Used for virtualization.

****** qemu

****** looking-glass

 Used to view VM in graphical display.

****** iptables-nft

  For networking with the VM.

****** edk2-ovmf

****** dnsmasq

  Used for VM networking.

****** mdevctl

  Used to create vGPU devices

****** scream

  Used to read audio stream from network.

******* How to setup 1. Install using package manager. 2. Create [[https://github.com/duncanthrax/scream/issues/155#issuecomment-924401541][systemd-file]] #+BEGIN_SRC systemd [Unit] Description=Scream network audio client

[Unit] Description=Scream Receiver After=pulseaudio.service network-online.target Wants=pulseaudio.service

[Service] Type=simple ExecStartPre=/bin/sleep 3 ExecStart=scream -i virbr0 Restart=always RestartSec=1

[Install] WantedBy=default.target #+END_SRC

***** Python packages :PROPERTIES: :ID: a7fa4275-7f2e-457b-ab7b-00af5a52de36 :END: Installed with =pip=. ****** frida ******* How to install ******** If using conda 1. Install ~python-pip~ using pacman. 2. Run ~/bin/pip install frida~ ******** Otherwise 1. ~pip install frida~

***** Graphics setup

****** Nvidia Driver ******* Version: 460.73.01 merged and pre-unlocked This driver is a merged version of Nvidia's vGPU driver and their standard driver. It allows for the host graphics to be displayed while the vGPU's are active. ******* Components :PROPERTIES: :ID: 52f0c050-0f82-48af-bd19-bd5c613a29b3 :END: 1. [[https://drive.google.com/file/d/1dCyUteA2MqJaemRKqqTu5oed5mINu9Bw/view?usp=sharing][merged driver]] 2. [[https://github.com/DualCoder/vgpu_unlock][vgpu_unlock]] 3. [[https://raw.githubusercontent.com/rupansh/vgpu_unlock_5.12/master/twelve.patch][vgpu_unlock_5.12 patch]]

******* How to install ******** Make sure all above [[id:94df3230-029b-42c2-a7bc-db75af7fb82a][arch packages]] and [[id:a7fa4275-7f2e-457b-ab7b-00af5a52de36][python packages]] are installed. ******** Download the[[id:52f0c050-0f82-48af-bd19-bd5c613a29b3][components]] using ~curl -O the_link~ ******** Make the driver executable. ~chmod +x NVIDIA-Linux-x86_64-460.73.01-grid-vgpu-kvm-v5.run~ ******** Extract it. ~./NVIDIA-Linux-x86_64-460.73.01-grid-vgpu-kvm-v5.run -x~ ******** ~cd NVIDIA-Linux-x86_64-640.73.01-grid-vgpu-kvm-v5~ ******** Apply the 5.12 patch ~patch -p0 < ../twelve.patch~ ******** Disable graphics ~sudo systemctl isolate multi-user.target~ ******** Re-login as root and navigate back to the driver directory #+BEGIN_SRC bash cd /home/user/Downloads/NVIDIA-Linux-x86_64-460.73.01-grid-vgpu-kvm-v5 #+END_SRC ******** Install the driver #+BEGIN_SRC bash ./nvidia-installer --dkms #+END_SRC ******** Add ~vgpu_unlock~ to service files. #+BEGIN_SRC bash nano /lib/systemd/system/nvidia-vgpud.service #+end_src

     Replace ExecStart with:
     #+BEGIN_SRC systemd

ExecStart=/root/vgpu_unlock/vgpu_unlock /usr/bin/nvidia-vgpud #+END_SRC

     #+begin_src bash

nano /lib/systemd/system/nvidia-vgpu-mgr.service #+end_src

     Replace ExecStart with:
     #+BEGIN_SRC systemd

ExecStart=/root/vgpu_unlock/vgpu_unlock /usr/bin/nvidia-vgpu-mgr #+END_SRC

     #+begin_src bash

systemctl daemon-reload #+end_src ******** Add ~vgpu_unlock~ to source files. #+BEGIN_SRC bash nano /usr/src/nvidia-460.73.01/nvidia/os-interface.c #+END_SRC

     Under #include “nv-time.h” insert this line
     #+BEGIN_SRC cpp

#include "/root/vgpu_unlock/vgpu_unlock_hooks.c" #+END_SRC #+BEGIN_SRC bash nano /usr/src/nvidia-460.73.01/nvidia/nvidia.Kbuild #+END_SRC

     Add this to the bottom of the file.
     #+BEGIN_SRC

ldflags-y += -T /root/vgpu_unlock/kern.ld #+END_SRC ******** Remove and reinstall the Nvidia dkms module #+BEGIN_SRC bash dkms remove -m nvidia -v 460.73.01 --all dkms install -m nvidia -v 460.73.01 #+END_SRC

******** Make all of vgpu_unlock executable

~chmod -R +x vgpu_unlock~

******** Reboot

****** vGPU Profiles - nvidia-48 GRID P40-3Q

******* How to install

******** Choose profile :PROPERTIES: :ID: 492ad298-5b52-4cb4-913c-a444940d9492 :END: #+BEGIN_SRC bash :results verbatim mdevctl types #+END_SRC

     #+RESULTS:
     #+begin_example
     0000:2b:00.0
       nvidia-156
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-2B
         Description: num_heads=4, frl_config=45, framebuffer=2048M, max_resolution=5120x2880, max_instance=12
       nvidia-215
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-2B4
         Description: num_heads=4, frl_config=45, framebuffer=2048M, max_resolution=5120x2880, max_instance=12
       nvidia-241
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-1B4
         Description: num_heads=4, frl_config=45, framebuffer=1024M, max_resolution=5120x2880, max_instance=24
       nvidia-283
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-4C
         Description: num_heads=1, frl_config=60, framebuffer=4096M, max_resolution=4096x2160, max_instance=6
       nvidia-284
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-6C
         Description: num_heads=1, frl_config=60, framebuffer=6144M, max_resolution=4096x2160, max_instance=4
       nvidia-285
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-8C
         Description: num_heads=1, frl_config=60, framebuffer=8192M, max_resolution=4096x2160, max_instance=3
       nvidia-286
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-12C
         Description: num_heads=1, frl_config=60, framebuffer=12288M, max_resolution=4096x2160, max_instance=2
       nvidia-287
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-24C
         Description: num_heads=1, frl_config=60, framebuffer=24576M, max_resolution=4096x2160, max_instance=1
       nvidia-46
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-1Q
         Description: num_heads=4, frl_config=60, framebuffer=1024M, max_resolution=5120x2880, max_instance=24
       nvidia-47
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-2Q
         Description: num_heads=4, frl_config=60, framebuffer=2048M, max_resolution=7680x4320, max_instance=12
       nvidia-48
         Available instances: 6
         Device API: vfio-pci
         Name: GRID P40-3Q
         Description: num_heads=4, frl_config=60, framebuffer=3072M, max_resolution=7680x4320, max_instance=8
       nvidia-49
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-4Q
         Description: num_heads=4, frl_config=60, framebuffer=4096M, max_resolution=7680x4320, max_instance=6
       nvidia-50
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-6Q
         Description: num_heads=4, frl_config=60, framebuffer=6144M, max_resolution=7680x4320, max_instance=4
       nvidia-51
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-8Q
         Description: num_heads=4, frl_config=60, framebuffer=8192M, max_resolution=7680x4320, max_instance=3
       nvidia-52
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-12Q
         Description: num_heads=4, frl_config=60, framebuffer=12288M, max_resolution=7680x4320, max_instance=2
       nvidia-53
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-24Q
         Description: num_heads=4, frl_config=60, framebuffer=24576M, max_resolution=7680x4320, max_instance=1
       nvidia-54
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-1A
         Description: num_heads=1, frl_config=60, framebuffer=1024M, max_resolution=1280x1024, max_instance=24
       nvidia-55
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-2A
         Description: num_heads=1, frl_config=60, framebuffer=2048M, max_resolution=1280x1024, max_instance=12
       nvidia-56
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-3A
         Description: num_heads=1, frl_config=60, framebuffer=3072M, max_resolution=1280x1024, max_instance=8
       nvidia-57
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-4A
         Description: num_heads=1, frl_config=60, framebuffer=4096M, max_resolution=1280x1024, max_instance=6
       nvidia-58
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-6A
         Description: num_heads=1, frl_config=60, framebuffer=6144M, max_resolution=1280x1024, max_instance=4
       nvidia-59
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-8A
         Description: num_heads=1, frl_config=60, framebuffer=8192M, max_resolution=1280x1024, max_instance=3
       nvidia-60
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-12A
         Description: num_heads=1, frl_config=60, framebuffer=12288M, max_resolution=1280x1024, max_instance=2
       nvidia-61
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-24A
         Description: num_heads=1, frl_config=60, framebuffer=24576M, max_resolution=1280x1024, max_instance=1
       nvidia-62
         Available instances: 0
         Device API: vfio-pci
         Name: GRID P40-1B
         Description: num_heads=4, frl_config=45, framebuffer=1024M, max_resolution=5120x2880, max_instance=24

     #+end_example

     I chose nvidia-47 (GRID P40-3Q) because it has 3Q at the end of its name. This means I can have two 3GB vGPU's running.

******** Determine GPU PCI address #+BEGIN_SRC bash :results verbatim lspci | grep VGA PCI_ADDRESS=$(lspci | grep VGA | grep -Po '\d\w:\d\d.\d') echo $PCI_ADDRESS #+END_SRC

     #+RESULTS:
     : 2b:00.0 VGA compatible controller: NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] (rev a1)
     : 2b:00.0

******** Generate UUIDs for each vGPU #+BEGIN_SRC bash UUID1=$(uuidgen) UUID2=$(uuidgen) echo $UUID1 $UUID2 #+END_SRC

     #+RESULTS:
     : 2e82a1ad-3c7a-4b79-869f-3637b6b299a7 7a9c2eda-fa37-49f7-bb97-069c679b6eef

******** Create vGPUs :PROPERTIES: :ID: 62088cb8-6c34-4fa0-9678-23bdc78632b6 :END: #+BEGIN_SRC bash mdevctl start -u $UUID1 -p 0000:$PCI_ADDRESS -t nvidia-48 mdevctl start -u $UUID2 -p 0000:$PCI_ADDRESS -t nvidia-48

mdevctl define -a -u $UUID1 mdevctl define -a -u $UUID2 #+END_SRC

**** VM Image The virtual machine configuration.

 - Chipset: Q35
 - Firmware: UEFI x86_64: /usr/share/edk2-ovmf/x64/OVMF_CODE.fd
 - Hypervisor KVM
 - Spice Server
 - Video QXL
 - MDEV
 - shmem looking-glass

***** How to install ****** In virt-manager, create virtual machine. ****** Apply above settings minus "MDEV" and "shmem looking-glass". ****** Start VM and install OS. ****** Shutdown guest. ****** Add looking-glass shmem device. The size is determined like [[https://looking-glass.io/docs/stable/install/#client-determining-memory][this]]. #+BEGIN_SRC xml 64 #+END_SRC

   Make a file =/etc/tmpfiles.d/10-looking-glass.conf=
   #+BEGIN_SRC conf

#Type Path Mode UID GID Age Argument

f /dev/shm/looking-glass 0660 user kvm - #+END_SRC ****** Remove tablet device

****** Add MDEV device. Where ~$UUID1~ is the UUID of one of the mdev vGPU's created [[id:62088cb8-6c34-4fa0-9678-23bdc78632b6][earlier]]. #+BEGIN_SRC xml

#+END_SRC ****** Install [[id:ae17e44e-f00c-4995-a017-8dcd919c8f0f][all guest software]]. ****** Shutdown guest. ****** Either set =Video= model to "none" or install [[id:e152ccec-fd25-4c23-befd-feb84becdf70][guest Nvidia driver]]​.

***** How to run 1. Start VM. (May need to click run several times if error related to "vfio-" occurs. 2. Run looking-glass client #+BEGIN_SRC bash export SDL_VIDEO_X11_VISUALID= looking-glass-client #+END_SRC

*** Guest Inside the VM.

**** Operating system - Windows 10

**** To download (within guest) :PROPERTIES: :ID: 6d9a90c9-e736-4d73-8447-a4e7db5c5bde :END: - [[https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.208-1/virtio-win-guest-tools.exe][virtio guest tools]] - [[https://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-latest.exe][spice guest tools]] - [[https://looking-glass.io/ci/host/download?id=stable][looking glass host]] - [[https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/upstream-virtio/virtio-win10-prewhql-0.1-161.zip][virtio PCI RAM controller driver]] - [[https://storage.googleapis.com/nvidia-drivers-us-public/GRID/GRID12.2/462.31_grid_win10_server2016_server2019_64bit_international.exe][Nvidia GRID driver]] - [[https://github.com/KrutavShah/vGPU_LicenseBypass/releases/download/v1.0/vGPULicenseBypass.bat][vGPU_LicenseBypass]] - [[https://github.com/duncanthrax/scream][Scream audio driver]]

**** Software :PROPERTIES: :ID: ae17e44e-f00c-4995-a017-8dcd919c8f0f :END: ***** Looking Glass Host ****** How to install 1. Download [[id:6d9a90c9-e736-4d73-8447-a4e7db5c5bde][components]]. 2. Update driver in =Device Manager->System Devicess->PCI standard RAM Controller= to [[https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/upstream-virtio/virtio-win10-prewhql-0.1-161.zip][virtio PCI RAM controller driver]]. 3. Install [[https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.208-1/virtio-win-guest-tools.exe][virtio guest tools]] and [[https://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-latest.exe][spice guest tools]]. 4. Install [[https://looking-glass.io/ci/host/download?id=stable][looking glass host]] by running =looking-glass-host-setup.exe= as administrator. 5. VM.

***** [[https://storage.googleapis.com/nvidia-drivers-us-public/GRID/GRID12.2/462.31_grid_win10_server2016_server2019_64bit_international.exe][Nvidia GRID driver]] :PROPERTIES: :ID: e152ccec-fd25-4c23-befd-feb84becdf70 :END: ****** How to install 1. Run [[https://storage.googleapis.com/nvidia-drivers-us-public/GRID/GRID12.2/462.31_grid_win10_server2016_server2019_64bit_international.exe][Nvidia GRID driver]] installer. 2. Reboot. 3. In =Nvidia Console= set resolution. My monitor used 2560x1440. 4. Run [[https://github.com/KrutavShah/vGPU_LicenseBypass/releases/download/v1.0/vGPULicenseBypass.bat][vGPU_LicenseBypass]].

   # TODO Maybe add Windows Autologon instructions https://docs.microsoft.com/en-us/sysinternals/downloads/autologon
   # TODO Maybe add looking-glass-host start-up instructions

***** [[https://github.com/duncanthrax/scream/releases/download/3.8/Scream3.8.zip][Scream audio driver]]

****** How to install 1. Install driver. 2. Change sound source to Scream (WDM).

** My files

  • [[file:win10.xml][Final QEMU Windows 10 VM image]]
  • [[file:mdev.sh][mdev device creation script]]

** Suggestions Since there is a lot of messing with the kernel and graphics drivers, it's important to have a plan for recovering your host OS.

  • Use timeshift or other auto-snapshotting of the host.
  • Have a recovery drive available.

** Maintenance

*** Preventing accidental upgrades In order to avoid accidentally upgrading these carefully chosen package versions, make sure to ignore updates to them:

~IgnorePkg = linux linux-headers nvidia-dkms nvidia nvidia-utils nvidia-settings opencl-nvidia libxnvctrl~