Изолировать одно устройство в отдельную группу IOMMU для сквозного подключения PCI?

Изолировать одно устройство в отдельную группу IOMMU для сквозного подключения PCI?

У меня есть следующие группы и устройства 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поместив его в отдельную группу, в которой не было бы других устройств.

Как можно изолировать одно устройство в отдельную группу IOMMU для сквозного подключения PCI к виртуальной машине KVM?

решение1

Я знаю, что это старый вопрос, но недавно мне пришлось попытаться в этом разобраться.

Правило большого пальца с IOMMU заключается в том, что ядро ​​будет определять сопоставления для вас. Когда ядро ​​загружается, оно будет искать, какие устройства могут быть сопоставлены с виртуальной картой ввода-вывода (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 году, но, судя по всему, с более свежими ядрами это может быть намного проще.

Для тех, у кого возникли проблемы, я хотел пропустить NIC на 4-портовой карте Broadcom BCM5709 NetXtreme II Gigabit Ethernet, которая была подключена к HP Z600. Я уже отключил всю виртуализацию, VT-d и т. п. в BIOS.

Проблема заключалась в том, что если я подключался к одной сетевой карте на 4-портовом порту, то хосту не было доступно ничего в группе 12, включая внутреннюю сетевую карту, которую я использовал для подключения к ней.


Это полезный раздел, дающий некоторые основы редактирования командной строки ядра. https://pve.proxmox.com/pve-docs/chapter-sysadmin.html#sysboot_edit_kernel_cmdline

Жратва

Командную строку ядра необходимо поместить в переменную GRUB_CMDLINE_LINUX_DEFAULTв файле /etc/default/grub. Запуск update-grubдобавляет ее содержимое ко всем записям linux в /boot/grub/grub.cfg.

Systemd-загрузка

Командную строку ядра необходимо поместить в одну строку в /etc/kernel/cmdline. Чтобы применить изменения, запустите proxmox-boot-tool refresh[не уверен, что будет использоваться без Proxmox], что установит ее в качестве строки параметров для всех файлов конфигурации в loader/entries/proxmox-*.conf.


Затем на этой странице приведены некоторые подробности о PCI Passthrough, в первую очередь ориентированные на Proxmox, но принцип должен быть тем же: 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"


Я включил базовую функцию IOMMUGRUB_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)

Я удалил все, кроме группы, которая меня интересует, Group 12. Вы можете видеть 4 порта NIC, но также и другой NIC, встроенный. К сожалению, если я прохожу через один NIC, то ничто в Group 12 не доступно хосту.


Я нашел работающий механизм, который разделяет сетевую карту на две части, используя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-портовую сетевую карту на 2 пары, и ни одна из них не находится в группе с встроенной сетевой картой. Я подозреваю, что каждая пара находится на той же шине (извините за терминологию) на карте, что и каждая другая, так что это, вероятно, наименьшее разделение, которое я смог получить (я пробовал другие механизмы, например, изолируя один или несколько мостов, как описано в видео, но они были хуже, чем выше).

Надеюсь, это будет полезно тем, у кого возникла та же проблема.

Связанный контент