|
|
|
@@ -57,6 +57,24 @@ group_members() {
|
|
|
|
done
|
|
|
|
done
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# The functions to hand to the guest with GPU $1: every device in its IOMMU group
|
|
|
|
|
|
|
|
# (mandatory for vfio), plus any sibling function of the same PCI device that is
|
|
|
|
|
|
|
|
# itself a display or HDMI/DP audio controller. An APU parks its PSP and USB
|
|
|
|
|
|
|
|
# controllers on the same PCI device in separate IOMMU groups - those are the
|
|
|
|
|
|
|
|
# host's, so siblings are filtered by class and never pulled in blindly.
|
|
|
|
|
|
|
|
passthrough_devs() {
|
|
|
|
|
|
|
|
local d="$1" m cls
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
group_members "$d"
|
|
|
|
|
|
|
|
for m in "/sys/bus/pci/devices/${d%.*}".*; do
|
|
|
|
|
|
|
|
[ -e "$m" ] || continue
|
|
|
|
|
|
|
|
m=$(basename "$m")
|
|
|
|
|
|
|
|
cls=$(cat "/sys/bus/pci/devices/$m/class" 2>/dev/null)
|
|
|
|
|
|
|
|
case "$cls" in 0x03*|0x0403*) echo "$m";; esac
|
|
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
} | sort -u
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
driver_of() {
|
|
|
|
driver_of() {
|
|
|
|
local l
|
|
|
|
local l
|
|
|
|
l=$(readlink -f "/sys/bus/pci/devices/$1/driver" 2>/dev/null)
|
|
|
|
l=$(readlink -f "/sys/bus/pci/devices/$1/driver" 2>/dev/null)
|
|
|
|
@@ -79,7 +97,7 @@ drives_display() {
|
|
|
|
|
|
|
|
|
|
|
|
ids_of() { # vendor:device for vfio-pci binding
|
|
|
|
ids_of() { # vendor:device for vfio-pci binding
|
|
|
|
local d
|
|
|
|
local d
|
|
|
|
for d in $(group_members "$1"); do
|
|
|
|
for d in $(passthrough_devs "$1"); do
|
|
|
|
local cls; cls=$(cat "/sys/bus/pci/devices/$d/class" 2>/dev/null)
|
|
|
|
local cls; cls=$(cat "/sys/bus/pci/devices/$d/class" 2>/dev/null)
|
|
|
|
# only real functions of the card: skip bridges (class 0x0604xx)
|
|
|
|
# only real functions of the card: skip bridges (class 0x0604xx)
|
|
|
|
case "$cls" in 0x0604*) continue;; esac
|
|
|
|
case "$cls" in 0x0604*) continue;; esac
|
|
|
|
@@ -219,7 +237,7 @@ prepare)
|
|
|
|
|
|
|
|
|
|
|
|
# 1. stop whatever is holding the DRM device
|
|
|
|
# 1. stop whatever is holding the DRM device
|
|
|
|
dm=$(systemctl list-units --type=service --state=running --no-legend 2>/dev/null |
|
|
|
|
dm=$(systemctl list-units --type=service --state=running --no-legend 2>/dev/null |
|
|
|
|
awk '{print $1}' | grep -xE '(gdm|sddm|lightdm|lxdm|greetd|display-manager)\.service' | head -1)
|
|
|
|
awk '{print $1}' | grep -xE '((gdm|sddm|lightdm|lxdm|greetd|ly|emptty|lemurs)(@[a-z0-9-]+)?|display-manager)\.service' | head -1)
|
|
|
|
if [ -n "$dm" ]; then
|
|
|
|
if [ -n "$dm" ]; then
|
|
|
|
echo "$dm" > "$STATE/dm"
|
|
|
|
echo "$dm" > "$STATE/dm"
|
|
|
|
log "stopping $dm"
|
|
|
|
log "stopping $dm"
|
|
|
|
@@ -303,7 +321,7 @@ apply() {
|
|
|
|
"$v" -c qemu:///system dumpxml --inactive "$dom" > "$backup/$dom.gpu-current.xml"
|
|
|
|
"$v" -c qemu:///system dumpxml --inactive "$dom" > "$backup/$dom.gpu-current.xml"
|
|
|
|
grep -q 'ua-vfionative-gpu' "$backup/$dom.gpu-current.xml" || cp "$backup/$dom.gpu-current.xml" "$backup/$dom.before-gpu.xml"
|
|
|
|
grep -q 'ua-vfionative-gpu' "$backup/$dom.gpu-current.xml" || cp "$backup/$dom.gpu-current.xml" "$backup/$dom.before-gpu.xml"
|
|
|
|
local devs="" m
|
|
|
|
local devs="" m
|
|
|
|
for m in $( { group_members "$d"; ls -d "/sys/bus/pci/devices/${d%.*}".* | xargs -n1 basename; } | sort -u); do
|
|
|
|
for m in $(passthrough_devs "$d"); do
|
|
|
|
case "$(cat "/sys/bus/pci/devices/$m/class" 2>/dev/null)" in 0x0604*) continue;; esac
|
|
|
|
case "$(cat "/sys/bus/pci/devices/$m/class" 2>/dev/null)" in 0x0604*) continue;; esac
|
|
|
|
IFS=':.' read -r dm bs sl fn <<< "$m"
|
|
|
|
IFS=':.' read -r dm bs sl fn <<< "$m"
|
|
|
|
devs+=" <hostdev mode='subsystem' type='pci' managed='yes'>\n <source>\n"
|
|
|
|
devs+=" <hostdev mode='subsystem' type='pci' managed='yes'>\n <source>\n"
|
|
|
|
@@ -330,7 +348,7 @@ xml() {
|
|
|
|
echo "Add this to the domain, inside <devices>. Every device in the GPU's"
|
|
|
|
echo "Add this to the domain, inside <devices>. Every device in the GPU's"
|
|
|
|
echo "IOMMU group has to go together:"
|
|
|
|
echo "IOMMU group has to go together:"
|
|
|
|
echo
|
|
|
|
echo
|
|
|
|
for m in $(group_members "$d"); do
|
|
|
|
for m in $(passthrough_devs "$d"); do
|
|
|
|
local cls; cls=$(cat "/sys/bus/pci/devices/$m/class" 2>/dev/null)
|
|
|
|
local cls; cls=$(cat "/sys/bus/pci/devices/$m/class" 2>/dev/null)
|
|
|
|
case "$cls" in 0x0604*) continue;; esac
|
|
|
|
case "$cls" in 0x0604*) continue;; esac
|
|
|
|
IFS=':. ' read -r dom bus slot fn <<< "$(echo "$m" | tr ':.' ' ')"
|
|
|
|
IFS=':. ' read -r dom bus slot fn <<< "$(echo "$m" | tr ':.' ' ')"
|
|
|
|
|