LoginSignup
2
4

More than 3 years have passed since last update.

Uuntu 19.10でGPUパススルーの構築(X570、シングルGPU)

Last updated at Posted at 2020-04-09

Ubuntu19.10のKVMでシングルGPU構成でGPUパススルーが出来る手順について掲載します。

環境

  マザー:Biostar X570GT8
  CPU:Ryzen3600
  OS:ubuntu 19.10
  GPU:RADEON RX580

1. grubの設定

# vi /etc/defalut/grub

GRUB_CMDLINE_LINUX="amd_iommu=on iommu=pt pcie_aspm=off acpi_enforce_resources=lax thermal.off=1 video=1920x1080"
amd_iommu : iommuの有効化
iommu     : PCIパススルーのパフォーマンス改善
pcie_aspm : PCI-Expressの省電力機能の無効化

GRUB_GFXMODE="1920x1080-24"
# update-grub2

2. initramfs設定

# vi /etc/modules-load.d/modules.conf

vfio
vfio_iommu_type1
vfio_virqfd
options kvm_amd avic=1

3. カーネルモジュールの設定

3.1 KVMモジュールの設定

# vi /etc/modprobe.d/kvm.conf

options kvm ignore_msrs=1
options kvm allow_unsafe_assigned_interrupts=1
options kvm report_ignored_msrs=0

3.2 QEMUモジュールの設定

# vi /etc/modprobe.d/qemu-system-x86.conf

options kvm_intel nested=1
options kvm_amd avic=1

3.3 VFIOモジュールの設定

# vi /etc/modprobe.d/vfio-pci.conf

options vfio-pci disable_vga=1

# vi /etc/modprobe.d/vfio_iommu_type1.conf

options vfio_iommu_type1 allow_unsafe_interrupts=1

3.4 AMD GPUドライバー設定

# vi /etc/modprobe.d/amd.conf

blacklist radeon
options amdgpu pcie_gen_cap=0x2

オプションはシングルGPU構成の時に、ドライバー再ロード後にVMが起動出来なくなるのを防ぐ設定。
ただし、ドライバーのアンロード、ロードをパススルーを挟まずに行うとOSがクラッシュする。

4. initramfsの再作成

# update-initramfs -k all -u

5. libvirtdの設定

5.1 QEMU HOOKスクリプトの作成(シングルGPU用、ホストとゲストでGPUを分けるなら不要)

# vi /etc/libvirt/hooks/qemu

#!/bin/bash

SHELL_PATH=/etc/libvirt/hooks

NAME=${1}
OPERATION=${2}
SUB_OPERATION=${3}
SCRIPT=${SHELL_PATH}/qemu_${NAME}.sh
LOG_FILE=/tmp/qemu.log

echo `date "+%Y-%m-%d %H:%M:%S.%N"` $* >> ${LOG_FILE}

if [ -x ${SCRIPT} ] ;then
        echo `date "+%Y-%m-%d %H:%M:%S.%N"` $SCRIPT ${OPERATION} ${SUB_OPERATION} >> ${LOG_FILE}
        $SCRIPT ${OPERATION} ${SUB_OPERATION}
fi

# vi /etc/libvirt/hooks/qemu_VM名.sh

#!/bin/bash
MODULE_FILE=/var/tmp/gpu_module

OPERATION=${1}
SUB_OPERATION=${2}
SCRIPT=$0
MAX_WAIT_COUNT=5
LOG_FILE=/tmp/qemu.log

