CentOS7 KVM で PCIパススルー、USBパススルー

BIOSでIOMMU拡張を有効化

「Intel VT-d」「I/O Virtualization Technology」などの名前の設定項目を有効にする。

LinuxカーネルでIOMMU機能を有効化

# vi /etc/default/grub
GRUB_CMDLINE_LINUX の末尾に「intel_iommu=on」もしくは「amd_iommu=on」を追加

# grub2-mkconfig -o /boot/grub2/grub.cfg

# reboot

# dmesg | grep -e DMAR -e IOMMU
[    0.000000] Intel-IOMMU: enabled

・IOMMUグループの確認

# vi iommu.sh
#!/bin/bash
shopt -s nullglob
for d in /sys/kernel/iommu_groups/*/devices/*; do 
    n=${d#*/iommu_groups/*}; n=${n%%/*}
    printf 'IOMMU Group %s ' "$n"
    lspci -nns "${d##*/}"
done;

# sh iommu.sh
IOMMU Group 1 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device
IOMMU Group 1 01:00.1 Audio device [0403]: NVIDIA Corporation Device
IOMMU Group 1 02:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
...

PCIパススルーはIOMMUグループ単位でしかできない。
上記例ではグループ1にGPUとNICが属しているため、パススルーする場合はGPUとNICを両方同時にパススルーする必要がある。

PCIパススルーするデバイスを特定

# lspci
01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Cedar [Radeon HD 5000/6000/7350/8350 Series]
01:00.1 Audio device: Advanced Micro Devices, Inc. [AMD/ATI] Cedar HDMI Audio [Radeon HD 5400/6300 Series]

# lspci -n
01:00.0 0300: 1002:68f9
01:00.1 0403: 1002:aa68

GPUをパススルーする場合下記を設定

・ホストにドライバが読み込まれないように grub に nomodeset を追加

# vi /etc/default/grub 
GRUB_CMDLINE_LINUX="vconsole.keymap=us crashkernel=auto vconsole.font=latarcyrheb-sun16 intel_iommu=on nomodeset"

# grub2-mkconfig -o /boot/grub2/grub.cfg

・ドライバをブラックリストに追加

# lspci -v -d 1002:68f9 | grep Kernel
	Kernel driver in use: radeon

# lspci -v -d 1002:aa68 | grep Kernel
	Kernel driver in use: snd_hda_intel

# lsmod | grep radeon
drm                   297829  2 ttm,drm_kms_helper,radeon

# vi /etc/modprobe.d/blacklist.conf
blacklist drm
blacklist radeon
blacklist snd-hda-intel

# reboot

NVIDIAGPUWindowsにパススルーする場合は下記の対応が必要。
http://d.hatena.ne.jp/kt_hiro/20170716/1500199181


仮想マシンの設定でPCIバイスを追加

# virsh edit vm1
<hostdev mode='subsystem' type='pci' managed='yes'>
  <source>
    <address domain='0' bus='1' slot='0' function='0'/>
  </source>
</hostdev>

※lspci で追加したいデバイスが 01:00.0 の場合、bus='1' slot='0' function='0' を指定する。

仮想マシンの設定でUSBデバイスを追加

# lsusb
Bus 002 Device 004: ID 3275:0080 VidzMedia Pte Ltd
※ 3275 が vendor id、0080 が product id

# virsh edit vm1
<hostdev mode=’subsystem’ type=’usb’>
  <source startupPolicy=’optional’>
    <vendor id=’0x3275’/>
    <product id=’0x0080’/>
  </source>
</hostdev>

仮想マシンの設定でUSBホストコントローラを追加
※サーバのフロントUSBポート、リアUSBポートをまとめて仮想マシンにパススルーすることができる

# lspci
00:1a.0 USB controller: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (rev 04)
00:1d.0 USB controller: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (rev 04)
※上記の例では 00:1a.0 がリアUSB、00:1d.0 がフロントUSB

# virsh edit vm1
<hostdev mode='subsystem' type='pci' managed='yes'>
  <driver name='vfio'/>
    <source>
      <address domain='0' bus='0' slot='1d' function='0'/>
    </source>
</hostdev>

※フロントUSB(00:1d.0)をパススルーする場合

単一仮想マシンGPUパススルーして画面出力し、USBパススルーしてマウス・キーボードを接続すれば、仮想マシンをローカルPCのように使用することができる。