Passthrough Intel integrated graphics to QEMU/KVM VM on Linux host.
本文Ivon紀錄將Linux Host的Intel內顯,直通給QEMU/KVM虛擬機的過程。
動機:這臺Linux桌電,Intel CPU有附內顯(integrated graphics, iGPU, 內顯,核顯),然而桌電常常是插在Nvidia獨顯上,這時內顯就晾在那邊沒事幹。雖說性能不怎麼樣,但還是想做有效利用,為此我決定將其直通給虛擬機使用,讓Windows系統動畫順一點,能利用3D硬體加速播放影片,玩點小遊戲。
1. 環境說明#
如果要直通GPU,搜尋資料常常會提及使用 Intel GVT-g的虛擬GPU技術,不過我們有更簡單的作法:像 直通Nvidia獨顯那樣隔離PCI再直通就好了。
硬體:
- Host OS:Arch Linux
- 核心版本:6.4.1
- QEMU版本:8.0.2
- 主機板:ASUS K31CD-K
- CPU:Intel i5-7400
- GPU:Intel UHD 630 ← 要直通的GPU
- GPU:Nvidia GTX1050Ti ← 顯示Linux和虛擬機視窗的GPU
接著是要直通的虛擬機系統,為什麼還要直通給另一個Linux?Intel的Linux驅動是開源的,直通後成功機率較大…
- Guest OS 1:Ubuntu 22.04
- Guest OS 2:Windows 11 22H2
2. 安裝虛擬機#
首先要 安裝QEMU/KVM,設定好VFIO
並裝好 Windows 11虛擬機。Ubuntu 22.04的安裝過程跟Windows 11類似我不贅述。
3. 隔離Intel GPU#
3.1. 啟用IOMMU#
- 編輯GRUB設定檔
sudo vim /etc/default/grub
- 在GRUB_CMDLINE_LINUX_DEFAULT這行後面加入核心參數,啟用Intel CPU的
iommu
。(AMD CPU為amd_iommu
)
GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on iommu=pt video=efifb:off"
- 重新產生設定檔,重開機
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo reboot
- 終端機貼上以下指令稿查找顯示卡的IOMMU群組:
#!/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;
- 應會看到Intel顯示卡的分組,後面的四位數組合
8086:5912
就是硬體ID了。
IOMMU Group 0:
00:02.0 Display controller [0380]: Intel Corporation HD Graphics 630 [8086:5912] (rev 04)
3.2. 將Intel顯示卡綁定vfio-pci,禁止Intel驅動載入#
- 編輯GRUB
sudo vim /etc/default/grub
- 將
GRUB_CMDLINE_LINUX_DEFAULT
增加為以下內容,vfio-pci.ids
後面接的是要綁定的顯示卡硬體ID,以逗號分隔。
GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on iommu=pt video=efifb:off vfio-pci.ids=8086:5912"
- 接著用initramfs載入核心模組,修改initramfs內容:
sudo vim /etc/mkinitcpio.conf
- 將
Modules()
修改成如下,設定開機載入vfio核心模組。
MODULES=(vfio_pci vfio vfio_iommu_type1)
- 接著新增禁止載入的核心模組列表
sudo vim /etc/modprobe.d/blacklist.conf
- 填入以下內容,禁止Intel顯示卡的核心模組
i915
載入,snd_hda-*
則是連Intel音效卡也禁止載入(選擇性)。
blacklist i915
blacklist snd_hda_intel
blacklist snd_hda_codec_hdmi
- 刪除Xorg的設定檔
sudo rm /etc/X11/xorg.conf
- 一切就緒後,重新生成initramfs。
sudo mkinitcpio -p linux
- 再重新產生GRUB設定檔
sudo grub-mkconfig -o /boot/grub/grub.cfg
3.3. 設定優先用獨顯開機#
這個ASUS主機板需要特別的設定,讓系統優先以獨顯開機,也防止X伺服器佔用i1915核心模組。
重開機進入BIOS,到Advanced → System Agent (SA)Configuration,設定以PCI獨顯優先開機,並勾選Enable iGPU Multi-Monitor。
3.4. 將Intel顯示卡分配給虛擬機#
開啟Virt Manager,對虛擬機按二下。
點選編輯硬體,新增硬體 → PCI裝置,將Intel UHD 630顯示卡分配給虛擬機。
4. 在Ubuntu 22.04虛擬機內安裝Intel驅動#
Linux的Intel顯示卡驅動是含在核心裡面的,不用裝。
用指令sudo losmod | grep i915
確認i915核心模組有載入
接著,不論Intel顯示卡主機上的HDMI孔有無接實體螢幕,系統都能使用Intel顯示卡運算了。
安裝intel-gpu-tools
,再執行sudo intel_gpu_top
可監控Intel顯示卡有沒有真的跑起來。
有鑑於此,您還可以直通GPU給 Android-x86虛擬機加速。
5. 在Windows 11虛擬機內安裝Intel驅動#
5.1. 正版的受害者#
理論上直通Intel顯示卡之後,Windows更新應該就會自動安裝Intel UHD 630驅動。然而有時裝好後裝置管理員顯示驚嘆號,出現代碼43錯誤 (Code 43),似乎是bug。UNRAID論壇和CSDN也有人也發現此問題。
經過搜尋之後,發現這可能是複合性問題,要讓Intel UHD 630驅動正常運作,必須裝30.*
版本的驅動,且QEMU機器類型必須是i440fx
由於我已經有Windows虛擬機了,之前測試過Nvidia顯示卡直通沒問題,Intel卻有bug。故在該問題解決之前,我只能保持原本的虛擬機不變,另外創一個空的Windows的虛擬機,讀取舊的虛擬機的硬碟開機。這樣做的話Windows的PIN會噴掉,需要重設。
開啟Virt Manager,點選左上角新增機器,跳過新增儲存。作業系統選擇
Microsoft Windows NT Server 3.1
,機器類型選擇i440fx
,點選開機前自訂配置。在機器的頁面選取i440fx,韌體選UEFI (OVMF_CODE.secboot)
點選左下角新增硬體,選儲存,選取現有虛擬機的硬碟
別忘了新增虛擬TPM 2.0硬體裝置
開機,按照畫面指示重設Windows的PIN。
暫停Windows更新,防止下載新版驅動,或是把虛擬網卡移除,將虛擬機斷網。
開啟裝置管理員,對Intel UHD 630 點右鍵 → 解除安裝裝置 → 裝置(依驅動程式),右鍵強制移除
iigd_dch.inf
驅動程式。重開機。至 Intel官網下載
30.0.101.1340
驅動,選取zip版的。將其解壓縮。回到裝置管理員,點選「其他裝置」下的「視訊控制卡」,右鍵 → 更新驅動程式 → 瀏覽電腦上的驅動程式,填入剛剛解壓縮的資料夾,讓Windows自動安裝驅動程式。
重開機一切應該就正常了。
5.2. 指定應用程式使用Intel顯示卡運算#
開啟系統 → 顯示器 → 圖形,選取應用程式exe,指定使用Intel顯示卡運算。
再用工作管理員監控Intel顯示卡有沒有動起來。
5.3. 遠端存取啟用硬體加速#
內網穿透+RDP的方案無法使用硬體加速。
於虛擬機內安裝 Looking Glass即可使用硬體加速的遠端桌面。
6. 如何讓一切回歸原狀#
將/etc/modprobe.d/blacklist.conf
內容全部註解掉。
移除GURB參數寫的vfio硬體ID
。
重新生成initramfs和GRUB設定檔。