Isolar um único dispositivo em um grupo IOMMU separado para passagem PCI?

Isolar um único dispositivo em um grupo IOMMU separado para passagem PCI?

Tenho abaixo grupos e dispositivos 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

Gostaria de isolar esse dispositivo específico /sys/kernel/iommu_groups/7/devices/0000:01:00.0em seu próprio grupo, sem outros dispositivos no mesmo grupo.

Como podemos isolar um único dispositivo em um grupo IOMMU separado para passagem PCI para máquina virtual KVM?

Responder1

Eu sei que esta é uma questão antiga, mas tive que tentar descobrir isso recentemente.

A regra geral do IOMMU é que o kernel descobrirá os mapeamentos para você. Quando o kernel inicializar, ele procurará quais dispositivos podem mapear para um mapa virtual de E/S (IOVA). Se os dispositivos tiverem o mesmo IOVA eles acabarão no mesmo grupo. Isto é feito para garantir que cada grupo tenha dispositivos que possam realmente ser endereçados e conversados ​​separadamente.

Existem algumas soluções. A primeira é que você pode tentar mover a placa para outra posição na placa-mãe. Se for uma placa PCI e não uma placa PCIe, provavelmente você está sem sorte, pois todas as portas PCI provavelmente estão mapeadas para a mesma ponte PCIe e, portanto, compartilharão o mesmo IOVA.

Se você realmente ainda precisa fazer isso, você pode pegar todos os dispositivos que estão no mesmo grupo e atribuí-los ao vfio-pci e depois fazer as atribuições para onde os dispositivos precisam ir.

Na minha máquina, por exemplo, o grupo 13 tem vários dispositivos, incluindo uma placa de vídeo extra (18:00). Aqui está minha saída desse diretório:

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

Como você pode ver, o diretório é um monte de links. Aqui está a cadeia de como as coisas estão conectadas:

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)

Para mim, todos esses dispositivos estão na mesma ponte, minha placa de vídeo extra, controlador RAID, etc.

Mas você pode

Você precisará aplicar ohttps://queuecumber.gitlab.io/linux-acs-override/(Patch ACS Override Kernel) Isso permitirá que você use parâmetros de linha de comando para expor partes de grupos em seus próprios grupos. Depois de instalar o patch, você pode configurar os parâmetros de linha de comando do kernel que deseja:

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

A partir daqui, você poderá fazer com que o dispositivo esteja em seu próprio grupo e você deverá partir para as corridas. Existem problemas com este método:

Aqui estão alguns bons links:

Responder2

Eu sei que a pergunta original é de 2019, mas pelo que parece, pode ser muito mais fácil com kernels mais recentes.

Para quem tiver algum problema, eu gostaria de passar por uma NIC em uma placa Gigabit Ethernet Broadcom BCM5709 de 4 portas NetXtreme II, que estava conectada a um HP Z600. Eu já tinha ativado toda virtualização, VT-d e similares na BIOS.

Meu problema era que, se eu passasse por uma NIC nas 4 portas, nada no Grupo 12 ficaria acessível ao host, incluindo a NIC interna que eu estava usando para conectar-me a ele.


Esta é uma seção útil para fornecer algumas noções básicas sobre como editar a linha de comando do Kernel https://pve.proxmox.com/pve-docs/chapter-sysadmin.html#sysboot_edit_kernel_cmdline

Comida

A linha de comando do kernel precisa ser colocada na variável GRUB_CMDLINE_LINUX_DEFAULTdo arquivo /etc/default/grub. A execução update-grubanexa seu conteúdo a todas as entradas do Linux em /boot/grub/grub.cfg.

Inicialização do Systemd

A linha de comando do kernel precisa ser colocada como uma linha no arquivo /etc/kernel/cmdline. Para aplicar suas alterações, execute proxmox-boot-tool refresh[não tenho certeza do que seria usado sem o Proxmox], que o define como a linha de opção para todos os arquivos de configuração em loader/entries/proxmox-*.conf.


Então, esta página fornece alguns detalhes sobre o PCI Passthrough, focado principalmente no Proxmox, mas o princípio ainda deve ser o mesmo: https://pve.proxmox.com/wiki/PCI_Passthrough


ESSE VÍDEO ME AJUDOU MUITO!e foi muito útil e completo para orientar você durante o processo. É para uma implementação específica, mas tudo mostrado pode ser realizado usando as informações acima e abaixo

https://www.youtube.com/watch?v=qQiMMeVNw-o&ab_channel=SpaceinvaderOne


Finalmente, não me lembro de onde o tirei, mas este é um comando realmente útil para identificar todos os grupos IOMMU para todos os dispositivos (executados como 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;

Para mim, originalmente comecei comGRUB_CMDLINE_LINUX_DEFAULT="quiet"


Habilitei o IOMMU básicoGRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on"

Isso me deu:

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)

Removi tudo, exceto o grupo no qual estou interessado, Grupo 12. Você pode ver as 4 portas da NIC, mas também outra NIC, a onboard. Infelizmente, se eu passar por uma NIC, nada no Grupo 12 ficará acessível ao host.


Encontrei um mecanismo funcional que divide a NIC em duas, usandoGRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on pcie_acs_override=downstream"

Isso me deu

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)

Você pode ver que a NIC de 4 portas está dividida em 2 pares e nenhuma delas está em um grupo com a NIC integrada. Suspeito que cada par esteja no mesmo barramento (desculpe a terminologia) na placa, então essa é provavelmente a menor divisão que consegui (tentei outros mecanismos, por exemplo, isolar uma ou mais pontes conforme descrito no vídeo, mas eles eram piores que os anteriores).

Espero que isso possa ser útil para alguém que tenha o mesmo problema.

informação relacionada