× К оглавлению На главную Об авторе

   Дата и время публикации   :
   Дата и время модификации:

Использование и применение


1. Использование

Технологии виртуализации является предпочтительной благодаря постоянно возрастающему числу ядер центрального процессора. Перевод графических карт на виртуальной машине стало так же возможным с появлением исполнений графических процессоров (англ. Graphics Processing Unit, GPU) не использующих микропрограммный код, которые важны для игрового сегмента программного, но и пакетов программ с интенсивной обработкой графики подобно Adobe Photoshop и т.п.

В результате чего в ядре GNU/Linux появилась функция прямого доступа VM к графического процессору (англ. GPU passthrough) или проброс GPU. Это когда виртуальная машина действует так, как-будто она управляет графическим адаптером непосредственно и имеет возможность определять физически его наличие на шине PCI.

Примечание. Функция проброса GPU часто известна, как IOMMU несмотря на то, что это не совсем верно, поскольку последняя является аппаратной технологией, обеспечивающей по мимо данной функции еще и защиту от атак DMA или доступность 64-х разрядных адресов в пространства памяти к 32-м разрядным. В конечном счете аббревиатура IOMMU по англицки звучит как "input–output memory management unit", что переводится дословно как "ввод/вывод блока управления оперативной памяти". Как можно догадаться, по сути данный программный компонент отвечает за взаимодействие с блоком управления памятью (англ. memory management unit, MMU), который сопряжен с физической памятью через функциональное устройство прямого доступа к оперативной памяти ( англ.DMA-capable,direct-memory-access–capable) с шиной ввода/вывода. IOMMU приводит видимый устройством виртуальный адрес (англ. IO virtual address, IOVA) к физическому адресу. Другими словами, он транслирует или согласует IOVA с реальными физическими адресами. В идеале, каждое устройство имеет свое собственное адресной пространство IOVA и нет другого устройства, которое адреса из этого пространства разделяло. Но, на практике зачастую такой случай является редкостью. Более того, спецификация PCI-Express (PCIe) позволяет сопрягать и взаимодействовать непосредственно между собой подобные устройства, через так называемые одноранговые транзакции (англ. peer-to-peer transactions), тем самым избегая IOMMU. Безопасность обеспечивается там, где в наличии службы управления доступом к PCI (англ. PCI Access Control Services, ACS), потому что обмен одноразовыми транзакциями возможен только между двумя устройствами, центральным процессором и обслуживающим их набором чипсет.

Поэтому ниже разберем:

Например так, как это делали ранее во время создания системного раздела ESP.

2. Применение

2.1 Включение проброса GPU и ACS

Первым о чем позаботимся, чтобы IOMMU (в linux-сообществе отзывается как AMD-V) для процессора AMD была активна, как показано в дампе 2.1

Дамп 2.1


$ grep svm /proc/cpuinfo
...
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb hw_pstate sme ssbd sev ibpb vmmcall fsgsbase bmi1 avx2 smep bmi2 rdseed adx smap clflushopt sha_ni xsaveopt xsavec xgetbv1 xsaves clzero irperf xsaveerptr arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif overflow_recov succor smca
...

В случае, если на выходе ничего не будет обнаружено, то необходимо включить поддержку AMD-Vi в BIOS.

После чего проверить в сообщениях системного журнала, что IOMMU была включена, как показано в дампе 2.2

Дамп 2.2


sudo journalctl -p emerg..debug | grep 'IOMMU enabled'

В случае, если ничего подобного не было найдено, необходимо произвести её включения, как показано в дампе 2.3а и 2.3b

Для процессора AMD, показано в дампе 2.3а

Дамп 2.3а


GRUB_CMDLINE_LINUX="... iommu=pt amd_iommu=on pcie_acs_override=downstream,multifunction ..."

Для процессора Intel, показано в дампе 2.3b

Дамп 2.3b


