Дата и время публикации : Дата и время модификации:
Использование и применение
1. Использование
Технологии виртуализации является предпочтительной благодаря постоянно возрастающему числу ядер центрального процессора. Перевод графических карт на виртуальной машине стало так же возможным с появлением исполнений графических процессоров (англ. Graphics Processing Unit, GPU) не использующих микропрограммный код, которые важны для игрового сегмента программного, но и пакетов программ с интенсивной обработкой графики подобно Adobe Photoshop и т.п.
В результате чего в ядре GNU/Linux появилась функция прямого доступа VM к графического процессору (англ. GPU passthrough) или проброс GPU. Это когда виртуальная машина действует так, как-будто она управляет графическим адаптером непосредственно и имеет возможность определять физически его наличие на шине PCI.
Поэтому ниже разберем:
- как производить настройку ядра GNU/Linux,
- передавать ему опций во время загрузки системы.
Например так, как это делали ранее во время создания системного раздела 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=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 обеспечивает следующей информацию о том,
- как и каким образом IOMMU представлен(ы) в текущей платформе, включая их функциональные особенности и свойства конфигурации;
- какая топология системного ввода/вывода установлена для каждого IOMMU на используемой платформе;
- какие существуют периферийные устройства, которые иначе не могут быть перечислены;
- какие участки (диапазоны) памяти, используются SMI/SMM, микропрограмами и аппаратным обеспечением платформы, которые являются обычно специальными диапазонами, конфигурируемые только системным программным обеспечением.
При этом в программной реализации информация, содержащаяся в IVRS частенько замещает соответствующую информацию, получаемую из аппаратных регистров IOMMU. Системное программное обеспечение требует, чтобы соблюдались некоторые настройки ACPI, например идентификаторы выбранной производителем базовой "оси-зла".
В памяти таблица IVRS создается встроенной микропрограммой (или системным программным обеспечением) используемой платформы. Существует два формата, предназначенные для IVRS:
- Первый формат поддерживает только фиксированные идентифицируемые устройства (англ. DeviceID) ввода/вывода.
- Второй формат поддерживает не только устройства ввода/вывода DeviceID, но и идентифицируемые ACPI аппаратные средства )англ. ACPI Hardware ID, HID).
Таким образом, системное программное обеспечение должно уметь понимать оба формата.
IVRS содержит один или более определенных блоков виртуализации ввода/вывода (англ. I/O Virtualization Definition Blocks, IVDBs).
Существует два типа IVDB, которые могут быть определены IVRS:
- Блок определения аппаратуры ввода/вывода виртуализации (англ. I/O Virtualization Hardware Definition, IVHD ), которой содержит соответствующую информацию об каждом IOMMU в данной платформе и подчиненными им устройствах.
- Блок определения памяти ввода/вывода виртуализации (англ. I/O Virtualization Memory Definition, IVMD), который используется для определения специальных ограничений по работе с памятью.
Рассмотрим функциональную схему стандартного взаимодействия 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