
以下の IOMMU グループとデバイスがあります。
$ for a in /sys/kernel/iommu_groups/*; do find $a -type l; done | sort --version-sort
/sys/kernel/iommu_groups/0/devices/0000:00:00.0
/sys/kernel/iommu_groups/1/devices/0000:00:02.0
/sys/kernel/iommu_groups/2/devices/0000:00:04.0
/sys/kernel/iommu_groups/3/devices/0000:00:14.0
/sys/kernel/iommu_groups/3/devices/0000:00:14.2
/sys/kernel/iommu_groups/4/devices/0000:00:15.0
/sys/kernel/iommu_groups/4/devices/0000:00:15.1
/sys/kernel/iommu_groups/5/devices/0000:00:16.0
/sys/kernel/iommu_groups/6/devices/0000:00:17.0
/sys/kernel/iommu_groups/7/devices/0000:00:1c.0
/sys/kernel/iommu_groups/7/devices/0000:00:1c.7
/sys/kernel/iommu_groups/7/devices/0000:01:00.0
/sys/kernel/iommu_groups/7/devices/0000:02:00.0
/sys/kernel/iommu_groups/8/devices/0000:00:1f.0
/sys/kernel/iommu_groups/8/devices/0000:00:1f.2
/sys/kernel/iommu_groups/8/devices/0000:00:1f.3
/sys/kernel/iommu_groups/8/devices/0000:00:1f.4
/sys/kernel/iommu_groups/7/devices/0000:01:00.0
特定のデバイスを、同じグループ内に他のデバイスが存在しない独自のグループに分離したいと思います。
KVM 仮想マシンの PCI パススルー用に、単一のデバイスを別の IOMMU グループに分離するにはどうすればよいですか?
答え1
これは古い質問だとはわかっていますが、最近これを理解しようとしなければなりませんでした。
IOMMU の原則は、カーネルがマッピングを決定することです。カーネルが起動すると、どのデバイスが I/O 仮想マップ (IOVA) にマップできるかを調べます。デバイスが同じ IOVA を持つ場合、それらは同じグループになります。これは、各グループに、実際に個別にアドレス指定して通信できるデバイスがあることを保証するために行われます。
解決策はいくつかあります。まず、カードをマザーボード上の別の位置に移動してみることです。PCI カードであって PCIe カードではない場合、すべての PCI ポートが同じ PCIe ブリッジにマップされている可能性があり、同じ IOVA を共有することになるため、おそらくうまくいかないでしょう。
それでもどうしても必要な場合は、同じグループ内のすべてのデバイスを取得して、それらをすべて vfio-pci に割り当て、その後、デバイスを配置する必要がある場所に割り当てを行うことができます。
たとえば、私のマシンでは、グループ 13 には追加のビデオ カード (18:00) を含む多数のデバイスがあります。そのディレクトリからの出力は次のとおりです。
root@rwl01:/sys/kernel/iommu_groups/13/devices# ll
total 0
drwxr-xr-x 2 root root 0 Feb 15 15:43 .
drwxr-xr-x 3 root root 0 Feb 15 15:43 ..
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:03:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:03:00.1 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.1
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:03:00.2 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:16:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:00.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:16:01.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:01.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:16:02.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:02.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:16:03.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:03.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:16:04.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:04.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:16:08.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:08.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:17:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:00.0/0000:17:00.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:18:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:01.0/0000:18:00.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:18:00.1 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:01.0/0000:18:00.1
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:19:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:02.0/0000:19:00.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:1a:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:03.0/0000:1a:00.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:1b:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:04.0/0000:1b:00.0
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:1b:00.1 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:04.0/0000:1b:00.1
lrwxrwxrwx 1 root root 0 Feb 15 15:43 0000:1c:00.0 -> ../../../../devices/pci0000:00/0000:00:01.3/0000:03:00.2/0000:16:08.0/0000:1c:00.0
ご覧のとおり、ディレクトリはリンクの集まりです。以下は、物事がどのようにつながっているかを示すチェーンです。
root@rwl01:/sys/kernel/iommu_groups/13/devices# lspci | grep -E '00:01.3|03:00.2|16:01.0'
00:01.3 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 1453
03:00.2 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 43b0 (rev 02)
16:01.0 PCI bridge: Advanced Micro Devices, Inc. [AMD] Device 43b4 (rev 02)
私の場合、追加のビデオ カード、RAID コントローラーなど、これらすべてのデバイスは同じブリッジ上にあります。これらを簡単に分離することはできません。
でも君ならできる
申請する必要があります詳しくは、https://queuecumber.gitlab.io/linux-acs-override/ をご覧ください。(ACS Override Kernel パッチ) これにより、コマンド ライン パラメータを使用して、グループの一部を独自のグループとして公開できるようになります。パッチをインストールしたら、カーネル コマンド ライン パラメータを次のように設定できます。
pcie_acs_override =
[PCIE] Override missing PCIe ACS support for:
downstream
All downstream ports - full ACS capabilties
multifunction
All multifunction devices - multifunction ACS subset
id:nnnn:nnnn
Specfic device - full ACS capabilities
Specified as vid:did (vendor/device ID) in hex
ここから、デバイスを独自のグループにまとめることができ、準備は完了です。この方法には問題があります。
ここにいくつかの良いリンクがあります:
答え2
元の質問は 2019 年のものだとわかっていますが、聞くところによると、最近のカーネルではずっと簡単になるかもしれません。
問題を抱えている方のために、私は HP Z600 に接続された Broadcom BCM5709 4 ポート NetXtreme II ギガビット イーサネット カードの NIC をパススルーしたいと考えていました。BIOS ですべての仮想化、VT-d などを有効にしていました。
私の問題は、4 ポートの 1 つの NIC を通過すると、接続に使用していた内部 NIC を含め、グループ 12 内の何もホストにアクセスできないということでした。
これはカーネルコマンドラインを編集する基本的な方法を説明する便利なセクションです。 https://pve.proxmox.com/pve-docs/chapter-sysadmin.html#sysboot_edit_kernel_cmdline
グラブ
GRUB_CMDLINE_LINUX_DEFAULT
カーネル コマンドラインは、ファイル内の変数に配置する必要があります/etc/default/grub
。 を実行すると、update-grub
その内容が /boot/grub/grub.cfg 内のすべての Linux エントリに追加されます。
Systemd ブート
カーネル コマンドラインは、 に 1 行として配置する必要があります/etc/kernel/cmdline
。変更を適用するには、proxmox-boot-tool refresh
[Proxmox なしで何が使用されるかは不明] を実行します。これにより、loader/entries/proxmox-*.conf 内のすべての構成ファイルのオプション行として設定されます。
次に、このページでは、主に Proxmox に焦点を当てた PCI パススルーに関する詳細がいくつか示されていますが、原則は同じです。 https://pve.proxmox.com/wiki/PCI_Passthrough
このビデオが私に一番役立ちました!プロセスを順を追って説明してくれるので、とても役立ち、徹底しています。これは特定の実装のためのものですが、示されていることはすべて、上記と下記の情報を使用して実現できます。
https://www.youtube.com/watch?v=qQiMMeVNw-o&ab_channel=SpaceinvaderOne
最後に、どこから入手したかは覚えていませんが、これはすべてのデバイスのすべての IOMMU グループを識別するのに非常に便利なコマンドです (root として実行)。
for d in $(find /sys/kernel/iommu_groups/ -type l | sort -n -k5 -t/); do n=${d#*/iommu_groups/*}; n=${n%%/*}; printf 'IOMMU Group %s ' "$n"; lspci -nns "${d##*/}"; done;
私の場合は、最初はGRUB_CMDLINE_LINUX_DEFAULT="quiet"
基本的なIOMMUを有効にしましたGRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on"
これにより、次のことがわかりました。
IOMMU Group 12 00:1c.0 PCI bridge [0604]: Intel Corporation 82801JI (ICH10 Family) PCI Express Root Port 1 [8086:3a40]
IOMMU Group 12 00:1c.5 PCI bridge [0604]: Intel Corporation 82801JI (ICH10 Family) PCI Express Root Port 6 [8086:3a4a]
IOMMU Group 12 01:00.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme BCM5764M Gigabit Ethernet PCIe [14e4:1684] (rev 10)
IOMMU Group 12 1c:00.0 PCI bridge [0604]: Microsemi / PMC / IDT PES12T3G2 PCI Express Gen2 Switch [111d:8061] (rev 01)
IOMMU Group 12 1d:02.0 PCI bridge [0604]: Microsemi / PMC / IDT PES12T3G2 PCI Express Gen2 Switch [111d:8061] (rev 01)
IOMMU Group 12 1d:04.0 PCI bridge [0604]: Microsemi / PMC / IDT PES12T3G2 PCI Express Gen2 Switch [111d:8061] (rev 01)
IOMMU Group 12 1e:00.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
IOMMU Group 12 1e:00.1 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
IOMMU Group 12 1f:00.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
IOMMU Group 12 1f:00.1 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
関心のあるグループ 12 以外はすべて削除しました。NIC の 4 つのポートだけでなく、オンボードの別の NIC も表示されています。残念ながら、1 つの NIC を通過すると、グループ 12 のどのポートもホストからアクセスできなくなります。
私は、NICを2つに分割する実用的なメカニズムを見つけました。GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on pcie_acs_override=downstream"
これにより、
IOMMU Group 12 00:1c.0 PCI bridge [0604]: Intel Corporation 82801JI (ICH10 Family) PCI Express Root Port 1 [8086:3a40]
IOMMU Group 13 00:1c.5 PCI bridge [0604]: Intel Corporation 82801JI (ICH10 Family) PCI Express Root Port 6 [8086:3a4a]
IOMMU Group 18 1c:00.0 PCI bridge [0604]: Microsemi / PMC / IDT PES12T3G2 PCI Express Gen2 Switch [111d:8061] (rev 01)
IOMMU Group 19 1d:02.0 PCI bridge [0604]: Microsemi / PMC / IDT PES12T3G2 PCI Express Gen2 Switch [111d:8061] (rev 01)
IOMMU Group 20 1d:04.0 PCI bridge [0604]: Microsemi / PMC / IDT PES12T3G2 PCI Express Gen2 Switch [111d:8061] (rev 01)
IOMMU Group 21 1e:00.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
IOMMU Group 21 1e:00.1 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
IOMMU Group 22 1f:00.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
IOMMU Group 22 1f:00.1 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet [14e4:1639] (rev 20)
IOMMU Group 23 01:00.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme BCM5764M Gigabit Ethernet PCIe [14e4:1684] (rev 10)
4 ポート NIC が 2 つのペアに分割されており、どちらもオンボード NIC と同じグループではないことがわかります。各ペアはカード上で互いに同じバス (用語はご容赦ください) 上にあると思われるため、おそらくこれが私が実現できる最小の分割です (ビデオで説明されているように 1 つ以上のブリッジを分離するなど、他のメカニズムも試しましたが、上記よりも悪い結果でした)。
同じ問題を抱えている人にとって、これが少しでも役に立つことを願っています。