Create a Linux Gaming HVM, integrated with QubesOS

Goals

We want a qube with the following characteristics:

Hardware used

The same as for my article "Create a Gaming HVM".

Prerequise

You already followed my article "Create a Gaming HVM"

Main steps summary

  1. Create a standalone qube based on a debian template

  2. Install the GPU drivers and Steam

  3. Make the qube bootable without a kernel provided by dom0

  4. Create a Xorg configuration file for your screen and GPU

  5. Install your favorite Windows Manager and some Xorg input dependencies

  6. Create specific pulseaudio config for muliseat Xorg

Detailled steps

Create a new standalone based on a debian template (I used the debian minimal template, but it is a better idea to use the debian template). Then install the required dependencies for Steam and the AMD GPU

dpkg --add-architecture i386
apt update
apt install pciutils steam firmware-linux-nonfree libgl1-mesa-dri xserver-xorg-video-amdgpu libgl1:i386 mesa-vulkan-drivers mesa-vulkan-drivers:i386

Using a kernel provided by debian

You must run the kernel provider by debian, because we will use some non-default kernel module for the GPU driver. Just follow the doc: managing-vm-kernel.

HVM

In the qube configuration, set it to HVM, without kernel and do all the PCI passthough you want. I do 3 PCI passthough:

Xorg

Now Xorg and Pulseaudio. From XKCD:

image

Things you need to install:

In my case, it is:

apt install xserver-xorg-input-kbd xserver-xorg-input-libinput xserver-xorg-input-mouse pavucontrol i3

Then create a xorg configuration file for your GPU and screen. My file, named "AOC.conf":

Section "ServerLayout"
Identifier "Gaming"
Screen 0 "AMD AOC" Absolute 0 0
EndSection

Section "Device"
Identifier  "AMD"
Driver      "amdgpu"
# The BusID value will change after each qube reboot. 
BusID       "PCI:0:8:0"
EndSection

Section "Monitor"
Identifier "AOC"
VertRefresh 60
# https://arachnoid.com/modelines/
Modeline "1920x1080" 172.80 1920 2040 2248 2576 1080 1081 1084 1118
EndSection

Section "Screen"
Identifier "AMD AOC"
Device     "AMD"
Monitor    "AOC"
EndSection

We can’t know what is the correct BusID before the qube is started. And it change after each reboot. So let’s write a script — named "xorgX1.sh" — that update this configuration file with the correct value, then start a binary on the Xorg X screen n°1.

#!/bin/bash

binary=${1:?binary required}

# Find the correct BusID of the AMD GPU, then set it in the Xorg configuration file
pci=$(lspci | grep "VGA" | grep "AMD/ATI" | cut -d " " -f 1 | cut -d ":" -f 2 | cut -d "." -f 1 | cut -d "0" -f 2)
sed -i "s/PCI:0:[0-9]:0/PCI:0:$pci:0/g" /home/user/AOC.conf

# Start the Xorg server for the X screen number 1.
# The X screen n°0 is already used for QubesOS integration
startx "$binary" -- :1 -config /home/user/AOC.conf

You can launch you favorite Windows Manager like that

sudo ./xorgX1.sh /usr/bin/i3

Now... another issue: You don’t have sound for anything that is not on Xorg server X screen n°0.

Pulseaudio

So you need to configure pulseaudio for Xorg multiseat. The archlinux documentation explain that very well: Xorg multiseat Use the option without system-mode deamon and adapt it to qube: Add the following line to /etc/pulse/qubes-default.pa

load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1

Then add this config for root:

mkdir /root/.pulse
echo "default-server = 127.0.0.1" > /root/.pulse/client.conf

The sound was buggy/laggy on my computer. So tried to find a workaround by playing with pulseaudio settings. It was more or less random tries, so I can’t really explain it: In /etc/pulse/daemon.conf add the following lines:

default-fragments = 60
default-fragment-size-msec = 1
high-priority = no
realtime-scheduling = no
nice-level = 18

In /etc/pulse/qubes-default.pa change

load-module module-udev-detect

to

load-module module-udev-detect tsched=0

Final notes

It is working, integrated with QubesOS, and good enough to play video games (I am playing / played on it: FFXIV, Tomb raider, Avorion, Don’t Starve, …). However, it is a bit slower than on a Windows HVM.

References