NVMe SSDは単にNVMeプロトコルに対応したPCIeデバイスなので、GPUなどと同様にPCI Passthroughの手段を用いてVMにデバイスごとパススルーすることができます。ほとんど手順としては同じなのですが、備忘録代わりに具体的な手順を書いておきます。
今回の作業はホスト側にDebian BookwormベースのProxmox VE 8.3.1を、ゲスト側にDebain 12 (Bookworm)を用いました。が、他のディストリビューション(Arch LinuxやFedoraなど)でも殆ど手順は変わらないはずです。
BIOS(UEFI)、カーネルの起動オプションの設定
まずBIOSの設定でVT-d(intel)やAMD-V(AMD)、IOMMUその他を有効にしておきます。今回はなんとなくでAbove 4G decoding(Resizable BAR)も有効にしましたが、これは特段影響しなさそうです。
次に、 /etc/default/grub
を編集して GRUB_CMDLINE_LINUX_DEFAULT
に intel_iommu=on iommu=pt
を追加します(前者はAMD環境では不要)。そうしたら update-grub
として設定を適用します。
dmesgを見て設定が適用されていることを確認します:
# dmesg | grep -e DMAR -e IOMMU [ 0.527449] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported [ 0.529504] perf/amd_iommu: Detected AMD IOMMU #0 (2 banks, 4 counters/bank).
カーネルモジュールの読み込み
必要なカーネルモジュールを起動時に読み込ませるため、 /etc/modules-load.d/
以下に適当なファイルを作成して以下を追加します(拡張子が.confでないといけないかもしれない(未検証)):
vfio vfio_iommu_type1 vfio_pci
そうしたら update-initramfs -u -k all
でinitramfsを再生成すると起動時に読み込まれるようになるはずです。念の為確認しておきましょう:
# lsmod | grep ^vfio vfio_pci 16384 1 vfio_pci_core 86016 1 vfio_pci vfio_iommu_type1 49152 1 vfio 65536 8 vfio_pci_core,vfio_iommu_type1,vfio_pci
カーネルモジュールの設定
ここがGPUのパススルーと違うところで、対象となるNVMe SSDに対してカーネルのnvmeドライバ ではなく 、vfioドライバにデバイスを初期化させる。そのために、nvme_coreより先にvfioをロードさせます。GPUではシステムに1枚しか刺さなかったり刺しても全部パススルーしたりするので気軽にblacklist nouveau
みたいなことができてしまいますが、それをnvmeに対して行うとおそらく別のnvmeデバイスも見えなくなってしまうので少し違う方法を取る必要があります。
# lspci -nn | grep -i non-volatile 01:00.0 Non-Volatile memory controller [0108]: Phison Electronics Corporation PS5019-E19 PCIe4 NVMe Controller (DRAM-less) [1987:5019] (rev 01)
ここでは 1987:5019
がデバイスIDです。現時点ではnvmeドライバが利用されているはずです。
# lspci -ks 01:00.0 01:00.0 Non-Volatile memory controller: Phison Electronics Corporation PS5019-E19 PCIe4 NVMe Controller (DRAM-less) (rev 01) Subsystem: Phison Electronics Corporation PS5019-E19 PCIe4 NVMe Controller (DRAM-less) Kernel driver in use: nvme Kernel modules: nvme
vfio-pciを代わりに使わせたいので、 /etc/modprobe.d/
以下に適当にファイルを作成して以下の内容を書き込みます(今回は nvme-passthrough.conf
としました)。以下の例ではデバイスIDを 1987:5019
としています(Phison E19のもの)が、手元のデバイスに合わせて書き換えられるべきです。なお、複数のデバイスを指定する場合は ids=xxxx:xxxx,yyyy:yyyy
とカンマで区切ります。
options vfio-pci ids=1987:5019 softdep nvme_core pre: vfio-pci
こう書けばPCI(e)のデバイス1987:5019に対してvfio-pciドライバを使用し、softdepでvfio-pciがnvme_coreより先に読み込まれるようになります。これで再起動すれば lsblk
などから当該NVMeデバイスが消えていて、 lspci -nnk
で出てくるKernel driver in useの項目がvfio-pciになっているはずです。(mkinitramfsの再生成と再起動が必要だったかもしれない)
# lspci -ks 01:00.0 01:00.0 Non-Volatile memory controller: Phison Electronics Corporation PS5019-E19 PCIe4 NVMe Controller (DRAM-less) (rev 01) Subsystem: Phison Electronics Corporation PS5019-E19 PCIe4 NVMe Controller (DRAM-less) Kernel driver in use: vfio-pci Kernel modules: nvme