Виправити помилку Proxmox «IOMMU не ввімкнено» для PCI passthrough (VT-d/AMD‑Vi) безпечно

Було корисно?

Ви дивитесь на Proxmox, намагаєтесь передати GPU, HBA або NIC у VM, і бачите класичний холодний душ: «IOMMU не ввімкнено». Ви щось увімкнули в BIOS, перезавантажились двічі, і тепер думаєте, чи не зводить вас машина з розуму.

Ця проблема майже ніколи не містична. Зазвичай це одна з п’яти причин: перемикачі прошивки, невірний файл завантажувача, відсутні параметри ядра, відсутні модулі VFIO або плата, що групує пристрої так, ніби намагається перешкодити вам мати хобі. Ми виправимо це безпечно, з доказами на кожному кроці і з варіантами відкату, щоб ви не зробили «брік» віддаленого хоста о 2:00 ночі.

Що таке IOMMU насправді (і чому Proxmox дбатиме)

IOMMU (Intel VT-d, AMD‑Vi) — це блок керування пам’яттю для пристроїв. Процесори мають MMU, яка транслює віртуальні адреси пам’яті в фізичні для процесів. IOMMU робить те саме для DMA (Direct Memory Access) від PCIe-пристроїв: NIC, HBA, GPU, USB-контролерів та інших.

PCI passthrough залежить від цього, бо коли ви передаєте реальний пристрій у VM, хост повинен забезпечити «цей пристрій може виконувати DMA лише в пам’ять цієї VM». Без цього пристрій може «малювати» по пам’яті хоста або іншої VM. Окрім безпеки, це також питання стабільності: випадковий DMA у невірне місце може спричинити креативні kernel panic.

Тому Proxmox перевіряє наявність IOMMU. Якщо він не бачить його, він відмовляється робити вигляд, що все в порядку. Це не примха Proxmox — це захист від того, щоб ваш контролер сховища випадково не перетворився на генератор абстрактного мистецтва.

Одна корисна мантра надійності: як сказав Джон Оллспо, перефразовано: Надійність походить від проєктування під випадок відмови та вивчення їх, а не від ігнорування відмов. Такий тут підхід: змінюйте, перевіряйте та майте відкат.

Також: повідомлення «IOMMU не ввімкнено» стосується хоста. Це ще не про конфігурацію вашої VM. Не витрачайте час на редагування конфігів VM, поки хост не доведе, що IOMMU увімкнено і працює.

Цікаві факти та історія (чому все це таке кумедно-мучительне)

  • Факт 1: Брендинг Intel для IOMMU — VT-d; VT-x — це CPU-віртуалізація. Люди постійно плутають їх, навіть у меню BIOS виробників.
  • Факт 2: Реалізація IOMMU від AMD зазвичай називається AMD‑Vi, а перемикач у BIOS часто просто підписаний «IOMMU».
  • Факт 3: Ранні реалізації PCI passthrough у Linux використовували старий підхід «pciback» перед тим, як VFIO став стандартом. VFIO переміг, бо він більш розумний і безпечний.
  • Факт 4: Межі груп IOMMU походять із ACPI-таблиць та топології PCIe. Два однакові процесори на різних материнських платах можуть поводитися зовсім по-різному.
  • Факт 5: «ACS» (Access Control Services) — це функція PCIe, яка допомагає ізолювати пристрої за свічами/бриджами. Деякі споживчі плати її опускають або реалізують частково.
  • Факт 6: Ядро Linux давно підтримує DMA remapping, але значення за замовчуванням і евристики змінювалися між версіями — особливо щодо компромісу продуктивність vs безпека.
  • Факт 7: Споживчі NVIDIA GPU історично чинили спротив віртуалізації різними способами; сучасні драйвери краще, але фольклор лишається через накопичені «шрами».
  • Факт 8: «Interrupt remapping» — це частина історії: вона допомагає тримати переривання пристроїв ізольованими. Її відсутність може блокувати деякі складні схеми passthrough.
  • Факт 9: Proxmox робить це доступнішим, але під капотом це все ще Linux: параметри завантаження, initramfs, модулі, sysfs і час від часу прошивкові дивні речі.

Це контекст. Тепер практична частина: змусьте хост довести, що він може працювати з IOMMU, потім доведіть, що пристрій можна ізолювати, і лише потім — передавайте його.

Швидкий план діагностики

Якщо ви на виклику, вам не потрібна філософія. Вам потрібен найшвидший шлях до відповіді «це BIOS, завантажувач, ядро чи топологія апаратного забезпечення?». Ось порядок, що найчастіше допомагає.

Перш за все: підтвердьте можливості CPU та реальність перемикачів прошивки

  • Чи підтримує CPU/платформа VT-d/AMD‑Vi?
  • Чи увімкнено це в BIOS/UEFI (не тільки «virtualization», а саме IOMMU/VT-d)?
  • Чи ви перезавантажилися після зміни? (Теплий перезавантаження часто достатній, але деякі плати вимагають повного вимкнення живлення.)

