228 半夜停電 結果原本的 server 掛了一顆硬碟 申請到經費後 不但買了新硬碟 也把 server 整個升級 還順便買了張新顯卡 XDD

新的電腦配置如下

  • CPU : Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
  • RAM:16GB
  • GPU: MSI Radeon RX 480 GAMING X 8G [1002:67df]
  • OS:Ubuntu 16.04

現在要設定 VGA Passthrough 簡直簡單到不行 不過還是簡單記錄一下撞到的牆

  1. 使用 virt-manager 建立新 vm 時 得要記得選成 UEFI 不要用 BIOS (不需要選 Q35 直接用預設的 I440 就可以了)

  2. 我有原版的 Windows 10 專業版 裡面附的是一隻安裝 USB 我用這個 USB dd 出來的 image 在安裝時會一直要我裝驅動程式 明明 virtio driver 都已經掛上 也都裝完了 但是卻一直沒辦法進行下一步 把所有的磁碟都改成 IDE 也一樣 最後就去 MS 官網下載 win10 iso 這樣才順利安裝

  3. 安裝時的磁碟機原本選 virtio 安裝時也裝了 virtio driver 但是安裝完重開時 卻會找不到硬碟 沒辦法開機 得要改成 IDE 開 然後再裝一次 virtio 的驅動程式

  4. Windows 整個裝完後 再從 virt-manager 那邊將顯卡跟音效卡從 PCI 那邊選進來 原本的 QXL 顯卡可以先留著 繼續用 virt-manager 裝顯卡 但是最後要開始使用時 記得將 QXL 移調 預設會用這張卡 沒辦法 disable 掉

