Featured image of post Прокидання відеокарти PCI до Windows KVM на Arch Linux

Прокидання відеокарти PCI до Windows KVM на Arch Linux

Вступ

Прокидання GPU в KVM відноситься до процесу безпосереднього призначення фізичного GPU (графічного пристрою) віртуальній машині, що працює на гіпервізорі KVM. Це дозволяє віртуальній машині мати виключний доступ до GPU, обійшовши практично віртуалізаційний шар гіпервізора.

Для багатьох це може звучати складно, але з Linux та KVM це насправді легко, і налаштування включає наступні 5 кроків:

  1. Перевірка GPU. Перший крок - переконатися, що GPU, який ви хочете передати, сумісний з вашим обладнанням і підтримує необхідні функції для прохідного доступу. Це часто потребує підтримки VT-d (віртуалізаційна технологія Intel для прямого введення/виведення) або AMD-Vi (AMD віртуалізація I/O) на процесорі, а також IOMMU (одиниця управління пам’яттю введення/виведення) на материнській платі.

  2. Налаштування хоста. Вам потрібно налаштувати систему хоста для активації IOMMU, VT-d або AMD-Vi в налаштуваннях BIOS/UEFI, а також завантажити необхідні модулі ядра та драйвери.

  3. Ізоляція GPU. GPU, призначений для прохідного доступу, потрібно ізолювати від операційної системи хоста таким чином, щоб його можна було виключно призначити для віртуальної машини. Це зазвичай робиться шляхом блокування завантаження драйвера GPU на хості.

  4. Налаштування віртуальної машини. У межах налаштування KVM ви налаштовуєте віртуальну машину для використання GPU, що прокидується. Це включає вказівку GPU як пристрій PCI для передачі до ВМ.

  5. Встановлення драйверів. Після передачі GPU віртуальній машині ви встановлюєте необхідні драйвери в гостьовій операційній системі так само, як і на фізичній машині.

Вимоги до обладнання

Важливо відзначити, що для такого типу налаштувань необхідно, щоб ваше обладнання відповідало вимогам.

ЦП (процесор)

Ваш процесор повинен підтримувати розширення апаратної віртуалізації, такі як Intel VT-x (Intel Virtualization Technology) або AMD-V (AMD Virtualization). Крім того, для пропускання GPU вам знадобиться підтримка розширень Intel VT-d (Intel Virtualization Technology for Directed I/O) або AMD-Vi (AMD Virtualization I/O), які дозволяють прямий доступ до пристроїв вводу-виводу з віртуальних машин.

Материнська плата

Ваша материнська плата повинна мати IOMMU (Input-Output Memory Management Unit), яка підтримує ізоляцію та пропускання пристроїв PCIe. Більшість сучасних материнських плат мають цю функцію, але вам слід перевірити специфікації вашої материнської плати, щоб переконатися в сумісності.

GPU (графічний процесор)

Ваш графічний процесор повинен підтримувати UEFI. Ідеальним вибором буде GPU, який підтримує необхідні функції для пропускання, такі як GPU серії AMD Radeon Pro або Nvidia Quadro, оскільки в GPU для споживачів можуть бути обмеження або вимагати обхідних шляхів.

Налаштування пропускання GPU

Перегляньте ваше обладнання

Першим кроком для налаштування є перегляд вашого обладнання. Якщо ви хочете досягти такого ж налаштування, як у моєму випадку, переконайтеся, що у вас є 2 відеокарти (або принаймні одна зовнішня відеокарта PCI).

Специфікації мого обладнання:

Обладнання PCIE - Робоча станція з двома відеокартами

Встановлення та налаштування KVM

Цей посібник написаний з припущенням, що у вас вже працює система Linux з встановленим та налаштованим KVM (libvirt) та програмним забезпеченням для керування вашими віртуальними машинами (virt-manager, virt-viewer).

Якщо у вас ще не встановлено KVM, перегляньте мій інший посібник: Як встановити KVM на Arch Linux.

Зміна налаштувань BIOS материнської плати