Друге: підтвердьте, що ядро отримало правильні параметри

  • Перевірте реальну командну лінію завантаження в /proc/cmdline.
  • Не довіряйте файлу, який ви відредагували, допоки не побачите його у працюючому ядрі.

Третє: підтвердьте, що ядро справді ініціалізувало IOMMU

  • Шукайте рядки DMAR/IOMMU у dmesg.
  • Перевірте, що /sys/kernel/iommu_groups існує і заповнений.

Четверте: перевірте групування перед тим, як звинувачувати VFIO

  • Погане групування IOMMU — це питання топології/прошивки, а не VFIO.
  • Знайте, що ви готові робити: пересунути карту в інший слот або погодитися на ризики ACS override.

П’яте: лише потім прив’язуйте пристрій до vfio-pci

  • Визначте пристрій за vendor:device ID.
  • Прив’яжіть його в initramfs, щоб драйвер хоста не захопив його першим.

Такий порядок уникає класичної помилки: витрачати годину на налаштування VFIO, поки IOMMU все ще вимкнено на рівні прошивки.

Передпольотна безпека: не залишайте себе наодинці

Увімкнення IOMMU зазвичай безпечне. Небезпечним є те, як люди це роблять: редагують невірний конфігураційний файл завантажувача, додають агресивні параметри, перезавантажують віддалений хост без доступу поза мережею, а потім виявляють, що він не піднімається.

Перед тим як щось робити:

  • Підтвердіть, що маєте доступ до консолі (IPMI/iDRAC/iLO, KVM-over-IP або принаймні хтось, хто може підключити монітор).
  • Заплануйте вікно для перезавантаження. Це зона ядра/прошивки; ви будете перезавантажуватись.
  • Збережіть знімок конфігів, які змінюєте, і тримайте одну відому робочу запис у завантажувачі, якщо можливо.
  • Знайте режим завантаження: GRUB чи systemd-boot. Proxmox може використовувати будь-який залежно від способу інсталяції та макету дисків.

Короткий жарт #1: Якщо ви вмикаєте IOMMU на віддаленому сервері без консолі — ви не займаєтесь SRE, ви займаєтесь перформанс-артом.

Практичні завдання: команди, виводи, рішення (12+)

Ці завдання розташовані в тому порядку, як я би робив на продакшн Proxmox хості. Кожне містить, що воно значить і яке рішення прийняти далі.

Завдання 1: підтвердити розширення віртуалізації CPU (перевірка)

cr0x@server:~$ lscpu | egrep -i 'Vendor ID|Model name|Virtualization|Flags'
Vendor ID:                       GenuineIntel
Model name:                      Intel(R) Xeon(R) CPU E-2278G @ 3.40GHz
Virtualization:                  VT-x
Flags:                           ... vmx ...

Що це означає: VT-x (Intel) або SVM (AMD) — це CPU-віртуалізація. Цей вивід не підтверджує VT-d/AMD‑Vi, але показує, що у вас не дуже старий хардвер.

Рішення: Продовжуйте. Якщо ви не бачите vmx (Intel) або svm (AMD), можливо ви в неправильному режимі BIOS або віртуалізація повністю вимкнена.

Завдання 2: визначити, Intel чи AMD (щоб підібрати параметри ядра)

cr0x@server:~$ lscpu | awk -F: '/Vendor ID/ {print $2}'
 GenuineIntel

Що це означає: Intel використовує intel_iommu=on; AMD — amd_iommu=on. Так, є й інші режими, але почніть з простого.

Рішення: Виберіть правильний параметр для платформи. Невірний параметр зазвичай просто нічого не робить — так ви опинитесь певні, що «увімкнули його».

Завдання 3: підтвердити режим завантаження й завантажувач (GRUB vs systemd-boot)

cr0x@server:~$ proxmox-boot-tool status
Re-executing '/usr/sbin/proxmox-boot-tool' in new private mount namespace..
System currently booted with uefi
Found 1 ESP(s) configured:
  /dev/disk/by-uuid/9A1B-2C3D mounted on /boot/efi
Configured with: systemd-boot

Що це означає: Цей хост використовує systemd-boot. Редагування /etc/default/grub було б марною тратою часу.

Рішення: Якщо бачите systemd-boot, зазвичай редагуйте /etc/kernel/cmdline і виконайте proxmox-boot-tool refresh. Якщо GRUB — редагуйте /etc/default/grub і запустіть update-grub.

Завдання 4: перевірте поточну командну лінію ядра (джерело істини)

cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet

Що це означає: Параметри IOMMU наразі не застосовані.

Рішення: Додайте правильні параметри й перезавантажтесь. Не переходьте до VFIO, поки це не зміниться.

Завдання 5A (systemd-boot): безпечно встановити параметри ядра

cr0x@server:~$ sudo cp -a /etc/kernel/cmdline /etc/kernel/cmdline.bak
cr0x@server:~$ echo "root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt" | sudo tee /etc/kernel/cmdline
root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt

