Ideal Reality

興味の赴くままに

QEMU(KVM)でNVMe SSDをPCIパススルーして使用する

KVMでPCIパススルーを行うには、デバイスの制御をデバイスドライバからvfio-pciに切り替えなきゃいけないけど、検索して出てくる方法は大抵デバイスドライバを無効化するとか、ベンダーID/デバイスIDで使用するドライバを上書きする等対象範囲が広すぎて、同じデバイスを2つ積んでて片側だけKVMに割り当てるといったことができない。

OVMF による PCI パススルー#ゲストとホストで同じ GPU を使う

ここにあるような起動時にスクリプトを実行するような方法もあまりスマートじゃないのでやりたくない。

それこそ、virt-managerだと起動時の作業がなくても、設定したデバイスだけ自動でvfio-pciに切り替えてくれるのに、QEMUを直接叩く場合はできないの?って思って調べたので、その方法をまとめます。

(おそらく今回の方法はNVMe SSD以外のGPU・NIC・USBコントローラー等普通のPCIeデバイスでも使えますが、動作検証を行なってないのであくまでタイトルはNVMe SSDだけにしてます。また、当方Arch Linuxを使ってるので、それ以外のLinuxディストリビューションでは適宜読み替えが必要かもしれません。)

Contents
スポンサーリンク

デバイスを使用中の場合は止める

SSDだったらマウントされているとかですね。アンマウントしてデバイスにアクセスしているプロセスがいない状態にしてください。

デバイスの情報を得る

とりあえず以下のコマンドを打ってください。

$ lspci -D -v

そうすると、積んでるPCIeデバイスの一覧が出てきます。その中からKVMに割り当てたいデバイスを探してください。僕の場合これですね

0000:01:00.0 Non-Volatile memory controller: Intel Corporation SSD Pro 7600p/760p/E 6100p Series (rev 03) (prog-if 02 [NVM Express])
	Subsystem: Intel Corporation SSD Pro 7600p/760p/E 6100p Series [NVM Express]
	Flags: bus master, fast devsel, latency 0, IRQ 44, NUMA node 0, IOMMU group 13
	Memory at fe900000 (64-bit, non-prefetchable) [size=16K]
	Capabilities: <access denied>
	Kernel driver in use: nvme

必要な情報は先頭と末尾にあるやつです。デバイスの識別番号が0000:01:00.0で、nvmeドライバによって制御されてます。

スポンサーリンク

デバイスの制御をvfio-pciに切り替える

ここら辺カーネルモジュールをいじるのでスーパーユーザーに入っての作業になります。

# modprobe vfio-pci
# echo -n "0000:01:00.0" > /sys/bus/pci/drivers/nvme/unbind
# echo vfio-pci > /sys/bus/pci/devices/0000:01:00.0/driver_override
# echo 0000:01:00.0 > /sys/bus/pci/drivers_probe

まず1つ目のコマンド、これはvfio-pciカーネルモジュールを読み込んでます。起動後に一度実行すればあとは不要ですし、起動時の設定で自動読み込みするようにしていれば不要です。

2つ目のコマンドは0000:01:00.0のデバイスをnvmeドライバから切り離しています。"0000:01:00.0"の部分と/sys/bus/pci/drivers/nvme/unbind内のnvmeは各自自分のデバイスに合わせて変えてください。

3つ目のコマンドは0000:01:00.0で使用するドライバにvfio-pciを指定しています。

そして、4つ目のコマンドで0000:01:00.0のドライバを再読み込みさせると、無事デバイスの制御がvfio-pciに切り替わります。

試しに、再度lspci -D -vで確認してみましょう。

0000:01:00.0 Non-Volatile memory controller: Intel Corporation SSD Pro 7600p/760p/E 6100p Series (rev 03) (prog-if 02 [NVM Express])
	Subsystem: Intel Corporation SSD Pro 7600p/760p/E 6100p Series [NVM Express]
	Flags: bus master, fast devsel, latency 0, IRQ 44, NUMA node 0, IOMMU group 13
	Memory at fe900000 (64-bit, non-prefetchable) [size=16K]
	Capabilities: <access denied>
	Kernel driver in use: vfio-pci

切り替わってることが確認できればOKです。

QEMU(KVM)の起動

これでKVMからPCIeデバイスを使用する準備は整ったので、あとはパラメータにパススルーを指定して起動しましょう。

$ sudo qemu-system-x86_64 \
-cpu host -smp 8 --enable-kvm \
-m 16G \
-bios efi/OVMF.fd \
-device vfio-pci,host=0000:01:00.0

これは僕が普段使ってるコマンドから起動に必要なものだけを抜き出したコマンドです。

今回大事なのは-device vfio-pci,host=0000:01:00.0のオプション。これでPCIパススルーを指定します。host=の値はデバイスの識別番号ですね。

-bios efi/OVMF.fdはQEMUでUEFIを使いたいときに必要なやつです。NVMeからの起動はBIOSじゃできないので。efi/OVMF.fdはUEFIのファームウェアを指定してください。主要なLinuxディストリビューションだとパッケージマネージャーで公式のレポジトリから取ってこれることが多いので、それを指定すればいいでしょう。自分はあまりそこらへん考えるのが面倒なので、以下で用意したのをいろいろな場所で使いまわしてます。

QEMU用のUEFIファームウェアをビルドする

QEMUはUEFI用のファームウェアを持っていないので、UEFI環境でのブートをしたかったら別途用意しなきゃいけないのですが、Intel用のファームウェアはLinuxのパッケージマネージャーのレポジト...

スポンサーリンク

コメント

投稿されたコメントはありません

名前

メールアドレス(任意)

コメント

関連する投稿

OVMFをビルドする

virt-manager(libvirt)で自分でビルドしたQEMUを使用する

NO IMAGE

Raspberry PiでKVMを動かす (旧版)

Raspberry PiでKVMを動かす

NO IMAGE

QEMUでブリッジネットワークを使用する