diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 index 80f2505..a858630 --- a/install.sh +++ b/install.sh @@ -9,5 +9,5 @@ cp vfio-teardown.sh /bin/vfio-teardown.sh cp qemu /etc/libvirt/hooks/qemu chmod +x /bin/vfio-startup.sh -chmod +x /bin/vfio-teardonw/sh +chmod +x /bin/vfio-teardown.sh chmod +x /etc/libvirt/hooks/qemu diff --git a/vfio-startup.sh b/vfio-startup.sh index d488739..0a3585b 100755 --- a/vfio-startup.sh +++ b/vfio-startup.sh @@ -28,6 +28,14 @@ function unload_module_if_loaded { done } +function get_virsh_id { + python -c "print('pci_0000_'+'$1'.split(':')[0] + '_' + '$1'.split(':')[1].split('.')[0] + '_' + '$1'.split(':')[1].split('.')[1])" +} + +function get_pci_id_from_device_id { + lspci -nn | grep $1 | awk '{print $1}' +} + # Stop currently running display manager if test -e "/tmp/vfio-store-display-manager" ; then rm -f /tmp/vfio-store-display-manager @@ -41,20 +49,33 @@ stop_display_manager_if_running mdm.service stop_display_manager_if_running display-manager.service -# Unbind VTconsoles if currently bound -if test -e "/sys/class/vtconsole/vtcon0/bind" ; then - echo 0 > /sys/class/vtconsole/vtcon0/bind -fi -if test -e "/sys/class/vtconsole/vtcon1/bind" ; then - echo 0 > /sys/class/vtconsole/vtcon1/bind +# Unbind VTconsoles if currently bound (adapted from https://www.kernel.org/doc/Documentation/fb/fbcon.txt) +if test -e "/tmp/vfio-bound-consoles" ; then + rm -f /tmp/vfio-bound-consoles fi +for (( i = 0; i < 16; i++)) +do + if test -x /sys/class/vtconsole/vtcon${i}; then + if [ `cat /sys/class/vtconsole/vtcon${i}/name | grep -c "frame buffer"` \ + = 1 ]; then + echo 0 > /sys/class/vtconsole/vtcon${i}/bind + echo "Unbinding console ${i}" + echo $i >> /tmp/vfio-bound-consoles + fi + fi +done + +# According to kernel documentation (https://www.kernel.org/doc/Documentation/fb/fbcon.txt), +# specifically unbinding efi-framebuffer is not necessary after all consoles +# are unbound (and often times harmful in my experience), so it was omitted here +# I leave it here for reference in case anyone needs it. #Unbind EFI-Framebuffer if currently bound -if test -e "/sys/bus/platform/drivers/efi-framebuffer/unbind" ; then - echo efi-framebuffer.0 > /sys/bus/platform/drivers/efi-framebuffer/unbind -else - echo "Could not find framebuffer to unload!" -fi +# if test -e "/sys/bus/platform/drivers/efi-framebuffer/unbind" ; then +# echo efi-framebuffer.0 > /sys/bus/platform/drivers/efi-framebuffer/unbind +# else +# echo "Could not find framebuffer to unload!" + sleep "${long_delay}" @@ -74,8 +95,21 @@ unload_module_if_loaded nouveau unload_module_if_loaded i915 # Unbind the GPU from display driver -virsh nodedev-detach pci_0000_01_00_0 -virsh nodedev-detach pci_0000_01_00_1 +if test -e "/tmp/vfio-virsh-ids" ; then + rm -f /tmp/vfio-virsh-ids +fi + +gpu_device_id=$(modprobe -c vfio-pci | grep 'options vfio_pci ids' | cut -d '=' -f2 | cut -d ',' -f 1) +gpu_audio_device_id=$(modprobe -c vfio-pci | grep 'options vfio_pci ids' | cut -d '=' -f2 | cut -d ',' -f 2) +gpu_pci_id=$(get_pci_id_from_device_id ${gpu_device_id}) +gpu_audio_pci_id=$(get_pci_id_from_device_id ${gpu_audio_device_id}) +virsh_gpu_id=$(get_virsh_id ${gpu_pci_id}) +virsh_gpu_audio_id=$(get_virsh_id ${gpu_audio_pci_id}) +echo ${virsh_gpu_audio_id} >> /tmp/vfio-virsh-ids +echo ${virsh_gpu_id} >> /tmp/vfio-virsh-ids + +virsh nodedev-detach "${virsh_gpu_id}" +virsh nodedev-detach "${virsh_gpu_audio_id}" # Load VFIO kernel module modprobe vfio-pci diff --git a/vfio-teardown.sh b/vfio-teardown.sh index 29dde10..9aac128 100755 --- a/vfio-teardown.sh +++ b/vfio-teardown.sh @@ -9,28 +9,39 @@ modprobe -r vfio_iommu_type1 modprobe -r vfio # Re-Bind GPU to AMD Driver -virsh nodedev-reattach pci_0000_01_00_1 -virsh nodedev-reattach pci_0000_01_00_0 +input="/tmp/vfio-virsh-ids" +while read virshId; do + virsh nodedev-reattach "$virshId" +done < "$input" -# Rebind VT consoles -if test -e "/sys/class/vtconsole/vtcon0/bind" ; then - echo 1 > /sys/class/vtconsole/vtcon0/bind -fi -if test -e "/sys/class/vtconsole/vtcon1/bind" ; then - echo 1 > /sys/class/vtconsole/vtcon1/bind -fi +# Rebind VT consoles (adapted from https://www.kernel.org/doc/Documentation/fb/fbcon.txt) +input="/tmp/vfio-bound-consoles" +while read consoleNumber; do + if test -x /sys/class/vtconsole/vtcon${consoleNumber}; then + if [ `cat /sys/class/vtconsole/vtcon${consoleNumber}/name | grep -c "frame buffer"` \ + = 1 ]; then + echo "Rebinding console ${consoleNumber}" + echo 1 > /sys/class/vtconsole/vtcon${consoleNumber}/bind + fi + fi +done < "$input" # Hack that magically makes nvidia gpus work :) if command -v nvidia-xconfig ; then nvidia-xconfig --query-gpu-info > /dev/null 2>&1 fi +# According to kernel documentation (https://www.kernel.org/doc/Documentation/fb/fbcon.txt), +# specifically unbinding efi-framebuffer is not necessary after all consoles +# are unbound (and often times harmful in my experience), so it was omitted here +# I leave it here for reference in case anyone needs it. + # Re-Bind EFI-Framebuffer -if test -e "/sys/bus/platform/drivers/efi-framebuffer/bind" ; then - echo "efi-framebuffer.0" > /sys/bus/platform/drivers/efi-framebuffer/bind -else - echo "Could not find framebuffer to bind!" -fi +# if test -e "/sys/bus/platform/drivers/efi-framebuffer/bind" ; then +# echo "efi-framebuffer.0" > /sys/bus/platform/drivers/efi-framebuffer/bind +# else +# echo "Could not find framebuffer to bind!" +# fi #Load amd driver input="/tmp/vfio-loaded-gpu-modules"