Що це означає: Ви встановили параметри для Intel. iommu=pt використовує pass-through режим для хост-пристроїв (часто краща продуктивність, але зберігає ізоляцію для VFIO).

Рішення: Оновіть записи завантаження та інтеграцію в initramfs за допомогою інструментів Proxmox.

Завдання 6A (systemd-boot): застосувати і синхронізувати конфігурацію завантаження

cr0x@server:~$ sudo proxmox-boot-tool refresh
Re-executing '/usr/sbin/proxmox-boot-tool' in new private mount namespace..
Running hook script 'proxmox-auto-removal'..
Copying kernel and creating EFI boot entry
Refreshing /dev/disk/by-uuid/9A1B-2C3D
Success.

Що це означає: Нова командна лінія ядра тепер у середовищі UEFI, яке використовує Proxmox.

Рішення: Перезавантажте, коли матимете доступ до консолі.

Завдання 5B (альтернатива GRUB): встановити параметри ядра

cr0x@server:~$ sudo cp -a /etc/default/grub /etc/default/grub.bak
cr0x@server:~$ sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 intel_iommu=on iommu=pt"/' /etc/default/grub
cr0x@server:~$ grep GRUB_CMDLINE_LINUX_DEFAULT /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

Що це означає: Параметри будуть вставлені у генерований GRUB конфіг наступним кроком.

Рішення: Запустіть update-grub і перезавантажтеся.

Завдання 6B (альтернатива GRUB): згенерувати конфіг GRUB

cr0x@server:~$ sudo update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.8.12-4-pve
Found initrd image: /boot/initrd.img-6.8.12-4-pve
done

Що це означає: Конфіг GRUB оновлено. Він набуде чинності після перезавантаження.

Рішення: Перезавантажтесь з готовою консоллю.

Завдання 7: перезавантаження і перевірка, що cmdline справді змінився

cr0x@server:~$ sudo reboot
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt

Що це означає: Ви більше не вгадуєте. Працююче ядро має параметри IOMMU.

Рішення: Тепер перевірте логи ядра, щоб підтвердити ініціалізацію.

Завдання 8: підтвердіть ініціалізацію IOMMU у dmesg (Intel DMAR або AMD IOMMU)

cr0x@server:~$ dmesg | egrep -i 'DMAR|IOMMU|AMD-Vi|Interrupt Remapping' | head -n 20
[    0.000000] DMAR: IOMMU enabled
[    0.000000] DMAR: Host address width 39
[    0.123456] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[    0.234567] DMAR: Interrupt remapping enabled

Що це означає: Це — головний доказ. Якщо ви не бачите «IOMMU enabled» (або еквівалентів AMD), ви ще не завершили налаштування.

Рішення: Якщо відсутній, повертайтесь: перевірте налаштування прошивки, невірний параметр завантаження або обмеження платформи.

Завдання 9: перевірте наявність груп IOMMU у sysfs

cr0x@server:~$ ls -1 /sys/kernel/iommu_groups | head
0
1
10
11
12
13
14
15
16
17

Що це означає: Групи існують. Це сильно вказує на те, що IOMMU працює.

Рішення: Переходьте до ідентифікації вашого пристрою і перевірки ізоляції.

Завдання 10: перерахувати PCI-пристрої і знайти той, який хочете передати

cr0x@server:~$ lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation Device [8086:3ec2]
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
03:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Що це означає: GPU знаходиться на 01:00.0, а його аудіо-функція — на 01:00.1. Для GPU зазвичай передають обидві функції разом.

Рішення: Запишіть BDF-адреси та vendor:device ID. Вони знадобляться для прив’язки VFIO і конфігу VM.

Завдання 11: подивіться, який драйвер ядра наразі володіє пристроєм

cr0x@server:~$ lspci -nnk -s 01:00.0
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
        Subsystem: Hewlett-Packard Company Device [103c:12a3]
        Kernel driver in use: nouveau
        Kernel modules: nouveau

Що це означає: Драйвер хоста nouveau захопив GPU. Це буде конфліктувати з VFIO.

Рішення: Плануйте прив’язати цей пристрій до vfio-pci рано (в initramfs) і при потребі заблокувати конфліктні драйвери.

Завдання 12: завантажити модулі VFIO (і зробити це постійним)

cr0x@server:~$ printf "vfio\nvfio_iommu_type1\nvfio_pci\nvfio_virqfd\n" | sudo tee /etc/modules-load.d/vfio.conf
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
cr0x@server:~$ sudo modprobe vfio_pci
cr0x@server:~$ lsmod | egrep '^vfio'
vfio_pci               16384  0
vfio_iommu_type1       45056  0
vfio                   65536  2 vfio_pci,vfio_iommu_type1

Що це означає: VFIO тепер доступний і буде завантажуватись при старті в майбутньому.

Рішення: Далі прив’яжіть конкретні ID пристроїв до vfio-pci, потім перебудуйте initramfs, щоб прив’язка відбулася до того, як драйвери хоста підхоплять пристрій.