Для того щоб KVM працював на вашій системі, технологія віртуалізації повинна бути включена. Вона може мати різні назви залежно від виробника материнської плати/процесора, але зазвичай це VT-D для Intel та AMD-Vi для AMD відповідно.

Приклад налаштувань віртуалізації на материнській платі MSI Z490 і процесорі Intel

Якщо у вас є налаштування BIOS з інтегрованою графікою в процесорі, вам також потрібно буде змінити пріоритет ініціалізації графіки. Це потрібно для того, щоб запобігти ініціалізації зовнішнього GPU при старті BIOS POST, і делегувати відеосигнал інтегрованій графіці. У моєму випадку цей крок не потрібний, оскільки у мене є 2 зовнішні PCI GPU.

Приклад налаштувань ініціалізації GPU на материнській платі MSI Z490

Увімкнення IOMMU

IOMMU - це загальна назва для Intel VT-d та AMD-Vi.

Для включення IOMMU в системі Linux вам слід передати правильний параметр завантаження ядра. Додавання параметрів завантаження ядра може відрізнятися в залежності від того, який завантажувач ви використовуєте.

Якщо ви використовуєте:

  • Процесор Intel - додайте прапори: intel_iommu=on iommu=pt
  • Процесор AMD - додайте прапори: iommu=pt

У випадку процесорів AMD ядро визначає, чи має бути увімкнений IOMMU з BIOS, і iommu=pt запобігає обробці пристроїв, які не можуть бути пропущені через IOMMU.

Варіант 1: GRUB

Якщо ви використовуєте grub як свій завантажувач, ви можете змінити параметри ядра в файлі /etc/default/grub та додати прапори до параметрів GRUB_CMDLINE_LINUX, наприклад:

1
2
3
...
GRUB_CMDLINE_LINUX="quiet splash intel_iommu=on iommu=pt"
...

Потім збережіть файл і перегенеруйте конфігурацію вашого GRUB за допомогою команди:

sudo grub-mkconfig -o /boot/grub/grub.cfg

Опція 2: Завантаження через systemd Boot

Якщо ви використовуєте завантажувач systemd boot, вам потрібно відредагувати файл вашого завантаження. У моєму випадку цей файл розташований за адресою /boot/loader/entries/arch.conf.

Параметри ядра слід додати в кінець параметра options, наприклад:

1
2
3
...
options rw quiet splash intel_iommu=on iommu=pt
...

Після додавання правильних параметрів ядра до вашого завантажувача, перезавантажте комп’ютер.

Перевірка групування IOMMU

Група IOMMU (Input-Output Memory Management Unit) - це логічне об’єднання пристроїв, які контролюються тією ж самою IOMMU. Основна мета групи IOMMU полягає в тому, щоб сприяти ізоляції та управлінню пристроями в віртуалізованих середовищах, зокрема при використанні технологій пропускання GPU.

Важливо, щоб у тій самій групі IOMMU були лише пристрої, пов’язані з GPU, який ви маєте намір пропустити через них. Оскільки, якщо ви маєте щось інше, воно також повинно бути передане в ВМ, інакше пропускання не працюватиме.

Ви можете скористатися наступним скриптом, щоб перевірити ваші групи iommu:

1
2
3
4
5
6
7
8
#!/bin/bash
shopt -s nullglob
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
    echo "IOMMU Group ${g##*/}:"
    for d in $g/devices/*; do
        echo -e "\t$(lspci -nns ${d##*/})"
    done;
done;

Вам потрібно зберегти вміст скрипта у файл (наприклад, iommu.sh) і зробити цей файл виконуваним (chmod +x iommu.sh), після чого ви можете просто запустити його за допомогою ./iommu.sh.

У моєму випадку групи IOMMU такі:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
IOMMU Group 0:
	00:00.0 Host bridge [0600]: Intel Corporation Comet Lake-S 6c Host Bridge/DRAM Controller [8086:9b33] (rev 05)