其他的設定 大概就這些

  1. 不知道為什麼 之前泛用的 id 設定不會讓顯卡上的音效裝置載入 vfio-pci 所以我就寫死了

    cat /etc/modprobe.d/vfio.conf
    1
    options vfio-pci ids=1002:67df,1002:aaf0

  2. 開機的 kernel command line 大部分都拿掉了 不過多了個 video=efifb:off 一但啟動 vm dmesg 會吐一大堆錯誤訊息(我沒記錄下來是什麼 :p) 得要加上這個參數才行

    cat /proc/cmdline
    1
    BOOT_IMAGE=/ROOT/ubuntu@/boot/vmlinuz-4.4.0-64-generic root=ZFS=rpool/ROOT/ubuntu ro quiet splash intel_iommu=on i915.enable_hd_vgaarb=1 kvm.ignore_msrs=1 video=efifb:off vt.handoff=7

  3. Host blacklist radeon

    blacklist radeon
    1
    sudo sh -c "echo \"blacklist radeon\"" >> /etc/modprobe.d/blacklist.conf

  4. 另外我有從舊 server 上抓了些設定檔過來 不是很確定是不是需要

    $ sudo tail -n17 /etc/libvirt/qemu.conf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    nvram = [
    "/var/vm/ovmf-x64/OVMF_CODE-pure-efi.fd:/var/vm/ovmf-x64/OVMF_VARS-pure-efi.fd",
    "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd",
    "/usr/share/AAVMF/AAVMF_CODE.fd:/usr/share/AAVMF/AAVMF_VARS.fd"
    ]

    user = "root"
    group = "root"
    cgroup_device_acl = [
    "/dev/null", "/dev/full", "/dev/zero",
    "/dev/random", "/dev/urandom",
    "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
    "/dev/rtc","/dev/hpet", "/dev/vfio/vfio",
    "/dev/vfio/1"
    ]
    clear_emulator_capabilities = 0

  5. 最後 vm 的 xml 長這樣

    $ virsh dumpxml win10
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    <domain type='kvm' id='53'>
    <name>win10</name>
    <uuid>1ac4335d-e696-442a-bf9b-c75c455377e8</uuid>
    <memory unit='KiB'>8388608</memory>
    <currentMemory unit='KiB'>8388608</currentMemory>
    <vcpu placement='static'>8</vcpu>
    <resource>
    <partition>/machine</partition>
    </resource>
    <os>
    <type arch='x86_64' machine='pc-i440fx-xenial'>hvm</type>
    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
    <nvram>/var/lib/libvirt/qemu/nvram/win10_VARS.fd</nvram>
    </os>
    <features>
    <acpi/>
    <apic/>
    <hyperv>
    <relaxed state='on'/>
    <vapic state='on'/>
    <spinlocks state='on' retries='8191'/>
    </hyperv>
    </features>
    <cpu mode='host-passthrough'>
    <topology sockets='1' cores='4' threads='2'/>
    </cpu>
    <clock offset='localtime'>
    <timer name='hypervclock' present='yes'/>
    </clock>
    <on_poweroff>destroy</on_poweroff>
    <on_reboot>restart</on_reboot>
    <on_crash>restart</on_crash>
    <pm>
    <suspend-to-mem enabled='no'/>
    <suspend-to-disk enabled='no'/>
    </pm>
    <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='file' device='disk'>
    <driver name='qemu' type='raw' cache='writeback'/>
    <source file='/var/vm/win10.img'/>
    <backingStore/>
    <target dev='vda' bus='virtio'/>
    <boot order='2'/>
    <alias name='virtio-disk0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
    <driver name='qemu' type='raw'/>
    <source file='/var/vm/iso/virtio-win-0.1.132.iso'/>
    <backingStore/>
    <target dev='hdc' bus='ide'/>
    <readonly/>
    <alias name='ide0-1-0'/>
    <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>
    <controller type='usb' index='0' model='ich9-ehci1'>
    <alias name='usb'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x7'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci1'>
    <alias name='usb'/>
    <master startport='0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0' multifunction='on'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci2'>
    <alias name='usb'/>
    <master startport='2'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x1'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci3'>
    <alias name='usb'/>
    <master startport='4'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'>
    <alias name='pci.0'/>
    </controller>
    <controller type='ide' index='0'>
    <alias name='ide'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <controller type='scsi' index='0' model='virtio-scsi'>
    <alias name='scsi0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </controller>
    <interface type='direct'>
    <mac address='52:54:00:92:0a:af'/>
    <source dev='enp0s31f6' mode='bridge'/>
    <target dev='macvtap0'/>
    <model type='virtio'/>
    <alias name='net0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <sound model='ich6'>
    <alias name='sound0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </sound>
    <hostdev mode='subsystem' type='pci' managed='yes'>
    <driver name='vfio'/>
    <source>
    <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
    </source>
    <alias name='hostdev0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </hostdev>
    <hostdev mode='subsystem' type='pci' managed='yes'>
    <driver name='vfio'/>
    <source>
    <address domain='0x0000' bus='0x01' slot='0x00' function='0x1'/>
    </source>
    <alias name='hostdev1'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </hostdev>
    <memballoon model='virtio'>
    <alias name='balloon0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </memballoon>
    </devices>
    <seclabel type='dynamic' model='apparmor' relabel='yes'>
    <label>libvirt-1ac4335d-e696-442a-bf9b-c75c455377e8</label>
    <imagelabel>libvirt-1ac4335d-e696-442a-bf9b-c75c455377e8</imagelabel>
    </seclabel>
    </domain>

幾個步驟可以驗證一下

  1. lspci -nnk 看一下顯卡使用的 driver 是不是 vfio-pci

    1
    Kernel driver in use: vfio-pci

  2. 用 top 看一下 CPU loading 發生問題時 不是 100% 不然就是 0.x%

最後是我用 Performance Test 跑的測試結果 我抓了幾台同樣用 RX 480 的 i7 機器來比較 這效能真是剛剛的 沒話說

參考文件

  1. PCI passthrough via OVMF
  2. VFIO tips and tricks
  3. KVM VGA-Passthrough using the new vfio-vga support in kernel =>3.9
  4. The vfio-users Archives