JDWA 技术文档
首页
  • 数据库
  • 前端开发
  • 后端开发
  • 开发工具
  • 虚拟化技术
  • KVM显卡直通
  • FPGA仿真固件
  • 项目实战
  • 踩坑记录
  • 开发心得
  • 软件工具
  • 学习资料
  • 开发环境
更新日志
关于我
Gitee
GitHub
首页
  • 数据库
  • 前端开发
  • 后端开发
  • 开发工具
  • 虚拟化技术
  • KVM显卡直通
  • FPGA仿真固件
  • 项目实战
  • 踩坑记录
  • 开发心得
  • 软件工具
  • 学习资料
  • 开发环境
更新日志
关于我
Gitee
GitHub
  • 数据库

    • 数据库教程
    • MySQL免安装版使用指南
    • MySQL性能优化实践
    • Redis入门与实践
    • MinIO快速部署指南
    • MinIO基础使用教程
  • 前端开发

    • 前端开发教程
    • Vue.js开发最佳实践
    • CSS常用技巧与解决方案
    • JavaScript实用技巧与编程模式
    • CSS Grid布局教程
  • 后端开发

    • 后端开发教程
    • Spring Boot实战指南
    • Node.js Express 框架开发实战指南
    • Python Flask 框架开发指南
  • 开发工具

    • 开发工具教程
    • Git 基础教程
    • Git工作流实践指南
    • VS Code 全面使用指南
    • VS Code必装插件推荐
    • Docker基础入门
    • IntelliJ IDEA 使用技巧
    • Eclipse配置与优化
    • Sublime Text 高级技巧
    • Vim 从入门到精通
    • Maven 详解
    • Gradle 入门与进阶
    • Webpack 配置指南
    • npm 与 yarn 使用技巧
    • Makefile 编写指南
    • Navicat 使用指南
    • MCP本地部署教程
  • 虚拟化技术

    • JDWA虚拟化技术专题
    • KVM虚拟机去虚拟化技术详解
  • KVM显卡直通

    • KVM显卡GPU直通教程
  • FPGA仿真固件

    • FPGA仿真固件开发指南
    • 基础-完整设备仿真定制固件开发指南
    • 中级-完整设备仿真定制固件开发指南
    • 高级-完整设备仿真定制固件开发指南

KVM显卡GPU直通配置指南

本文档详细介绍如何在Ubuntu 22.04系统上配置KVM虚拟机显卡直通,让虚拟机能够直接使用物理显卡,获得接近原生的图形处理性能。

  • 视频教程
  • 资源下载
  • 准备工作
  • 第一步:安装Ubuntu 22.04
  • 第二步:安装KVM及相关工具
  • 第三步:配置VFIO驱动
  • 第四步:识别PCI设备并添加到黑名单
    • NVIDIA显卡
    • AMD显卡
  • 第五步:启用IOMMU
  • 第六步:创建并配置虚拟机
    • 6.1 创建新的虚拟机
    • 6.2 自定义虚拟机配置
    • 6.3 安装Windows系统
    • 6.4 安装必要软件和准备直通
    • 6.5 配置直通钩子脚本
    • 6.6 配置虚拟机显卡直通
    • 6.7 配置SSH和网络连接
    • 6.8 启动带有显卡直通的虚拟机
  • 常用命令参考
  • 显卡直通故障排除
  • 如何恢复主机显卡使用
  • 常见问题与解决方案
  • 参考资源
  • B站教程视频

视频教程

以下是KVM显卡直通和虚拟机去虚拟化的视频教程,可直接在页面中观看:

提示

如果视频无法加载,请点击这里直接访问B站观看完整视频。

时间节点参考

  • 22:54 - 删除设备并配置PCI直通

资源下载

以下是本教程所需的资源文件下载链接:

  • 蓝奏云链接:https://wwyy.lanzouu.com/iCkgm2vmoenc 密码: jdwa
  • 123云盘链接:https://www.123912.com/s/6gFkjv-PT9u3 提取码: jdwa

包含内容:VirtIO驱动、配置脚本和其他直通所需工具。

准备工作

在开始配置前,请确保:

  1. 您的CPU和主板支持虚拟化技术(Intel VT-d或AMD-Vi)
  2. BIOS/UEFI中已经启用虚拟化和IOMMU功能
  3. 您使用的是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 创建新的虚拟机

  1. 打开虚拟机管理器(virt-manager)
  2. 点击左上角的"创建新虚拟机"图标
  3. 选择"本地安装介质(ISO镜像或光盘)",点击"前进"
  4. 点击"浏览",选择您下载好的Windows 10 ISO镜像
  5. 在"选择操作系统"中,搜索并选择"Microsoft Windows 10",点击"前进"
  6. 分配内存和CPU:
    • 内存:建议分配主机内存的一半(例如:主机32GB,分配16GB)
    • CPU:建议分配比主机CPU核心数少2个(例如:主机12核,分配10核)
  7. 存储配置:
    • 点击"选择或创建自定义存储"
    • 点击"管理"
    • 点击绿色加号"创建新存储卷"
    • 名称设为"win10"
    • 格式选择"qcow2"
    • 容量建议大于250GB
    • 点击"完成"
  8. 选择刚创建的存储卷,点击"前进"
  9. 重要:勾选"在安装前自定义配置",然后点击"完成"