Завдання 13: прив’язати конкретні vendor:device ID до vfio-pci

cr0x@server:~$ echo "options vfio-pci ids=10de:1eb1,10de:10f8 disable_vga=1" | sudo tee /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:1eb1,10de:10f8 disable_vga=1

Що це означає: Під час завантаження vfio-pci має претендувати на ці ID.

Рішення: Якщо це ваша єдина GPU і ви покладаєтесь на локальну консоль, зупиніться і подумайте. Передача єдиного адаптера дисплея може зробити хост «безголовим» у несподівані способи.

Завдання 14: заблокувати конфліктні GPU-драйвери (тільки якщо потрібно)

cr0x@server:~$ printf "blacklist nouveau\noptions nouveau modeset=0\n" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0

Що це означає: Це завадить відкритому драйверу NVIDIA зв’язатися першим. Схожа логіка застосовується до інших пристроїв (наприклад, ixgbe для деяких NIC), але блокування драйвера NIC може відрізати і ваш мережевий кабель. Не робіть цього бездумно.

Рішення: Перебудуйте initramfs і перезавантажтесь, щоб забезпечити ранню прив’язку.

Завдання 15: перебудувати initramfs (щоб прив’язка VFIO відбувалась раніше)

cr0x@server:~$ sudo update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-6.8.12-4-pve

Що це означає: Під час завантаження вибір драйверів тепер враховуватиме ваші налаштування VFIO раніше.

Рішення: Перезавантажтесь і перевірте, що пристрій зайнятий vfio-pci.

Завдання 16: перевірити, що пристрій тепер прив’язаний до vfio-pci

cr0x@server:~$ sudo reboot
cr0x@server:~$ lspci -nnk -s 01:00.0
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
        Subsystem: Hewlett-Packard Company Device [103c:12a3]
        Kernel driver in use: vfio-pci
        Kernel modules: nouveau

Що це означає: Ідеально. Хост бачить карту, але vfio-pci її контролює. Рядок «Kernel modules» може ще перелічувати можливі модулі; важливе — «driver in use».

Рішення: Тепер перевірте членство в групі IOMMU, щоб упевнитися, що ви можете безпечно передати пристрій.

Завдання 17: перерахувати групи IOMMU з пристроями (топологічна правда)