IOMMU Group 1:
	00:01.0 PCI bridge [0604]: Intel Corporation 6th-10th Gen Core Processor PCIe Controller (x16) [8086:1901] (rev 05)
	01:00.0 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 XL Upstream Port of PCI Express Switch [1002:1478] (rev c0)
	02:00.0 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 XL Downstream Port of PCI Express Switch [1002:1479]
	03:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 22 [Radeon RX 6700/6700 XT/6750 XT / 6800M/6850M XT] [1002:73df] (rev c0)
	03:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:ab28]

...

IOMMU Group 18:
	07:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 23 [Radeon RX 6600/6600 XT/6600M] [1002:73ff] (rev c7)
IOMMU Group 19:
	07:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:ab28]
...

Переконайтеся, що GPU та пов’язані з ним пристрої не згруповані з іншими критичними системними пристроями (наприклад, контролерами USB, контролерами Ethernet), які ви не маєте наміру передавати у віртуальну машину. Важливо, щоб GPU був у власній ізольованій групі IOMMU для надійного пропускання.

У цьому випадку AMD RX 6600 GPU, який я хочу передати до ВМ, має 2 пристрої 07:00.0 і 07:00.1, кожен у окремій групі IOMMU 18 і 19, і жодні інші пристрої не знаходяться в групах 18 і 19. Це означає, що я можу пропускати його без проблем.

Якщо ми подивимося на пристрої для AMD RX 6750 XT, які є 03:00.0 і 03:00.1 у групі IOMMU 1, також є деякі пристрої PCI-мосту, які в теорії не заважатимуть пропусканню цього GPU, поки ви також передасте ці PCI-мости до ВМ. Справжньою проблемою було б, якщо, наприклад, група IOMMU 1 містила б інший PCI-пристрій (наприклад, мост USB або звукову карту).

У випадку, якщо у вас більше пристроїв, ніж вам потрібно в групі IOMMU з GPU, ви можете спробувати:

  • Якщо ваша материнська плата має багато слотів PCI Express, спробуйте встановити GPU в різні слоти PCI Express і подивіться, чи допоможе це.
  • У випадку, якщо ви не можете знайти оптимальну групу IOMMU без зайвих пристроїв, ви можете патчити свій ядро Linux з патчем ACS Override (але це виходить за рамки цієї статті).

Ізолюйте ваш GPU

Ізоляція GPU - це процес забезпечення того, що GPU доступний виключно для використання конкретною віртуальною машиною, зазвичай шляхом прив’язки його до драйвера VFIO (Virtual Function I/O). Цей процес включає кілька кроків для запобігання використання GPU операційною системою хоста або іншими віртуальними машинами:

  • Відв’язка від драйвера хоста. Спочатку GPU зазвичай прив’язаний до драйвера, який використовується операційною системою хоста для звичайних графічних операцій. Для ізоляції GPU цю прив’язку потрібно скасувати, щоб GPU міг бути вибраний драйвером VFIO. Цей крок фактично відокремлює GPU від операційної системи хоста.

  • Прив’язка до драйвера VFIO. Після відв’язки від драйвера хоста GPU прив’язується до драйвера VFIO, що дозволяє його передавати до віртуальної машини. Драйвер VFIO надає необхідну функціональність для прямого призначення пристроїв (DDA) в віртуалізованих середовищах, забезпечуючи доступність GPU для віртуальної машини.

Ізоляція означає, що після того, як ви завантажите вашу хостову операційну систему Linux, ви не зможете використовувати ізольований GPU (який прив’язаний до драйвера vfio), ви можете використовувати його лише для передачі в ВМ.

Для ізоляції GPU вам потрібно знати ідентифікатори пристроїв вашої відеокарти та аудіовиходу PCI. Ви можете використовувати скрипт iommu.sh з попереднього кроку, щоб отримати цю інформацію. У моєму випадку ідентифікатори пристроїв - 1002:73df і 1002:ab28.

Раннє завантаження VFIO

