4. Game controllers and USB controllers - HikariKnight/vfio-setup-docs GitHub Wiki

Game controllers and USB controllers

Several game controllers will not work with a normal USB passthrough, in these cases you will need to pass an entire USB controller, yikes. There are a few solutions though.

  • Pass through a PCI-e USB controller (no stubbing required! Just make sure it is in its own IOMMU group).

  • Pass through a free USB controller from your motherboard if it has one (high end boards like the Asus Prime X399-A has 3 USB controllers, 2 of which are in their own IOMMU groups!).

  • If you passed through an Nvidia card to your VM you can use the Moonlight Streaming Client to “bridge” your game controller to the VM, also you will be able to get sound from the moonlight client instead of spice.

  • Steam In-Home streaming is an alternative but I have not had any reliable success with it when it comes to stable contact with the VM.

For option 1 and 2 you use the below 2 commands to figure out which groups the usb controllers are in then use the second command (but replace X with the group number that the usb controllers are in) to check if there are any other devices in that group, if the controllers are in their own group before passing them to the VM the same way you would with a graphics card after it has been stubbed.

ls-iommu | grep -i "usb controller"
ls-iommu | grep -i "group X"

Using Moonlight Streaming to “pass through” a game controller (requires an Nvidia card inside the VM!)

Using Moonlight Streaming to pass through your game controller will add some overhead and CPU heavy games might get some stutter, further testing on more hardware is needed to verify. Also you will have to use the Moonlight Streaming window when you plan to use the game controller, you can probably make a script to keep focus on the Moonlight Streaming window but set LookingGlass to be “always on top” for better image quality.

Lastly, latency should be very low as you will be using the Host-Only isolated network with the paravirtualized VirtIO driver.

First we need to install flatpak, as the Moonlight Streaming client is only available as a flatpak, unless you compile it from source.

Head over to https://flatpak.org/ and follow the install instructions.

Newer AMD GPUs that use the amdgpu kernel driver have no issues with OpenGL and flatpak, everything works out of the box!

Note: From my experience, Moonlight Streaming does not support the nouveau driver.

Enabling OpenGL support in flatpak for Nvidia Proprietary driver

If you are using an Nvidia Graphics Card on your Linux Host, You will need to do some extra work to enable OpenGL for flatpak.

Linux Uprising has a nice guide that you can read here, but a simplified version will be written here just in case the article vanishes in the future.

  1. Find out the exact version of your Nvidia driver (if you are unsure, try both commands).
Using newer nvidia drivers from 2018+ Nvidia driver is older than 390 (2017 and earlier)
apt-cache policy "nvidia-driver-*" apt-cache policy "nvidia-3*"
  1. Note down the numbers before the “-” and then check if your driver is supported by flatpak and available.
flatpak remote-ls flathub
  1. Install the appropriate 32bit and 64bit runtime for your driver (replace MAJOR and MINOR with the numbers that you wrote down, 390.48 would be 390-48 in the commands).
flatpak install flathub org.freedesktop.Platform.GL.nvidia-MAJOR-MINOR
flatpak install flathub org.freedesktop.Platform.GL32.nvidia-MAJOR-MINOR
  1. The example for installing the runtime for Nvidia driver 390.48 would then be
flatpak install flathub org.freedesktop.Platform.GL.nvidia-390-48
flatpak install flathub org.freedesktop.Platform.GL32.nvidia-390-48
  1. You are now done with installing flatpak with OpenGL support

Installing & configuring the Moonlight Streaming Client

  1. If you followed the flatpak install guide, you can install the Moonlight Streaming Client from here: https://flathub.org/apps/details/com.moonlight_stream.Moonlight or by using the command below.
flatpak install flathub com.moonlight_stream.Moonlight
  1. Open Geforce Experience on your virtual machine, click on the cogwheel and go to the Shield section and enable Gamestream.


  1. Open up Moonlight Streaming and click the cogwheel in the top right and change any settings you would like.

    Note: You can play around with the video bitrate for better quality overall, I have not personally noticed any issues related to latency or stutter when using the Host-Only network over the VirtIO network device when I decided to max the bitrate for testing once.



  1. Once done, click the back button and click Add PC and input the Host Only network IP address for the virtual machine.


  1. The machine should be detected and added to the list with a lock on it, once you click on it you will be asked to input a one time pin given to you by the Moonlight Streaming Client that you will have to type into your virtual machine.

    Note: If the pin input notification does not show up for you, try go into Geforce Experience and remove all Shield devices to reset all Shield authentications.



  1. If successful the lock will be removed from the icon and you now just launch Steam or your games through Moonlight whenever you need Gamepad support!

    Read about any hotkeys that Moonlight Streaming has here: https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide#keyboardmousegamepad-input-options

Launch specific programs on specific cores in Windows

This is something you in most cases will never need but I will add it here in case you do.

Make a new text file and name it what you want but save it with the extension .ps1 and then paste in the below contents and change the filepath for what you want to launch, this example shows how to launch Guild Wars 2 and tell it to only use cores 3,4,5 and 6.

The ProcessorAffinity value is essentially the value of all the cores you want the program to run on, added together.

# If the executable has to have the priority and affinity changed with administrator rights, uncomment the lines below
#If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
#{
#	$arguments = "& '" + $myinvocation.mycommand.definition + "'"
#	Start-Process powershell -Verb runAs -ArgumentList $arguments
#	Break
#}

# Start the exe (comment out to not launch a program)
$app = Start-Process -FilePath "C:\Games\Guild Wars 2\Gw2-64.exe" -ArgumentList "$args"

# Get the process ID (exe name without .exe)
$proc = Get-Process Gw2-64

# Set the affinity and priority
$proc.ProcessorAffinity = 60
$proc.PriorityClass = "High"

# Uncomment the below line if you want the script to pause at the end
#cmd /c pause | out-null

# Core list (any cores past 8 is literally the previous cores value*2)
# core# = Value
# 1 = 1
# 2 = 2
# 3 = 4
# 4 = 8
# 5 = 16
# 6 = 32
# 7 = 64
# 8 = 128

You can then run the script through the command (or make a shortcut using it)

powershell -nologo -executionpolicy bypass -File “C:\path\to\ps1\file” arg1 arg2 etc

For a shortcut the process may have to start inside this folder, this depends on how the script is launched.

C:\Windows\System32\WindowsPowerShell\v1.0\
⚠️ **GitHub.com Fallback** ⚠️