GRUB_CMDLINE_LINUX="... iommu=pt intel_iommu=on pcie_acs_override=downstream,multifunction ..."

Примечания. Предлагаемое значение параметра 'pcie_acs_override=downstream,multifunction' предполагает отключение проверку ACS по топологии и предполагает изоляцию там где её может и не быть. Другими словами, если что-либо отвергает подобные проверки, тогда мы мы не получим никакой выгоды от них при первом обращении к устройствам, поэтому запрещая их не отключаем ACS. Взамен, предлагается просто выбрать 'pcie_acs_override=downstream' или наиболее предпочтительный вариант указать прямо ID устройств, например, которые могут не быть одноранговыми. Потому, для включения подпрограммы-вставки AСS можно указывать непосредственно ID устройств 'pcie_acs_override=id:nnnn:nnnn', как показано ниже.

...pcie_acs_override=id:1002:15d8,10de:1f91...

Где nnnn:nnnn для каждой графической карты указывается индивидуально и может быть получен командой 'lspci -nn | grep VGA' .

После внесения изменений в настройки GRUB, не забудьте обновить загрузчик системы таким же образом, как это делали во время его установки через использование команды UPDATE-GRUB(8) .

Так же, если amd_iommu=pt или intel_iommu=pt не сработает, тогда следует установить общий случай amd_iommu=on или intel_iommu=on, т.к. скорее всего установленная графическая карта проброс GPU не поддерживает.

После чего, обычно предлагается проверить стандартный набор настроек ядра для IOMMU, например как в menuconfig, показанный в дампе 2.4

Дамп 2.4

Device Drivers --->
  [*] IOMMU Hardware Support --->
            Generic IOMMU Pagetable Support ----
      [*]   AMD IOMMU support
      <*>     AMD IOMMU Version 2 driver
      [*]   Support for Intel IOMMU using DMA Remapping Devices
      [*]     Support for Shared Virtual Memory with Intel IOMMU
      [*]     Enable Intel DMA Remapping Devices by default
      [*]   Support for Interrupt Remapping

В результате все описанных действий на выходе, в системном журнале должны получить нечто подобное, как показано в дампе 2.5

Дамп 2.5

$sudo journalctl -p emerg..debug -b | grep "AMD-Vi\|Intel VT-d\|Virtualisation\|remapping"
дек 21 07:08:16 home kernel: AMD-Vi: Using IVHD type 0x40
дек 21 07:08:16 home kernel: AMD-Vi: device: 00:00.2 cap: 0040 seg: 0 flags: b0 info 0000
дек 21 07:08:16 home kernel: AMD-Vi:        mmio-addr: 00000000feb80000
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_SELECT_RANGE_START         devid: 00:01.0 flags: 00
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_RANGE_END                 devid: ff:1f.6
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_ALIAS_RANGE                 devid: ff:00.0 flags: 00 devid_to: 00:14.4
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_RANGE_END                 devid: ff:1f.7
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_SPECIAL(HPET[0])                devid: 00:14.0
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_SPECIAL(IOAPIC[9])                devid: 00:14.0
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_SPECIAL(IOAPIC[10])                devid: 00:00.1
дек 21 07:08:16 home kernel: AMD-Vi:   DEV_ACPI_HID(PNPD0040[])                devid: 00:13.1
дек 21 07:08:16 home kernel: AMD-Vi: ivrs, add hid:PNPD0040, uid:, rdevid:152
дек 21 07:08:16 home kernel: pci 0000:00:00.2: AMD-Vi: Unable to write to IOMMU perf counter.
дек 21 07:08:16 home kernel: pci 0000:00:00.2: AMD-Vi: Found IOMMU cap 0x40
дек 21 07:08:16 home kernel: pci 0000:00:00.2: AMD-Vi: Extended features (0x4f77ef22294ada):
дек 21 07:08:16 home kernel: AMD-Vi: Interrupt remapping enabled
дек 21 07:08:16 home kernel: AMD-Vi: Virtual APIC enabled
дек 21 07:08:16 home kernel: AMD-Vi: IO/TLB flush on unmap enabled
дек 21 07:08:16 home kernel: AMD-Vi: AMD IOMMUv2 driver by Joerg Roedel 