cr0x@server:~$ for g in /sys/kernel/iommu_groups/*; do \
  echo "IOMMU Group ${g##*/}"; \
  for d in "$g"/devices/*; do echo "  $(lspci -nn -s ${d##*/})"; done; \
done | sed -n '1,40p'
IOMMU Group 1
  00:01.0 PCI bridge [0604]: Intel Corporation Device [8086:1901]
IOMMU Group 2
  01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
  01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
IOMMU Group 3
  03:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Що це означає: Функції GPU ізольовані у власній групі. Це бажаний стан. Якщо ваш GPU ділить групу, наприклад, з SATA-контролером або USB-контролером, який потрібен хосту — це проблема.

Рішення: Якщо ізоляція добрий, продовжуйте конфігурування VM. Якщо ні — час перекладати карту у інший слот, оновлювати BIOS або обирати ACS override з розумінням ризиків.

Завдання 18: перевірити, що KVM дійсно працює (не пропускайте на дивних платформах)

cr0x@server:~$ lsmod | egrep 'kvm|vfio'
kvm_intel             380928  0
kvm                  1032192  1 kvm_intel
vfio_pci               16384  0
vfio_iommu_type1       45056  0
vfio                   65536  2 vfio_pci,vfio_iommu_type1

Що це означає: Віртуалізація присутня (kvm_intel або kvm_amd) і стек VFIO завантажено.

Рішення: Якщо KVM не завантажено, ви вирішуєте іншу проблему (вимкнена в BIOS віртуалізація або складнощі з nested virtualization). Не плутайте це з IOMMU.

Завдання 19: переконайтесь, що Proxmox бачить IOMMU у зручному вигляді

cr0x@server:~$ pvesh get /nodes/$(hostname)/hardware/pci --noborder | head -n 20
┌─────────┬───────────────────────────────────────────────────────────┬────────────┬────────────┬─────────────┬───────────────┐
│ class   │ device                                                    │ id         │ iommugroup │ subsystem_id │ subsystem_name │
╞═════════╪═══════════════════════════════════════════════════════════╪════════════╪════════════╪═════════════╪═══════════════╡
│ 0x0300  │ NVIDIA Corporation TU104GL [Quadro RTX 4000]              │ 0000:01:00 │ 2          │ 103c:12a3    │ Hewlett-Packard│
└─────────┴───────────────────────────────────────────────────────────┴────────────┴────────────┴─────────────┴───────────────┘

Що це означає: Proxmox може зіставити пристрої з групами IOMMU. Це сильний індикатор того, що попередня робота була правильною.

Рішення: Налаштуйте passthrough у VM. Якщо Proxmox все ще каже «IOMMU не ввімкнено» на цьому етапі, швидше за все ви дивитесь на застарілий стан UI, неправильний вузол або увімкнули це на невірному хості.

GRUB vs systemd-boot у Proxmox: виберіть правильний важіль

Це найпоширеніша трата часу, яку я бачу у реальних середовищах: хтось редагує GRUB, але система завантажується через systemd-boot; або редагує /etc/kernel/cmdline, але система GRUB-базована. Обидва підходи — це «правильна Linux-робота», що нічого не змінює на працюючому хості.

Як швидко визначити

  • systemd-boot (поширено з ZFS root, UEFI): proxmox-boot-tool status показує «Configured with: systemd-boot». Ви редагуєте /etc/kernel/cmdline і виконуєте proxmox-boot-tool refresh.
  • GRUB: efibootmgr -v часто показує GRUB, і proxmox-boot-tool може не використовуватись. Ви редагуєте /etc/default/grub, а потім запускаєте update-grub.

Параметри ядра, які зазвичай є розумними за замовчуванням

  • Intel: intel_iommu=on iommu=pt
  • AMD: amd_iommu=on iommu=pt

Параметри, які люди додають бо бачили в інтернеті (і чому варто бути обережним)

  • pcie_acs_override=downstream,multifunction: може штучно розбити групи; також знижує гарантії ізоляції. Використовуйте лише коли розумієте ризики і погоджуєтесь на них.
  • intel_iommu=on,igfx_off: може допомогти з iGPU-особливостями на деяких системах, але не використовуйте без розуміння.
  • iommu=soft: не те, що вам потрібно для passthrough; це режим відкату і може підвести вашу мету.

Правильне ставлення: додайте мінімальні параметри для ввімкнення IOMMU. Перевірте. Потім вирішуйте питання групування. Потім — прив’язку. Усе інше — це приправи, а не основна страва.

Прив’язка пристроїв до VFIO (без вкрадення завантажувального диска)

Коли IOMMU працює, VFIO — механізм, що робить passthrough керованим. Основна ідея проста: скажіть хосту прилаштувати пристрій до vfio-pci замість його звичайного драйвера, щоб QEMU міг забрати його для VM.

Безпечний спосіб: прив’язуйте за vendor:device ID, а не «те, що у 01:00.0»

Прив’язка за адресою PCI може працювати, але прив’язка за ID зазвичай є стійкішою після перезавантажень і змін топології. Це також небезпечніше, якщо бути недбалим: якщо ви випадково прив’яжете контролер зберігання — у вас буде дуже пізнавальна перезавантаження.

Що передавати разом

  • GPU: зазвичай VGA-функція + аудіо-функція HDMI/DP.
  • HBA: весь контролер. Не передавайте окремі диски контролера, який ви також використовуєте на хості, якщо не любите крайні випадки.
  • USB-контролери: передача цілого контролера часто надійніша, ніж по-пристроєво, особливо для донглів і пристроїв з низькою затримкою.
  • NIC: може бути відмінно, але продумайте доступ до управління. Якщо ви передасте єдиний NIC — ви можете обірвати сесію SSH.

Коли блокувати драйвери

Якщо драйвер хоста захоплює пристрій раніше, ніж VFIO, прив’язка може не спрацювати. Блокування допомагає, але це грубий інструмент. Блокування драйвера GPU на безголовому сервері — нормально. Блокування драйвера NIC на віддаленому хості — спосіб дізнатись, чи дійсно у вас є IPMI.

Короткий жарт #2: Заблокувати єдиний драйвер NIC — швидкий спосіб досягти «повітряної роз’ємності» відповідності.

Групи IOMMU: як їх читати і що робити з поганим групуванням

Групи IOMMU — це межа безпеки. Пристрої в одній групі не можна безпечно ізолювати один від одного для passthrough. Практично це означає: якщо ви передаєте один пристрій із групи в VM, зазвичай доведеться передати всі пристрої з цієї групи або погодитися на підвищений ризик.

Як виглядає «погане групування»

Типовий кошмар: GPU ділить IOMMU групу з SATA-контролером, USB-контролером або PCI-бриджем, який також містить пристрої, потрібні хосту. Proxmox часто відмовляється від passthrough або голосно попереджає. Це не драматизація — це відображення здатності платформи ізолювати DMA.

Три важелі, що реально працюють (ранжовані за правильністю)

  1. Перемістіть карту в інший PCIe слот. Інший слот — інші downstream порти, інше групування. Це найбільш ефективний безкоштовний фікс.
  2. Оновіть BIOS/UEFI прошивку. Виробники іноді виправляють проблеми з таблицями ACS/DMAR. Іноді ні, але варто спробувати перед хаками.
  3. Параметр ACS override ядра. Це може штучно розбити групи. Але це може дати хибне відчуття ізоляції. Використовуйте лише якщо ви приймаєте модель ризику (зазвичай для home-lab; рідко для регульованих середовищ).

Що я роблю в продакшн

У виробничих середовищах, де межі VM важливі, я уникаю ACS override. Якщо плата неправильно групує пристрої, я обираю інше обладнання або переробляю архітектуру: SR-IOV для NIC де можливо, або сервіс на хості замість passthrough.

Якщо ви робите workstation-in-VM на одній машині і готові пожертвувати суворою ізоляцією заради функціональності, ACS override може бути прийнятним. Просто не ілюструйте це як «та сама безпека». Це не так.

Три корпоративні міні-історії з практики

1) Інцидент через неправильне припущення: «увімкнено virtualization» означало, що VT-d увімкнено

Команда розгорнула новий кластер Proxmox для лабораторії з купою appliance VM. Один із аплайенсів потребував passthrough двопортового NIC для точності пакетного таймінгу та вимог підтримки. Інженер, що збирав, увімкнув «Intel Virtualization Technology» у BIOS, переконався, що KVM завантажився, і перейшов далі.

Під час cutover passthrough зазнав невдачі з «IOMMU не ввімкнено». Команда припустила, що це регресія Proxmox через оновлене ядро. Витратили годину на VFIO конфіг, двічі перебудували initramfs і заблокували драйвер, який взагалі не мав відношення. Тим часом старе середовище вже зливали й вимикали, бо план був «чисте переключення».

Виправлення було принизливо простим: у BIOS були два окремі перемикачі — VT-x і VT-d. VT-x був увімкнений; VT-d був вимкнений за замовчуванням. Машина перезавантажилась, DMAR з’явився в dmesg, і все запрацювало.

Урок не в тому, щоб «читати мануал». Урок: завжди перевіряйте стан працюючого ядра (/proc/cmdline, dmesg, /sys/kernel/iommu_groups) перед тим, як лізти в VFIO. Припущення затишні. Продакшн — ні.

2) Оптимізація, що обернулась проблемою: ACS override як хак