Щоб завантажити vfio ранніше та прив’язати необхідний GPU до vfio, створіть конфігураційний файл за адресою /etc/modprobe.d/vfio.conf, який у моєму випадку виглядає наступним чином:

1
2
softdep amdgpu pre: vfio-pci
options vfio-pci ids=1002:73ff,1002:ab28 disable_vga=1 kvm.ignore_msrs=1

Тут рядок softdep amdgpu pre: vfio-pci дозволяє примусово завантажити драйвер vfio-pci перед драйвером amdgpu. Мені це потрібно через те, що у мене є 2 зовнішні PCI GPU від одного виробника, і це дозволяє прив’язати GPU RX 6600 до драйвера vfio-pci, а потім прив’язати RX 6750 XT до драйвера amdgpu.

У вашому випадку, якщо у вас є GPU NVidia, то vfio-pci повинен бути завантажений перед драйвером nvidia (пропрітарним) або перед драйвером nouveau (вільним).

Налаштування initramfs

У моєму випадку я використовую mkinitcpio як збирач initramfs. Для налаштування mkinitcpio відредагуйте файл /etc/mkinitcpio.conf.

Додайте необхідні модулі до масиву MODULES:

1
2
3
...
MODULES=(vfio_pci vfio vfio_iommu_type1)
...

Потім переконайтеся, що у вас визначений хук modconf у масиві HOOKS:

1
2
3
...
HOOKS=(... modconf ...)
...

Збережіть файл, а потім виконайте команду для регенерації initramfs:

sudo mkinitcpio -P

Після цього потрібно перезавантажити комп’ютер, щоб зміни вступили в силу.

Налаштування нової віртуальної машини та установка Windows 10/11

Тепер час налаштувати нову віртуальну машину та встановити нову операційну систему Windows. Я рекомендую налаштовувати та встановлювати Windows без будь-яких переданих PCI-пристроїв, і додати їх до віртуальної машини пізніше після завершення встановлення.

Все налаштування легше виконувати за допомогою графічного додатка virt-manager.

  1. Відкрийте додаток virt-manager.

  2. Натисніть “Нова віртуальна машина”.

  3. Виберіть локальний носій для встановлення. Зазвичай це файл образу iso Windows 10/11, який можна завантажити з веб-сайту Microsoft.

Virt Manager - Локальний образ для встановлення ОС

  1. Перейдіть до вашого файлу iso Windows 10/11. Рекомендується розташувати ваш iso десь у вашій домашній теки користувача, щоб уникнути проблем з правами доступу до файлів. Також важливо переконатися, що операційна система ідентифікована як “Windows 10” або “Windows 11” у нижньому полі.

Virt Manager - Шлях до ISO та тип операційної системи

  1. Виділіть CPU та пам’ять. Переконайтеся, що зарезервовано принаймні 2 ядра CPU та деяку кількість оперативної пам’яті для вашої системи хоста Linux, щоб вона могла керувати мережею та іншими процесами. У моєму випадку я виділив 2 ядра CPU та 8 Гб оперативної пам’яті для ВМ, ви можете виділити більше, якщо потрібно.

Virt Manager - Виділення системних ресурсів

  1. Увімкніть зберігання для цієї віртуальної машини та створіть образ диску. Я рекомендую виділити принаймні 50 Гб для віртуальної машини Windows.

Virt Manager - Виділення дискового простору

Потім НЕ НАТИСКАЙТЕ FINISH, і виконайте наступне:

  • Переконайтеся, що увімкнено “Customize Configuration before install”.
  • Дайте вашій ВМ назву.
  • У виборі мережі оберіть “Пристрій хоста [ваш ID пристрою] -> Source Mode -> Bridge або NAT”.
  • Тепер ви можете натиснути “Finish”.

Virt Manager - Назва ВМ, віртуальний мережевий адаптер

  • Переконайтеся, що в «Огляді» вибрано чіпсет Q35 і мікропрограму UEFI. GPU Passthrough не працюватиме в мікропрограмі BIOS, для цього потрібно використовувати UEFI.

Virt Manager - Конфігураціятипу та прошивки чіпсета (Q35 UEFI).

