KVM显卡GPU直通配置指南
本文档详细介绍如何在Ubuntu 22.04系统上配置KVM虚拟机显卡直通,让虚拟机能够直接使用物理显卡,获得接近原生的图形处理性能。
视频教程
以下是KVM显卡直通和虚拟机去虚拟化的视频教程,可直接在页面中观看:
提示
如果视频无法加载,请点击这里直接访问B站观看完整视频。
时间节点参考
- 22:54 - 删除设备并配置PCI直通
资源下载
以下是本教程所需的资源文件下载链接:
- 蓝奏云链接:https://wwyy.lanzouu.com/iCkgm2vmoenc 密码:
jdwa
- 123云盘链接:https://www.123912.com/s/6gFkjv-PT9u3 提取码:
jdwa
包含内容:VirtIO驱动、配置脚本和其他直通所需工具。
准备工作
在开始配置前,请确保:
- 您的CPU和主板支持虚拟化技术(Intel VT-d或AMD-Vi)
- BIOS/UEFI中已经启用虚拟化和IOMMU功能
- 您使用的是Ubuntu 22.04或兼容系统
第一步:安装Ubuntu 22.04
首先,您需要安装Ubuntu 22.04系统,安装完成后设置root密码:
sudo passwd
第二步:安装KVM及相关工具
安装所需的虚拟化软件包:
sudo apt install qemu-kvm qemu-utils libvirt-daemon-system libvirt-clients bridge-utils virt-manager ovmf
提示
如果在软件中心找不到virt-manager,可以直接搜索"虚拟系统管理器"进行安装
将当前用户添加到libvirt和kvm用户组:
sudo usermod -aG libvirt $USER
sudo usermod -aG kvm $USER
重启libvirtd服务并重启系统:
sudo systemctl restart libvirtd.service
reboot
第三步:配置VFIO驱动
编辑modules文件:
sudo gedit /etc/modules
在文件末尾添加以下内容:
softdep snd_hda_intel pre:vfio vfio_pci
softdep amdgpu pre:vfio vfio_pci
# 这个是一个排序可以让vfio驱动优先加载
vfio
vfio_iommu_type1
vfio_virqfd
保存并重启系统:
reboot
第四步:识别PCI设备并添加到黑名单
查找您的显卡设备:
NVIDIA显卡
lspci -nnk | grep NVIDIA
NVIDIA显卡通常是01:00.0和01:00.1设备
AMD显卡
lspci -nnk | grep AMD
AMD显卡通常是03:00.0和03:00.1设备
查看设备驱动:
lspci -vv -s 01:00.0 | grep driver # 查看01:00.0的驱动
lspci -vv -s 01:00.1 | grep driver # 查看01:00.1的驱动(通常是音频设备)
查看IOMMU分组:
find /sys/kernel/iommu_groups/ -type l
将显卡驱动添加到黑名单:
sudo gedit /etc/modprobe.d/blacklist.conf
对于NVIDIA显卡,添加:
blacklist nvidia
blacklist nouveau
blacklist snd_hda_intel
对于AMD显卡,添加:
blacklist amdgpu
blacklist pcieport
blacklist snd_hda_intel
保存并重启:
reboot
第五步:启用IOMMU
确认IOMMU是否已启用:
sudo dmesg | grep -e DMAR -e IOMMU
查看显卡ID:
lspci -nn | grep NVIDIA # NVIDIA显卡
# 或
lspci -nn | grep AMD # AMD显卡
编辑GRUB配置:
sudo gedit /etc/default/grub
修改GRUB_CMDLINE_LINUX_DEFAULT
行,添加IOMMU及VFIO参数:
对于AMD处理器:
GRUB_CMDLINE_LINUX_DEFAULT="amd_iommu=on iommu=pt pcie_aspm=off vfio_iommu_type1.allow_unsafe_interrupts=1 vfio_pci.disable_vga=1 vfio_pci.disable_idle_d3=1 kvm.ignore_msrs=1 vfio-pci.ids=10de:1f9d"
对于Intel处理器,使用intel_iommu=on
代替amd_iommu=on
。
注意
vfio-pci.ids
参数后的值必须是您显卡的ID,例如上面的10de:1f9d
是一个NVIDIA显卡的ID,您需要将其替换为您显卡的实际ID。
更新GRUB配置并重启:
sudo update-grub
reboot
第六步:创建并配置虚拟机
6.1 创建新的虚拟机
- 打开虚拟机管理器(virt-manager)
- 点击左上角的"创建新虚拟机"图标
- 选择"本地安装介质(ISO镜像或光盘)",点击"前进"
- 点击"浏览",选择您下载好的Windows 10 ISO镜像
- 在"选择操作系统"中,搜索并选择"Microsoft Windows 10",点击"前进"
- 分配内存和CPU:
- 内存:建议分配主机内存的一半(例如:主机32GB,分配16GB)
- CPU:建议分配比主机CPU核心数少2个(例如:主机12核,分配10核)
- 存储配置:
- 点击"选择或创建自定义存储"
- 点击"管理"
- 点击绿色加号"创建新存储卷"
- 名称设为"win10"
- 格式选择"qcow2"
- 容量建议大于250GB
- 点击"完成"
- 选择刚创建的存储卷,点击"前进"
- 重要:勾选"在安装前自定义配置",然后点击"完成"
6.2 自定义虚拟机配置
进入自定义配置界面后,进行以下设置:
概况设置
- 固件:选择"UEFI x86_64: /usr/share/OVMF/OVMF_CODE_4M.fd"
CPU设置
- 取消勾选"复制主机CPU配置"
- 勾选"手动设置CPU拓扑"
- 套接字:1
- 核心:根据分配的CPU核心数(例如10个)或核心数的一半(例如5个)
- 线程:1或2(1×10=10或2×5=10,不推荐线程设置大于2)
引导选项
- 勾选"启用引导菜单"
- 在启动顺序中勾选"SATA 磁盘1"和"SATA CDROM1"
磁盘设置
- 选择"SATA 磁盘1"
- 将"磁盘总线"改为"virtio"(提供更好的性能)
网络设置
- 选择默认的NIC设备
- 将"设备型号"改为"virtio"
添加VirtIO驱动ISO
- 点击左下角的"添加硬件"
- 选择"存储"
- 勾选"选择或创建自定义存储"
- 设备类型选择"CDROM设备"
- 点击"管理",然后点击"浏览本地"
- 选择预先下载的VirtIO驱动ISO文件(virtio-win-0.1.240.iso)
- 点击"完成"添加
6.3 安装Windows系统
完成上述配置后,点击"开始安装"。注意以下步骤:
- 虚拟机启动后,看到"Press any key to boot from CD or DVD"提示时立即按下回车键
- 进入Windows安装界面,按照常规步骤操作,直到选择安装类型
- 选择"自定义:仅安装Windows(高级)"
- 此时可能看不到任何可用磁盘,需要加载VirtIO驱动:
- 点击"加载驱动程序"
- 点击"浏览",找到VirtIO驱动光盘(通常是E盘)
- 导航到"E:\amd64\w10"目录
- 选择"Red Hat VirtIO SCSI controller (E:\amd64\w10\viostor.inf)"
- 点击"下一步",驱动加载完成后回到分区界面
- 继续加载网卡驱动:
- 再次点击"加载驱动程序"
- 导航到"E:\NetKVM\w10\amd64"目录
- 选择"Red Hat VirtIO Ethernet Adapter"驱动
- 点击"下一步"
- 选择未分配的磁盘空间,点击"下一步"开始安装
- 等待Windows完成安装
6.4 安装必要软件和准备直通
Windows系统安装完成后,需要安装以下软件:
- 显卡驱动(预先下载与您显卡型号对应的驱动)
- 远程连接软件如ToDesk或TeamViewer(设置开机自启和固定密码)
- SSH客户端如FinalShell(用于连接主机)
重要提示
设置ToDesk开机自启动并记录远程ID和密码。当显卡直通到虚拟机后,主机将失去显示输出,您需要通过另一台设备远程连接到虚拟机以完成后续配置。
6.5 配置直通钩子脚本
- 关闭虚拟机
- 在主机上,打开安装文件夹,并启动终端
- 切换到root权限:
sudo -i
- 执行:
bash install_hooks.sh
- 输入:
nautilus
打开文件管理器 - 找到并编辑
/bin/vfio-teardown.sh
文件,将其内容替换为用户提供的脚本内容
6.6 配置虚拟机显卡直通
打开虚拟机管理器,编辑虚拟机配置
删除不必要的设备(如默认显示设备QXL):
- 选择"显示 Spice"或"QXL"设备
- 将类型更改为"None"或直接移除此设备
视频指导
可以观看本页底部B站教程视频的22:54处,获取更加直观的删除QXL设备的操作指导。
添加物理设备:
- 点击"添加硬件"
- 选择"USB主机设备",添加您的鼠标、键盘、耳机等USB设备
- 您可以通过插拔USB设备来确定哪个设备ID对应哪个外设
添加显卡PCI设备:
- 点击"添加硬件"
- 选择"PCI主机设备"
- 找到您的显卡(如"0000:01:00:0 NVIDIA Corporation AD106 [GeForce RTX 4060 Ti]")
- 如果显卡有多个功能(如音频控制器),也需要添加(通常是"0000:01:00:1")
6.7 配置SSH和网络连接
在主机上进行以下设置,以便在显卡直通后仍能远程访问:
# 安装SSH服务器
sudo apt-get install openssh-server
# 启动SSH服务
sudo service ssh start
# 安装网络工具包
sudo apt-get install net-tools
# 查看网络接口和IP地址
ifconfig
记录Ubuntu主机和Windows虚拟机的IP地址,以便之后进行远程连接。
6.8 启动带有显卡直通的虚拟机
- 重启Ubuntu系统
- 在终端中以root身份登录
- 启动虚拟机管理器
- 启动配置好直通的虚拟机
- 此时您的显示器可能会黑屏,因为显卡已被分配给虚拟机
- 使用另一台设备通过ToDesk远程连接到Windows虚拟机
- 安装显卡驱动
- 这时应该能够在显示器上看到Windows桌面
- 安装FinalShell以便与主机进行SSH连接
提示
如果屏幕在3分钟后仍然黑屏,请通过其他设备使用ToDesk连接到虚拟机,安装显卡驱动。
常用命令参考
以下是设置直通过程中可能会用到的一些命令:
# 安装KVM相关软件包
sudo apt install qemu-kvm qemu-utils libvirt-daemon-system libvirt-clients bridge-utils virt-manager ovmf
# 添加用户到libvirt和kvm组
sudo usermod -aG libvirt $USER
sudo usermod -aG kvm $USER
# 编辑modules配置
sudo gedit /etc/modules
# 内容:
# softdep snd_hda_intel pre:vfio vfio_pci
# softdep amdgpu pre:vfio vfio_pci
# vfio
# vfio_iommu_type1
# vfio_virqfd
# 编辑GRUB配置
sudo gedit /etc/default/grub
# 添加:intel_iommu=on iommu=pt
sudo update-grub
# 创建VFIO配置文件
sudo gedit /etc/modprobe.d/vfio.conf
# 内容:
# options vfio-pci ids=1002:67ff,1002:aae0(根据你的显卡ID修改)
# options vfio-pci disable_idle_d3=1
# options vfio-pci disable_vga=1
# 打开文件管理器
nautilus
# 查看服务文件
file /etc/systemd/system/display-manager.service
# 设置钩子脚本权限
sudo chmod +x /etc/libvirt/hooks/*
# 创建符号链接
sudo ln -s /etc/libvirt/hooks/vfio-startup.sh /bin/vfio-startup.sh
sudo ln -s /etc/libvirt/hooks/vfio-teardown.sh /bin/vfio-teardown.sh
# 创建防止系统休眠的服务
sudo nano /etc/systemd/system/libvirt-nosleep@.service
# 内容:
# [Unit]
# Description=Preventing sleep while libvirt domain "%i" is running
#
# [Service]
# Type=simple
# ExecStart=/usr/bin/systemd-inhibit --what=sleep --why="Libvirt domain \"%i\" is running" --who=%U --mode=block sleep infinity
# 设置服务文件权限
sudo chmod 644 -R /etc/systemd/system/libvirt-nosleep@.service
sudo chown root:root /etc/systemd/system/libvirt-nosleep@.service
# 编辑libvirt配置
sudo gedit /etc/libvirt/libvirtd.conf
# 更改:
# unix_sock_group = "libvirt"
# unix_sock_rw_perms = "0770"
# 编辑QEMU配置
sudo gedit /etc/libvirt/qemu.conf
# 注释:
# #user = "root"
# #group = "root"
# 添加:
# group = "libvirt"
# 添加用户到libvirt组
sudo usermod -a -G libvirt $USER
# 查看IOMMU是否启用
sudo dmesg | grep iommu
# 查看NVIDIA显卡
lspci -nn | grep NVIDIA
# 安装JSON库
sudo apt-get install libjsoncpp-dev
资源下载
VirtIO驱动官方下载页面: https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/
显卡直通故障排除
如果您遇到问题,可以运行以下IOMMU组查看脚本,以检查设备分组情况:
#!/bin/bash
useColors=true
usePager=true
usage() {
echo "\
Usage: $(basename $0) [OPTIONS]
Shows information about IOMMU groups relevant for working with PCI-passthrough
-c -C enables/disables colored output, respectively
-p -P enables/disables pager (less), respectively
-h display this help message"
}
color() {
if ! $useColors; then
cat
return
fi
rset=$'\E[0m'
case "$1" in
black) colr=$'\E[22;30m' ;;
red) colr=$'\E[22;31m' ;;
green) colr=$'\E[22;32m' ;;
yellow) colr=$'\E[22;33m' ;;
blue) colr=$'\E[22;34m' ;;
magenta) colr=$'\E[22;35m' ;;
cyan) colr=$'\E[22;36m' ;;
white) colr=$'\E[22;37m' ;;
intenseBlack) colr=$'\E[01;30m' ;;
intenseRed) colr=$'\E[01;31m' ;;
intenseGreen) colr=$'\E[01;32m' ;;
intenseYellow) colr=$'\E[01;33m' ;;
intenseBlue) colr=$'\E[01;34m' ;;
intenseMagenta) colr=$'\E[01;35m' ;;
intenseCyan) colr=$'\E[01;36m' ;;
intenseWhite) colr=$'\E[01;37m' ;;
esac
sed "s/^/$colr/;s/\$/$rset/"
}
indent() {
sed 's/^/\t/'
}
pager() {
if $usePager; then
less -SR
else
cat
fi
}
while getopts cCpPh opt; do
case $opt in
c)
useColors=true
;;
C)
useColors=false
;;
p)
usePager=true
;;
P)
usePager=false
;;
h)
usage
exit
;;
esac
done
iommuGroups=$(find '/sys/kernel/iommu_groups/' -maxdepth 1 -mindepth 1 -type d)
if [ -z "$iommuGroups" ]; then
echo "No IOMMU groups found. Are you sure IOMMU is enabled?"
exit
fi
for iommuGroup in $iommuGroups; do
echo "IOMMU group $(basename "$iommuGroup")" | color red
for device in $(ls -1 "$iommuGroup/devices/"); do
devicePath="$iommuGroup/devices/$device/"
# Print pci device
lspci -nns "$device" | color blue
# Print drivers
driverPath=$(readlink "$devicePath/driver")
if [ -z "$driverPath" ]; then
echo "Driver: none"
else
echo "Driver: $(basename $driverPath)"
fi | indent | color cyan
# Print usb devices
usbBuses=$(find $devicePath -maxdepth 2 -path '*usb*/busnum')
for usb in $usbBuses; do
echo 'Usb bus:' | color cyan
lsusb -s $(cat "$usb"): | indent | color green
done | indent
# Print block devices
blockDevices=$(find $devicePath -mindepth 5 -maxdepth 5 -name 'block')
for blockDevice in $blockDevices; do
echo 'Block device:' | color cyan
echo "Model: $(cat "$blockDevice/../model")" | indent | color green
lsblk -no NAME,SIZE,MOUNTPOINT "/dev/$(ls -1 $blockDevice)" | indent | color green
done | indent
done | indent
done | pager
如何恢复主机显卡使用
如果需要恢复主机系统对直通显卡的使用,可以使用以下脚本:
#!/bin/bash
set -x
sleep 10
modprobe -r vfio_pci
modprobe -r vfio
modprobe -r vfio_iommu_type1
modprobe -r vfio_virqfd
virsh nodedev-reattach pci_0000_01_00_0
virsh nodedev-reattach pci_0000_01_00_1
echo 1 > /etc/class/vtconsole/vtcon0/bind
echo 1 > /etc/class/vtconsole/vtcon1/bind
echo efi-framebuffer.0 > /sys/bus/platform/drivers/efi-framebuffer/bind
modprobe nvidia
modprobe nvidia_modeset
modprobe nvidia_uvm
modprobe nvidia_drm
modprobe drm_kms_helper
modprobe i2c_nvidia_gpu
modprobe drm
sleep 10
systemctl start gdm3
将上述脚本保存为restore-gpu.sh
,需要时用root权限执行。
常见问题与解决方案
无法找到IOMMU组
确保在BIOS中启用了虚拟化技术和IOMMU支持(对于Intel为VT-d,对于AMD为AMD-Vi)。
黑屏或虚拟机无法启动
检查VFIO驱动是否正确加载,以及是否有设备ID冲突。可尝试在GRUB配置中添加video=efifb:off
参数。
虚拟机性能低下
确保已安装VirtIO驱动,并检查CPU和内存分配是否合理。对于Windows虚拟机,还应检查是否安装了显卡最新驱动。
参考资源
B站教程视频
以下是KVM显卡直通和虚拟机去虚拟化的视频教程,可直接在页面中观看:
提示
如果视频无法加载,请点击这里直接访问B站观看完整视频。