Інша команда хотіла максимізувати щільність. Вони мали хости з платами споживчого класу. Треба було передати кілька пристроїв: GPU для VDI-подібних робочих навантажень і USB-контролер для ліцензійних донглів. Групування було погане: декілька root-портів і endpoint-ів опинились у великій IOMMU групі.

Хтось знайшов параметр ACS override і продав його як «чисте рішення». Він розбив групи. Proxmox припинив скаржитись. Роллаут пішов далі, і панелі стали зеленими.

Через тижні почалися рідкісні, але неприємні проблеми: VM іноді зависали під навантаженням I/O. Хост не падав, але уражена VM ставала не відзивною, а іноді скидання не допомагало. Не було єдиного явного винуватця — лише розсіяні таймаути VFIO і періодичний шум PCIe AER.

Вони відкотили ACS override і переробили дизайн: перенесли критичні passthrough навантаження на сервери з кращою ізоляцією PCIe і використали мережеве USB-редирект для тих випадків, де це було допустимо. «Оптимізація» не була про продуктивність; вона була про графік. Вона купила час і впевненість у бюджеті.

Мораль: ACS override — не безкоштовний обід. Це компроміс, який варто документувати як ризик, а не класти як «остаточне рішення».

3) Нудна, але правильна практика, що врятувала день: поетапне перезавантаження і записані записи відкату

Магазин, зосереджений на зберіганні, запускав Proxmox хости з HBA для ZFS і виділеним passthrough NIC для firewall VM. Потрібно було увімкнути IOMMU на підмножині хостів для нового PCIe-карти. Вони робили все повільно і правильно: по одному хосту, в години мінімальної активності, з підтвердженням консолі поза мережею.

Вони також мали план відкату, майже ганебно нудний. Перед змінами в параметрах завантаження вони копіювали відповідні конфіги, занотовували поточний /proc/cmdline і переконувались, що є відома робоча запис у boot entry. На systemd-boot хостах вони перевіряли proxmox-boot-tool status і явно запускали proxmox-boot-tool refresh. Жодного «я думаю, що воно синхронізується автоматично».

На третьому хості ввімкнення IOMMU виявило баг прошивки: машина завантажилась, але змінилася нумерація шини PCIe і ім’я NIC змінилося. Їх firewall VM не стартував, бо конфіг посилалася на відсутній інтерфейс. Оскільки зміни були поетапними, постраждав тільки один сегмент, і відкат пройшов просто.

Вони виправили це, зробивши найменування інтерфейсів більш стійким, і продовжили хост за хостом. Практика, що їх врятувала, не була геніальною — це було змінювати по одному і мати можливість повернутися. Надійність виграла за рахунок нудьги.

Типові помилки: симптом → причина → виправлення

1) Симптом: Proxmox UI каже «IOMMU не ввімкнено» після того, як ви «увімкнули virtualization» у BIOS

Причина: VT-x/SVM увімкнено, але VT-d/AMD‑Vi (IOMMU) досі вимкнено або потребує повної вимк-переключення живлення.

Виправлення: Увімкніть VT-d (Intel) або IOMMU/AMD‑Vi (AMD) явно в прошивці. Потім зробіть холодний перезавантаження, якщо потрібно. Підтвердіть через dmesg | egrep -i 'DMAR|AMD-Vi'.