case ${OPERATION} in
    "prepare")
        case ${SUB_OPERATION} in
            "begin")
                # display-manager.service Stop
                #systemctl isolate multi-user.target
                systemctl stop display-manager.service
                # kill lxqt-panel(In lightdm, lxqt environment, process may remain)
                killall lxqt-panel
                # vtconsole Unbind
                echo 0 > /sys/class/vtconsole/vtcon1/bind
                # VGA Device List Up
                DEVICE_ID=`lspci -nn | grep VGA | awk '{print $1}'`
                # Boot VGA Check
                for device in `echo ${DEVICE_ID}`; do
                    # Boot VGA Flag Check
                    if [ "`cat /sys/bus/pci/devices/0000:${device}/boot_vga`" = "1" ]; then
                        # PCI Vender ID Get
                        VENDER_ID=`cat /sys/bus/pci/devices/0000:${device}/vendor`
                        # Use Kernel Driver Name Get
                        DRIVER_NAME=`lspci -k -s 0000:${device} | grep "Kernel driver in use" | awk '{print $5}'`
                    fi
                done
                # Kernel Module List Up
                lsmod | grep ^${DRIVER_NAME} | awk '{print $1}' > ${MODULE_FILE}
                # Kernel GPU Module Check
                if [ -s ${MODULE_FILE} ]; then
                    # AMD GPU Driver Clashes
                    # Runs only with NVIDIA Driver
                    if [ "${DRIVER_NAME}" = "nvidia" ]; then
                        # Unbind EFI-Framebuffer
                        echo efi-framebuffer.0 > /sys/bus/platform/drivers/efi-framebuffer/unbind
                    fi
                    # Failure to sleep results in an error
                    sleep 2
                    # Unload All GPU drivers
                    for module in `cat ${MODULE_FILE}`; do
                        # Unload Kernel Module
                        modprobe -s -r ${module}
                        # Return Code Setting
                        rc=$?
                        # Running Log Output
                        echo "${SCRIPT} modprobe -r rc=${rc}" >> $LOG_FILE
                    done
                fi
                exit $rc
            ;;
        esac
    ;;
    "release")
        case ${SUB_OPERATION} in
            "end")
                # GPU Kernel Module Check
                if [ -s ${MODULE_FILE} ]; then
                    # Load All GPU drivers
                    for module in `cat ${MODULE_FILE}`; do
                        # Load Kernel Module
                        modprobe ${module}
                    done
                    # GPU Kernel Module List File Remove
                    # rm -f ${MODULE_FILE}
                    # Sleep for the time being
                    sleep 1
                    # efi-framebuffer.0 File not exist check
                    if [ ! -e /sys/bus/platform/drivers/efi-framebuffer/efi-framebuffer.0 ]; then
                        # Bind EFI-Framebuffer
                        echo "efi-framebuffer.0" > /sys/bus/platform/drivers/efi-framebuffer/bind
                    fi
                fi
                # display-manager.service Start
                #systemctl isolate graphical.target
                systemctl start display-manager.service
            ;;
        esac
    ;;
esac

5.2 VMの作成

5.2.1 virt-managerで新規VMを作成

・GPUを追加
・USB(キーボード、マウス)のPCIデバイスを追加
・ディスプレイ Spiceを削除
・チャンネル qemu-gaを削除
・チャンネル spiceを削除
・ビデオQXLを削除

5.2.2 VMのxmlファイル編集

# vi /etc/libvirt/qemu/VM名.xml

5.2.2.1 schema拡張

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

5.2.2.2 VIDEO BIOSファイル設定

※VIDEO BIOSファイルはTechPowerUpサイトからGPUに合ったファイルをダウンロードするかGPU-Zで吸い出す。
 NVIDIAのBIOSは先頭から0x600バイト削除する。("55 AA 7B"の前を削除)

<hostdev mode='subsystem' type='pci' managed='yes'>
  <source>
    <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
  </source>
  <rom bar='on' file='/etc/libvirt/qemu/vbios/vbios.rom'/>
  <address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</hostdev>

5.2.2.3 QEMU VGAの無効化

  <qemu:commandline>
    <qemu:arg value='-vga'/>
    <qemu:arg value='none'/>
    <qemu:arg value='-nographic'/>
  </qemu:commandline>

5.2.2.4 NVIDIAのCode43対応

  <features>
    <hyperv>
      <vendor_id state='on' value='123456789ab'/>
    </hyperv>
    <kvm>
      <hidden state='on'/>
    </kvm>
  </features>

5.2.2.5 QEMU4.0のNVIDIAのバグを回避

  <features>
    <ioapic driver='kvm'/>
  </features>

5.2.2.6 RYZENのCPU機能の有効化

  <cpu mode='host-passthrough' check='none'>
    <feature policy='require' name='topoext'/>
    <feature policy='require' name='invtsc'/>
  </cpu>

5.2.2.7 CPU,iothreadを固定することで映像と音声のずれを防ぐ設定。

  <iothreads>1</iothreads>
  <cputune>
    <vcpupin vcpu='0' cpuset='2'/>
    <vcpupin vcpu='1' cpuset='8'/>
    <vcpupin vcpu='2' cpuset='3'/>
    <vcpupin vcpu='3' cpuset='9'/>
    <vcpupin vcpu='4' cpuset='4'/>
    <vcpupin vcpu='5' cpuset='10'/>
    <emulatorpin cpuset='5'/>
    <iothreadpin iothread='1' cpuset='11'/>
  </cputune>

5.2.3 libvirtdの再起動

# systemctl restart libvirtd

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4