В котором последние три строчки являются положительным результатом инициализации.

2.2 Группы IOMMU

Представленный скрипт iommu-groupls.sh в листинге 2.6 показывает распределение устройств PCI по группам IOMMU, что позволит определить как и какие устройства имеют такую поддержку или она в них отсутствует.

Листинг 2.6

#!/bin/bash
shopt -s nullglob
for g in /sys/kernel/iommu_groups/*; do
    echo "IOMMU Group ${g##*/}:"
    for d in $g/devices/*; do
        echo -e "\t$(lspci -nns ${d##*/})"
    done;
done;

Группы IOMMU объединяют в себе физические устройства, которые могут быть приданы виртуальной машины. При этом, когда несколько устройств находятся в одной группе, то они могут быть переданы только вместе, но никак по отдельности.

В дампе 2.7 приводится дамп распределение физических устройств PCI по группам IOMMU (результат работы скрипта из дампа 2.6).

Листинг 2.7

user@home:~$ ./iommu-groupls.sh 
IOMMU Group 0:
	00:01.0 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge [1022:1452]
IOMMU Group 1:
	00:01.1 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 PCIe GPP Bridge [6:0] [1022:15d3]
IOMMU Group 10:
	02:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:8168] (rev 15)
IOMMU Group 11:
	03:00.0 Non-Volatile memory controller [0108]: Sandisk Corp WD Black 2018/PC SN520 NVMe SSD [15b7:5003] (rev 01)
IOMMU Group 12:
	04:00.0 Network controller [0280]: Realtek Semiconductor Co., Ltd. RTL8821CE 802.11ac PCIe Wireless Network Adapter [10ec:c821]
IOMMU Group 13:
	05:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Picasso [1002:15d8] (rev c1)
IOMMU Group 14:
	05:00.2 Encryption controller [1080]: Advanced Micro Devices, Inc. [AMD] Family 17h (Models 10h-1fh) Platform Security Processor [1022:15df]
	05:00.3 USB controller [0c03]: Advanced Micro Devices, Inc. [AMD] Raven USB 3.1 [1022:15e0]
	05:00.4 USB controller [0c03]: Advanced Micro Devices, Inc. [AMD] Raven USB 3.1 [1022:15e1]
	05:00.6 Audio device [0403]: Advanced Micro Devices, Inc. [AMD] Family 17h (Models 10h-1fh) HD Audio Controller [1022:15e3]
IOMMU Group 2:
	00:01.2 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 PCIe GPP Bridge [6:0] [1022:15d3]
IOMMU Group 3:
	00:01.3 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 PCIe GPP Bridge [6:0] [1022:15d3]
IOMMU Group 4:
	00:01.7 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 PCIe GPP Bridge [6:0] [1022:15d3]
IOMMU Group 5:
	00:08.0 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge [1022:1452]
	00:08.2 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus B [1022:15dc]
	06:00.0 SATA controller [0106]: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI mode] [1022:7901] (rev 61)
IOMMU Group 6:
	00:08.1 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus A [1022:15db]
IOMMU Group 7:
	00:14.0 SMBus [0c05]: Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller [1022:790b] (rev 61)
	00:14.3 ISA bridge [0601]: Advanced Micro Devices, Inc. [AMD] FCH LPC Bridge [1022:790e] (rev 51)
IOMMU Group 8:
	00:18.0 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 0 [1022:15e8]
	00:18.1 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 1 [1022:15e9]
	00:18.2 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 2 [1022:15ea]
	00:18.3 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 3 [1022:15eb]
	00:18.4 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 4 [1022:15ec]
	00:18.5 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 5 [1022:15ed]
	00:18.6 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 6 [1022:15ee]
	00:18.7 Host bridge [0600]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2 Device 24: Function 7 [1022:15ef]
