現在我有Intel內顯 + Nvidia獨顯的電腦,如果要增強QEMU/KVM虛擬機圖形效能,我們會使用Nvidia GPU Passthrough的方式讓虛擬機使用顯示卡資源,再讓Intel內顯負責顯示畫面。
相關文章: Arch Linux如何將Nvidia GPU直通給Windows QEMU/KVM虛擬機
本文探討另一個作法:GPU虛擬化,透過Nvidia的vGPU技術,動態分配Nvidia顯示卡給QEMU/KVM虛擬機使用。
下圖是Nvidia官網的架構圖,與GPU Passthrough比起來,vGPU可以一對多,將顯示卡資源切分給多個虛擬機使用。且不需要把Nvidia顯示卡驅動加入開機黑名單,也不需要綁定VFIO裝置。
我目前的用法是在BIOS調整,由Intel內顯當作Linux電腦的主顯示卡,Nvidia顯示卡在旁納涼,這樣才不會因為意外操作而沒畫面。
vGPU啟用有點複雜,Nvidia不會讓一般人用vGPU的,你需要安裝給企業使用的專門驅動程式。且如果顯示卡不支援vGPU功能,你還得手動打patch。
支援vGPU的顯示卡列表請看 官方列表,Quadro可以直接用,我的是GeForce系列需要手動打patch。
1. 環境#
- Host OS:Arch Linux
- Guest OS:Windows 11 23H2
- 核心版本:6.6.11
- QEMU版本:8.2.0
- Libvirt版本:9.10.0
- CPU:Intel i5-7400
- GPU:Intel UHD 630
- GPU:Nvidia GeForce GTX 1050 Ti
- Nvidia驅動版本:535.129.03
2. 啟用IOMMU和VFIO#
如果你有直通過GPU,請將之前做的步驟全撤銷。
- 編輯GRUB
sudo vim /etc/default/grub
- 啟用Intel的IOMMU功能
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet intel_iommu=on iommu=pt"
- 編輯mkinitcpio.conf
sudo vim /etc/mkinitcpio.conf
- 設定開機載入vfio核心模組
MODULES=(vfio_pci vfio vfio_iommu_type1)
- 更新initramfs和GRUB,重開機
sudo mkinitcpio -p linux
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo reboot
3. 設定vGPU系統服務#
vgpu_unlock-rs專案可以在系統跑一個解鎖vGPU功能的系統服務。
- 安裝編譯套件
sudo pacman -S git base-devel dkms linux-headers rust
yay -S mdevctl
- 用cargo編譯vgpu_unlock
su
cd /opt
git clone https://github.com/mbilker/vgpu_unlock-rs.git
cd vgpu_unlock-rs/
cargo build --release
- 編譯後啟動vgpu_unlock系統服務
mkdir /etc/vgpu_unlock
touch /etc/vgpu_unlock/profile_override.toml
mkdir /etc/systemd/system/{nvidia-vgpud.service.d,nvidia-vgpu-mgr.service.d}
echo -e "[Service]\nEnvironment=LD_PRELOAD=/opt/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so" > /etc/systemd/system/nvidia-vgpud.service.d/vgpu_unlock.conf
echo -e "[Service]\nEnvironment=LD_PRELOAD=/opt/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so" > /etc/systemd/system/nvidia-vgpu-mgr.service.d/vgpu_unlock.conf
4. 給顯示卡驅動打patch#
這裡使用Nvidia官方run
版本的驅動,應適用於大多數Linux發行版。
- 解除安裝目前的驅動程式,重開機
sudo pacman -R nvidia-dkms
啟用vGPU需要特製版的Nvidia Grid Driver,到 Nvidia官網註冊企業帳號才能下載Nvidia vgpu-kvm driver。不然你直接Goole搜尋
nvidia-linux-x86_64-535.129.03-vgpu-kvm.run
也能找到熱心網友提供的檔案,但風險自負就是。我的是GeForce系列顯示卡,需要手動給
.run
檔案打patch。下載vgpu-proxmox專案提供的檔案,套用patch。
chmod +x nvidia-linux-x86_64-535.129.03-vgpu-kvm.run
git clone https://gitlab.com/polloloco/vgpu-proxmox.git
./NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm.run --apply-patch vgpu-proxmox/535.129.03.patch
- 之後會得到
NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm-custom.run
檔案,接著以DKMS模式安裝驅動
sudo ./NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm-custom.run --dkms
- 更新initramfs
sudo mkinitcpio -p linux
- 重開機,檢查Nvidia驅動狀況
nvidia-smi
- 檢查vgpu是否啟用
nvidia-smi vgpu
5. 建立vGPU mdev裝置#
註:這一段我無法成功,卡在最後一段賦予UUID的部份,一直遇到「不適用的引數」錯誤。可能是Arch Linux核心太新了?換Ubuntu LTS比較好。
- 取得顯示卡PCI位址
lspci | grep NVIDIA
- 取得GPU在Virsh中的full identifier,例如這裡是
pci_0000_01_00_0
virsh nodedev-list --cap pci| grep 01_00_0
- 取得domain, bus, slot, function資訊
virsh nodedev-dumpxml pci_0000_01_00_0 | egrep 'domain|bus|slot|function'
範例輸出:
<domain>0</domain>
<bus>1</bus>
<slot>0</slot>
<function>0</function>
<address domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x1'/>
- 列出可用設定檔(也可以用
mdevctl types
指令查看)
ls -l /sys/bus/pci/devices/0000:01:00.0
ls /sys/class/mdev_bus/0000:01:00.0/mdev_supported_types
- 賦予uuid
uuid1 = $(uuidgen)
echo $uuid1 > nvidia-286/create
如果賦予多個UUID,等同建立多個虛擬GPU,讓不同的虛擬機使用。
查看mdev裝置狀態
ls -l /sys/bus/mdev/devices/
- 如果要移除裝置就傳入1
echo 1 > /sys/bus/pci/devices/0000:01:00.0/填入UUID/remove
6. 修改vGPU overrides數值#
編輯/etc/vgpu_unlock/profile_override.toml
控制要分配給虛擬機的VRAM大小,我這裡是設定2GB。你可以給多個虛擬機均分GPU。
# 全域設定
[profile.nvidia-286]
num_displays = 1
display_width = 1920
display_height = 1080
max_pixels = 2073600
cuda_enabled = 1
frl_enabled = 1
framebuffer = 0x74000000
framebuffer_reservation = 0xC000000
# 個別設定:mdev的UUID為vGPU mdev的UUID
[mdev.3613e491-7ff6-4e26-bab0-c6209306f0f4]
num_displays = 1
display_width = 1920
display_height = 1080
max_pixels = 2073600
cuda_enabled = 1
frl_enabled = 1
framebuffer = 0x74000000
framebuffer_reservation = 0xC000000
7. 將顯示卡分配給KVM虛擬機#
編輯虛擬機,點選編輯XML
在
</domain>
之前加入段落,添加mdev裝置。UUID1即為剛剛給vGPU賦予的UUID
<hostdev mode="subsystem" type="mdev" managed="no" model="vfio-pci" display="on">
<source>
<address uuid="填入UUID1"/>
</source>
</hostdev>
如果你無法添加mdev裝置,那就點選新增硬體 → 新增PCI,退回到直通GPU的作法。(如果這樣做,Nvidia顯示卡在分配給虛擬機後會從宿主機暫時「斷線」,所以你得準備內顯用於顯示螢幕)
開機後,Linux Guest安裝 Nvidia GRID driver;Windows Guest安裝 一般版驅動。
確認虛擬機認得到驅動版本