2) Симптом: Ви редагували GRUB, але /proc/cmdline ніколи не змінюється

Причина: Хост використовує systemd-boot, а не GRUB (поширено на UEFI + ZFS установках).

Виправлення: Редагуйте /etc/kernel/cmdline, запустіть proxmox-boot-tool refresh, перезавантажтесь і перевірте /proc/cmdline.

3) Симптом: /proc/cmdline включає intel_iommu=on, але dmesg не показує DMAR рядків

Причина: Прошивка все ще вимикає VT-d, або платформа його не підтримує, або DMAR таблиці пошкоджені/сховані через налаштування BIOS (іноді «Above 4G decoding» та пов’язані PCIe опції взаємодіють).

Виправлення: Повторно перевірте опції прошивки, оновіть BIOS, спробуйте увімкнути «Above 4G decoding» на деяких платформах (особливо для кількох GPU) і перевірте логи при завантаженні.

4) Симптом: IOMMU ввімкнено, але ваш GPU ділить групу з половиною машини

Причина: Недостатня підтримка ACS / топологія PCIe на материнській платі. Поширено на споживчих платах.

Виправлення: Перемістіть карту в інший слот, оновіть BIOS або погодьтеся на ризик ACS override. Якщо це продакшн з вимогами до ізоляції: змініть обладнання.

5) Симптом: VM не стартує; «device is in use» або «cannot bind to vfio»

Причина: Драйвер хоста досі володіє пристроєм (nouveau/nvidia/amdgpu або драйвер зберігання/NIC), або прив’язка не була внесена в initramfs.

Виправлення: Прив’яжіть через /etc/modprobe.d/vfio.conf, перебудуйте initramfs, перезавантажтесь, підтвердіть Kernel driver in use: vfio-pci.

6) Симптом: Хост завантажується, але локальна консоль мертва після прив’язки VFIO

Причина: Ви прив’язали єдиний GPU до VFIO. Хост залишився без виводу дисплея.

Виправлення: Використайте iGPU для консолі хоста, додайте дешевий другий GPU для хоста або будьте готові працювати headless + через віддалений менеджмент.

7) Симптом: Passthrough працює, але продуктивність дивна (скачки затримки)

Причина: Відсутнє interrupt remapping, проблеми з MSI/MSI-X, управління енергоспоживанням або невідповідність CPU pinning/NUMA. Це не прямо «IOMMU не ввімкнено», але часто виявляється відразу після.

Виправлення: Підтвердіть interrupt remapping у dmesg, перевірте NUMA-локалізацію, розгляньте pinning vCPU і уникайте передачі пристроїв через NUMA-вузли, якщо можливо.

8) Симптом: Після увімкнення IOMMU змінились імена мережевих інтерфейсів і VMs втратили зв’язок

Причина: Змінилася PCI енамеріція; передбачуване найменування інтерфейсів зсунулося; bridge-конфіг посилається на старі імена.

Виправлення: Використовуйте стабільні найменування (за MAC у конфігах Proxmox), перевірте /etc/network/interfaces і ставтеся до увімкнення IOMMU як до «перезавантаження з можливими змінами енамеріації».

Контрольні списки / покроковий план

Покроково: безпечне ввімкнення IOMMU на Proxmox хості

  1. Отримайте доступ до консолі (IPMI/iDRAC/iLO). Якщо не маєте — зупиніться.
  2. Визначте платформу: Intel чи AMD (lscpu).
  3. Увімкніть налаштування прошивки: VT-d (Intel) або IOMMU/AMD‑Vi (AMD). Збережіть і перезавантажтесь. Якщо не з’являється — зробіть холодний запуск.
  4. Визначте завантажувач: proxmox-boot-tool status.
  5. Додайте параметри ядра: Intel intel_iommu=on iommu=pt або AMD amd_iommu=on iommu=pt.
  6. Застосуйте зміни завантажувача: systemd-boot proxmox-boot-tool refresh; GRUB update-grub.
  7. Перезавантаження.
  8. Перевірте:
    • /proc/cmdline містить ваші параметри
    • dmesg показує DMAR/IOMMU enabled
    • /sys/kernel/iommu_groups заповнений

Покроково: підготовка пристрою до passthrough

  1. Ідентифікуйте пристрій: lspci -nn і зафіксуйте vendor:device ID.
  2. Перевірте групу: перерахунок IOMMU груп; переконайтесь, що пристрій не прив’язаний до критичних хост-пристроїв.
  3. Завантажте модулі VFIO постійно (/etc/modules-load.d/vfio.conf).
  4. Прив’яжіть ID до vfio-pci (/etc/modprobe.d/vfio.conf).
  5. Блокуйте драйвер хоста лише при потребі (не блоковуйте драйвери NIC/зберігання без розуміння наслідків).
  6. Перебудуйте initramfs і перезавантажтесь.
  7. Підтвердіть прив’язку: lspci -nnk показує Kernel driver in use: vfio-pci.
  8. Тільки потім підключайте пристрій до VM у Proxmox.