Потім натисніть “Begin installation” та встановіть Windows, як зазвичай. Після встановлення системи перейдіть до наступного кроку.

Налаштування певних параметрів ВМ

Є необхідність додати деякі параметри, що дозволяють приховати той факт, що ви використовуєте віртуальну машину від програми встановлення драйверів GPU.

Для редагування налаштувань ВМ переконайтеся, що ваша ВМ не запущена, і введіть цю команду в термінал:

sudo virsh edit win10

де ви повинні замінити win10 на ім’я вашої ВМ.

Потім виконайте наступні зміни в файлі XML в редакторі:

  • Додайте <vendor_id state='on' value='randomid'/> до розділу <hyperv>.
  • Додайте <kvm><hidden state='on'/></kvm> до розділу <features>.

В результаті структура повинна виглядати так:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
...
<features>
  ...
  <hyperv>
    ...
    <vendor_id state='on' value='randomid'/>
    ...
  </hyperv>
  <kvm>
    <hidden state='on'/>
  </kvm>
  ...
</features>
...

Прокидання GPU до ВМ

У програмі virt-manager відкрийте налаштування вашої ВМ та перейдіть до відповідних налаштувань, де потрібно додати 2 PCI-пристрої хоста, пов’язані з GPU, який ви маєте намір пропустити.

  1. Натисніть “Додати пристрої PCI”.

  2. Натисніть “Додати обладнання”.

  3. Виберіть PCI-пристрій хоста

Прокрутіть вниз, поки не знайдете GPU, який ви хочете пропустити. Ідентифікатори повинні відповідати виводам з попереднього етапу. Наприклад, у моєму випадку:

  • 0000:07:00:0 Advanced Micro Devices, Inc. [AMD/ATI] Navi 23 [Radeon RX 6600/6600 XT/6600M]
  • 0000:07:00:1 Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:ab28]

Вам потрібно це зробити двічі для відеопристрою та аудіопристрою GPU відповідно.

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

Встановлення драйверів GPU

Після успішного завантаження вашої Windows ВМ з зовнішнім GPU, час завантажити та встановити останні версії драйверів від виробника вашого GPU.

Висновок

Налаштована віртуальна машина Windows з пропусканням GPU може обробляти певні графічні програми (наприклад, геймінг або відеомонтаж) з майже нативною продуктивністю, що дозволяє використовувати вашу основну систему Linux та гостьову систему Windows одночасно.

Результат GPU Passthrough: Windows ВМ ліворуч, Linux host праворуч

Переваги пропускання GPU в KVM включають:

  • Покращена продуктивність: Шляхом безпосереднього доступу до фізичного GPU віртуальна машина може досягти майже нативної продуктивності для графічно інтенсивних завдань, таких як геймінг, відеомонтаж та 3D-моделювання.

  • Зменшення накладних витрат: Оскільки віртуальна машина обходить віртуалізаційний шар гіпервізора для операцій з GPU, накладні витрати менше порівняно з традиційними техніками віртуалізації GPU, такими як емуляція GPU або віртуальні рішення GPU (vGPU).

  • Підтримка завдань з апаратним прискоренням GPU: Пропускання GPU дозволяє віртуальним машинам використовувати апаратне прискорення для завдань, які покладаються на обробку GPU, що призводить до швидшого виконання та покращеної ефективності.

  • Сумісність з програмним забезпеченням, яке вимагає GPU: Деякі програми та робочі процеси вимагають прямого доступу до фізичного GPU, що можливо не здійснюється за допомогою віртуальних рішень GPU. Пропускання GPU дозволяє такому програмному забезпеченню працювати безперешкодно в віртуалізованому середовищі.

  • Геймінг: Гравці можуть скористатися пропусканням GPU, запускаючи ігри в межах віртуальної машини з мінімальним зниженням продуктивності, що дозволяє використовувати апаратно-прискорену графіку без подвійного завантаження або виділення окремої фізичної машини для геймінгу.

Всі права захищено.