IOMMU Group 9:
	01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:1f91] (rev a1)
	01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10fa] (rev a1)

2.3 Настройка таблица устройств ввода/вывода виртуализации ACPI

Архитектурой x86-64 определяются совместимые с ACPI данные, обзываемые структурой предоставляющей информацию о вводе/выводе виртуализации (англ. I/O Virtualization Reporting Structure, IVRS), которая используется для передачи информации, связующая I/O виртуализации с системным программным обеспечением.

IVRS описывает конфигурацию и функции IOMMU, содержащиеся в используемой платформе, также как и устройства, которые ей виртуализируются.

Таблица IVRS обеспечивает следующей информацию о том,

При этом в программной реализации информация, содержащаяся в IVRS частенько замещает соответствующую информацию, получаемую из аппаратных регистров IOMMU. Системное программное обеспечение требует, чтобы соблюдались некоторые настройки ACPI, например идентификаторы выбранной производителем базовой "оси-зла".

В памяти таблица IVRS создается встроенной микропрограммой (или системным программным обеспечением) используемой платформы. Существует два формата, предназначенные для IVRS:

Таким образом, системное программное обеспечение должно уметь понимать оба формата.

IVRS содержит один или более определенных блоков виртуализации ввода/вывода (англ. I/O Virtualization Definition Blocks, IVDBs).

Существует два типа IVDB, которые могут быть определены IVRS:

Рассмотрим функциональную схему стандартного взаимодействия IOMMU, как показано ниже.

Рисунок 2.1 взят с AMD I/O Virtualization Technology (IOMMU) SpecificationPDF

На данном рисунке показан единственный IOMMU и все устройства ввода/вывода, присоединенные соподчиненными к нему.

Предположим, что микропрограмма произвела назначение идентификаторам устройствам ввода вывода, надлежащая информация об ввода/вывода виртуализации может быть описана одним блоком формата IVHD для того, чтобы определить IOMMU и какие устройства к ней присоединены.

В системе, где один или более устройств ввода/вывода идентифицируются с использованием формата ACPI HID, IVRS содержит блок IVHD с записями устройств переменной и фиксированной длины для определения всего спектра используемой периферии перевести. Устройств ввода/вывода формата ACPI HID вносятся в IVRS во время загрузки системы. Тоже самое происходит с устройствами PСIe. В тоже время HPET ее не требуют и могут быть добавлены на "лету" без перезагрузки системы. Поэтому в Debian/Linux такие устройства необходимо прописывать до загрузки системы в случае проблем с автоматическим их распределением.

Для этого необходимо указать в опция к ядру amd_iommu_dump, как показано в дампе 2.8

Листинг 2.8

GRUB_CMDLINE_LINUX="...amd_iommu_dump=1..."

При этом не забываем обновить загрузчик, как делали во время его установки.

В результате чего, будет включена AMD IOMMU в выдача на стандартный поток ввода/вывода реальное распределение таблицы ACPI во время инициализации системы, как показано в дампе 2.9

Дамп 2.9

...
дек 21 07:08:16 home2 kernel: AMD-Vi: device: 00:00.2 cap: 0040 seg: 0 flags: b0 info 0000
дек 21 07:08:16 home2 kernel: AMD-Vi:        mmio-addr: 00000000feb80000
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_SELECT_RANGE_START         devid: 00:01.0 flags: 00
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_RANGE_END                 devid: ff:1f.6
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_ALIAS_RANGE                 devid: ff:00.0 flags: 00 devid_to: 00:14.4
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_RANGE_END                 devid: ff:1f.7
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_SPECIAL(HPET[0])                devid: 00:14.0
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_SPECIAL(IOAPIC[9])                devid: 00:14.0
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_SPECIAL(IOAPIC[10])                devid: 00:00.1
дек 21 07:08:16 home2 kernel: AMD-Vi:   DEV_ACPI_HID(PNPD0040[])                devid: 00:13.1
дек 21 07:08:16 home2 kernel: AMD-Vi: ivrs, add hid:PNPD0040, uid:, rdevid:152
...

