KVM/Xenであれこれ遊んだ記録を書いていきます
CPU:Intel Xeon-E3 1245v2 (core i7 3770相当)
GPU:Intel HD 4000P / AMD RADEON HD7750 / nVidia Geforce 750Tiの3GPU構成
M/B:Asrock Z77 extreme4
openSUSE tumbleweed x86-64
kernel 4.11.0
*(Kernel 4.8以上じゃないとigpu passthroughが出来ないのでLeap 42.3がkernel 4.9LTSベースになったらLeapに戻すかも)
qemu-kvm 2.8
*Leap 42.2はまだqemuが2.7
libvirt 3.3.0
普通にtumbleweedをインストール。一旦はxfceデスクトップで(ssh -Xで外からX端末でssh接続してvirt-manager動かしたいからX11関係を一旦一式入れてしまう)
最初のインストール時点ではdGPUを入れずにiGPUだけでインストールした方が無難。特にnouveauドライバはマルチGPUだと色々悪さする
YASTから一発でlibvirt関連とブリッジ設定まで済んでしまうので割愛
ここで一度普通にパススルーしないゲストがちゃんと動くか確認
YAST>サービスマネージャからランレベル3(マルチユーザー)に変更
YAST>ブートローダからカーネルパラメータにnomodeset追加、ついでにintel_iommu=onも追加(AMDの場合はそのように)
必ずランレベル変更を先にやること(nomodesetしつつX立ち上げるとハマる)
/etc/sysconfig/kernelにvfio関連のドライバを列挙してinitrd中にvfio関連ドライバを入れておく
このへんディストリ的に行儀の良いやり方は変わるが、SUSEとRHではドライバ先読み設定はここに書くのが行儀良いとされる
他のディストリの方法で行ってもたまたま大丈夫な場合もあるが、バージョン変化に追従できないことがある
逆もしかりなのでubuntuやdebian系で試す人は公式doc読むなりでディストリの流儀に従うことを推奨
# echo "INITRD_MODULES=\"pci_stub vfio vfio_iommu_type1 vfio_pci vfio_virqfd kvm kvm_intel\"" >> /etc/sysconfig/kernel
/etc/modprobe.d/以下に適当な俺々confを作ってパススルー対象のPCI device IDを列挙する IDはlspci -nで取る(例に列挙してるIDは当然うちの環境なので実環境に合わせること)
# echo "options vfio-pci ids=8086:016a,8086:1e20,1002:683f,1002:aab0,10de:1380,10de:0fbc" >> /etc/modprobe.d/99-mygpu.conf
本来nomodeset入れてランレベル3で起動すればカーネルはGPUもサウンドも掴まないはずではあるけど一応
# echo -e "\nblacklist i915\nblacklist snd_hda_intel\nblacklist radeon\nblacklist amdgpu\nblacklist nouveau" >> /etc/modprobe.d/50-blacklist.conf
# mkinitrd
LGA115x系core i/Xeon-E3とかRyzen7なんかのようにgpu用のPCIレーンが16本しかないM/Bでdgpuを二つ以上パススルーしたい時にはpached kernelが必要
(いわゆるacs override patch)
kernel 4.1~4.10であればarchのAURからパッチを拾ってくれば使えるはず
kernel 4.11用は自分で作ったのを貼っておく
openSUSE tumbleweed用で良ければビルド済カーネル作ったのでどうぞ
https://build.opensuse.org/project/show/home:zgock:kvm-vfio
kernel 4.8&qemu 2.7でやっとこigpuパススルーがどうにか動き始めた感じ
Seabios/i440fxでないと起動しないのでOVMF/Q35は使わないこと
Linux Gusetならわりと問題なく動く
Windows Guestは素の状態のkernelではドライバ入れた時点でBSOD。(intel driverがunsafe割り込みを吐いたり、qemuが対応してない拡張命令を吐いたりする) 対策としてKVMにオプションを追加する
# echo "options kvm allow_unsafe_assigned_interrupts=1 ignore_msrs=1 halt_poll_ns=0" >> /etc/modprobe.d/99-kvm.conf
ただまだゲームベンチでフルスクリーンにすると落ちたりとかが発生したりまだまだ未熟性
UEFI未対応の世代(RADEON R7系以前のHDxxxx系列)でもSeabiosでパススルーできるが、libvirtで使う場合ちょっと注意が必要
virt-managerで単純にPCI Deviceとして追加しただけではBIOS時点で固まる
virsh editでvgaのhostdevに対してx-vgaオプションを与える必要があるが、デフォルトのlibvirtのnamespaceでは付与できないため、domainのnamespaceを明示的に与えてqemu:commandlineを有効にする
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
xml末尾にqemu:commandlineタグを入れてvgaに対応するhostdevにx-vgaオプションを付ける
<qemu:commandline>
<qemu:arg value='-set'/>
<qemu:arg value='device.hostdev0.x-vga=on'/>
</qemu:commandline>
</domain>
OVMF対応世代以降ならOVMFで良いが、x-vgaオプションは付けておいた方が無難
ただし、RADEONは特定の世代のチップ(R9-3xx系あたりに多い)のUEFIファームにバグがあってシャットダウン時に問題が出るとかあるので、特に理由がない限りはseabiosでゲスト起動するのを推奨
Windows7はsecure boot未対応なのでOVMFで起動する場合は必ずOVMFのセキュアブートを切っておくこと
Seabiosでは基本的に動かない(geforce系のファームにガードがかかっている)。OVMF環境では普通に動くが、Windowsゲスト及びLinuxでもnvidiaドライバでは仮想化カーネルであることを検知するとドライバが落ちる問題(Code 43)問題があるため設定にひと工夫が必要
(要するにUEFI時代になってファームでガードかけるのが難しくなったのでドライバーでガードかけるようになったと(ここに中指画像が入ります))
具体的にはlibvirtのfeatures句でkvmをドライバに検知させないようにする
<kvm>
<hidden state='on'/>
</kvm>
</features>
openSUSE Leap 42.1 x86-64 kernel 4.1.xx-xen xen 4.5