Контрольний список відкату (бо дорослі планують відкат)

  • Приберіть параметри IOMMU з GRUB або /etc/kernel/cmdline.
  • Видаліть або закоментуйте VFIO ID у /etc/modprobe.d/vfio.conf.
  • Приберіть блокування, які додавали.
  • Перебудуйте initramfs.
  • Оновіть конфіг завантажувача (GRUB/systemd-boot).
  • Перезавантажтесь і переконайтесь, що оригінальний драйвер знову володіє пристроєм.

FAQ

1) Чи те саме VT-x і VT-d?

Ні. VT-x — це CPU-віртуалізація. VT-d — це IOMMU для пристроїв. Ви можете мати VT-x працюючим (KVM завантажиться), але VT-d вимкненим і passthrough не працюватиме.

2) На AMD що потрібно увімкнути в BIOS?

Шукайте «IOMMU» або «AMD‑Vi». «SVM» — це CPU-віртуалізація, а не DMA remapping для пристроїв. Зазвичай потрібно увімкнути обидва для Proxmox і passthrough.

3) Чи потрібен iommu=pt?

Зазвичай це хороший дефолт на хостах, що роблять passthrough. Воно може зменшити накладні витрати на хост-пристрої, зберігаючи ізоляцію для VFIO. Під час діагностики можна його прибрати для спрощення, але більшість налаштувань працюють з ним.

4) Чому Proxmox все ще каже «IOMMU не ввімкнено» після встановлення параметрів ядра?

Бо параметри ядра могли не застосуватись (ви редагували невірний конфіг завантажувача), або VT-d/AMD‑Vi у прошивці вимкнено, або ви не перезавантажились. Спочатку перевірте /proc/cmdline. Якщо там немає параметрів — далі нічого не має значення.

5) Що робити, якщо групи IOMMU жахливі?

Спершу спробуйте інший слот PCIe і оновлення BIOS. Якщо це не допомагає, вирішіть, чи приймаєте ризик ACS override. Якщо потрібна сильна ізоляція — не «ліпіть» погане обладнання ядром; використовуйте краще обладнання.

6) Чи можна передати USB-пристрій без передачі всього контролера?

Так, через USB passthrough на рівні QEMU. Але для нестабільних пристроїв (донгли, VR, периферія з низькою затримкою) передача цілого USB-контролера часто надійніша.

7) Чи потрібно відключати драйвер GPU на хості?

Тільки якщо драйвер хоста прив’язується до GPU до того, як це зробить VFIO. Найчистіший підхід — прив’язка VFIO по ID в initramfs. Блокування драйвера допомагає, коли драйвер агресивний, але це грубий інструмент.

8) Чи увімкнення IOMMU може зламати щось?

Зазвичай ні. Іноді це змінює PCI-енумерацію або виявляє баги прошивки. Ось чому роблять поетапні перезавантаження, перевіряють найменування мережі і мають варіанти відкату.

9) Чи можна увімкнути IOMMU без перезавантаження?

Ні. Це ініціалізується на етапі завантаження апаратури/прошивки та ядра. Якщо хтось каже інакше — вас продають настрій.

10) У чому різниця між passthrough по PCI-адресі і по vendor:device ID?

Прив’язка по адресі таргетує конкретний слот/шлях; прив’язка по ID таргетує модель пристрою. Прив’язка по ID зазвичай стабільна, але може захопити більше пристроїв, якщо у вас дублікатів. У продакшні будьте явними і перевіряйте через lspci -nnk після перезавантаження.

Висновок: наступні кроки, що справді рухають справу

Якщо ви бачите «IOMMU не ввімкнено», не метушіться в конфігураціях VM. Змусьте хост довести, що IOMMU увімкнено:

  • Підтвердьте перемикач у прошивці: VT-d/AMD‑Vi увімкнено.
  • Підтвердьте, що параметри ядра застосовано через /proc/cmdline.
  • Підтвердьте, що ядро ініціалізувало IOMMU через dmesg і /sys/kernel/iommu_groups.
  • Підтвердьте ізоляцію пристрою через групи IOMMU перед прив’язкою і passthrough.

Потім робіть VFIO дисципліновано: прив’яжіть потрібні ID, перебудуйте initramfs, перезавантажтесь, підтвердіть, що vfio-pci володіє пристроєм, і тільки після цього приєднуйте його до VM.

Нарешті, приймайте рішення про групування як дорослий: спочатку переміщуйте слоти і оновлюйте прошивку; розглядайте ACS override лише якщо ви приймаєте компроміс. Найбезпечніший passthrough — це той, який підтримує ваше обладнання.

← Попередня
MySQL vs PostgreSQL: резервні копії та відновлення — хто повертає сервіс швидше
Наступна →
Docker «too many open files»: як правильно підвищувати ліміти (systemd + контейнер)

Залишити коментар