который соответствует нормальному определению всех подключенных устройств к IOMMU, что наблюдается в ядре Linux 5-й версии.

В более ранних реализаций BIOS и версиях ядра часто наблюдалась картина, показанная в дампе 2.10 .

Дамп 2.10

[    0.297434] AMD-Vi: device: 00:00.2 cap: 0040 seg: 0 flags: 3e info 1300
[    0.297435] AMD-Vi:        mmio-addr: 00000000feb20000
[    0.297444] AMD-Vi:   DEV_SELECT_RANGE_START  devid: 00:00.0 flags: 00
[    0.297445] AMD-Vi:   DEV_RANGE_END           devid: 00:00.2
[   (HPET[0])           devid: 00:14.0
[               …
[    0.297476] AMD-Vi: DEV_RANGE_END devid: 00:16.2
[    0.297477] AMD-Vi: DEV_SPECIAL(IOAPIC[0]) devid: 00:14.0
[    0.297478] AMD-Vi: DEV_SPECIAL(HPET[0]) devid: 00:14.0
[    0.297479] AMD-Vi:   DEV_SPECIAL(IOAPIC[255])               devid: 00:00.1
[    0.297481] [Firmware Bug]: AMD-Vi: IOAPIC[7] not in IVRS table
[    0.297485] [Firmware Bug]: AMD-Vi: IOAPIC[8] not in IVRS table
[    0.297487] [Firmware Bug]: AMD-Vi: No southbridge IOAPIC found in IVRS table
[    0.297490] AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)

Из которго следует, что найдены устройства ввода/вывода ACPI в таблице IVRS, поиск что неправильно определен поиск северного моста и самого IOMMU, которые нужно переназначить в IOAPIC[7] и IOAPIC[8]. Для чего нужно воспользоваться 'lspci -nn', как показано в дампу 2.11

Дамп 2.11

lspci | grep "SMBus \ | IOMMU"
. . .
00: 00.2 IOMMU: Advanced Micro Devices, Inc. [AMD / ATI] RD990 I / O Memory Management Unit (IOMMU)
. . .
00: 14.0 SMBus: Advanced Micro Devices, Inc. [AMD / ATI] SBx00 SMBus Controller (rev 42)
. . .

после определения их devids, нужно явно указать в опциях ядра, передаваемых загрузчиком Grub, как показано в листинге 2.12

Дамп 2.10

GRUB_CMDLINE_LINUX="...ivrs_ioapic[7]=00:14.0 ivrs_ioapic[8]=00:00.1..."

При этом не забываем обновить загрузчик, как делали во время его установки.

Соответственно, при последующей загрузке получим нечто похожее, что наблюдали ранее в дампе 2.9

3. Библиография

3.1 Understanding the iommu Linux grub File Configuration

3.2 AMD Ryzen ThreadRipper KVM Windows 10 GPU pass-through

3.3 oVirt Installation Guide. Appendix G: Configuring a Host for PCI Passthrough

3.4 wiki.archlinux.org. PCI passthrough via OVMF

3.5 wiki.gentoo.org. GPU passthrough with libvirt qemu kvm

3.6 VFIO tips and tricks: VFIO+VGA FAQ

3.7 Help with PCI Express passthrough (ACS - IOMMU issue) + kernel bugfix

3.8 [PATCH] pci: Enable overrides for missing ACS capabilities

3.9 IOMMU group splitting for PCIe passthrough - no success, please help!

3.10 Easy solution to get IOMMU working on mobos with broken BIOSes.

3.11 [AMD iommu] pci Failed to assign device "hostdev0" : Device or resource busy