6.2 自定义虚拟机配置

进入自定义配置界面后,进行以下设置:

概况设置

  1. 固件:选择"UEFI x86_64: /usr/share/OVMF/OVMF_CODE_4M.fd"

CPU设置

  1. 取消勾选"复制主机CPU配置"
  2. 勾选"手动设置CPU拓扑"
  3. 套接字:1
  4. 核心:根据分配的CPU核心数(例如10个)或核心数的一半(例如5个)
  5. 线程:1或2(1×10=10或2×5=10,不推荐线程设置大于2)

引导选项

  1. 勾选"启用引导菜单"
  2. 在启动顺序中勾选"SATA 磁盘1"和"SATA CDROM1"

磁盘设置

  1. 选择"SATA 磁盘1"
  2. 将"磁盘总线"改为"virtio"(提供更好的性能)

网络设置

  1. 选择默认的NIC设备
  2. 将"设备型号"改为"virtio"

添加VirtIO驱动ISO

  1. 点击左下角的"添加硬件"
  2. 选择"存储"
  3. 勾选"选择或创建自定义存储"
  4. 设备类型选择"CDROM设备"
  5. 点击"管理",然后点击"浏览本地"
  6. 选择预先下载的VirtIO驱动ISO文件(virtio-win-0.1.240.iso)
  7. 点击"完成"添加

6.3 安装Windows系统

完成上述配置后,点击"开始安装"。注意以下步骤:

  1. 虚拟机启动后,看到"Press any key to boot from CD or DVD"提示时立即按下回车键
  2. 进入Windows安装界面,按照常规步骤操作,直到选择安装类型
  3. 选择"自定义:仅安装Windows(高级)"
  4. 此时可能看不到任何可用磁盘,需要加载VirtIO驱动:
    • 点击"加载驱动程序"
    • 点击"浏览",找到VirtIO驱动光盘(通常是E盘)
    • 导航到"E:\amd64\w10"目录
    • 选择"Red Hat VirtIO SCSI controller (E:\amd64\w10\viostor.inf)"
    • 点击"下一步",驱动加载完成后回到分区界面
  5. 继续加载网卡驱动:
    • 再次点击"加载驱动程序"
    • 导航到"E:\NetKVM\w10\amd64"目录
    • 选择"Red Hat VirtIO Ethernet Adapter"驱动
    • 点击"下一步"
  6. 选择未分配的磁盘空间,点击"下一步"开始安装
  7. 等待Windows完成安装

6.4 安装必要软件和准备直通

Windows系统安装完成后,需要安装以下软件:

  1. 显卡驱动(预先下载与您显卡型号对应的驱动)
  2. 远程连接软件如ToDesk或TeamViewer(设置开机自启和固定密码)
  3. SSH客户端如FinalShell(用于连接主机)

重要提示

设置ToDesk开机自启动并记录远程ID和密码。当显卡直通到虚拟机后,主机将失去显示输出,您需要通过另一台设备远程连接到虚拟机以完成后续配置。

6.5 配置直通钩子脚本

  1. 关闭虚拟机
  2. 在主机上,打开安装文件夹,并启动终端
  3. 切换到root权限:sudo -i
  4. 执行:bash install_hooks.sh
  5. 输入:nautilus打开文件管理器
  6. 找到并编辑/bin/vfio-teardown.sh文件,将其内容替换为用户提供的脚本内容

6.6 配置虚拟机显卡直通

  1. 打开虚拟机管理器,编辑虚拟机配置

  2. 删除不必要的设备(如默认显示设备QXL):

    • 选择"显示 Spice"或"QXL"设备
    • 将类型更改为"None"或直接移除此设备

    视频指导

    可以观看本页底部B站教程视频的22:54处,获取更加直观的删除QXL设备的操作指导。

  3. 添加物理设备:

    • 点击"添加硬件"
    • 选择"USB主机设备",添加您的鼠标、键盘、耳机等USB设备
    • 您可以通过插拔USB设备来确定哪个设备ID对应哪个外设
  4. 添加显卡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 启动带有显卡直通的虚拟机

  1. 重启Ubuntu系统
  2. 在终端中以root身份登录
  3. 启动虚拟机管理器
  4. 启动配置好直通的虚拟机
  5. 此时您的显示器可能会黑屏,因为显卡已被分配给虚拟机
  6. 使用另一台设备通过ToDesk远程连接到Windows虚拟机
  7. 安装显卡驱动
  8. 这时应该能够在显示器上看到Windows桌面
  9. 安装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虚拟机,还应检查是否安装了显卡最新驱动。

参考资源

  • Arch Linux Wiki: PCI passthrough via OVMF
  • VFIO官方文档
  • VirtIO驱动下载

B站教程视频

以下是KVM显卡直通和虚拟机去虚拟化的视频教程,可直接在页面中观看:

提示

如果视频无法加载,请点击这里直接访问B站观看完整视频。