惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google DeepMind News
Google DeepMind News
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
Y
Y Combinator Blog
aimingoo的专栏
aimingoo的专栏
A
About on SuperTechFans
V2EX - 技术
V2EX - 技术
Webroot Blog
Webroot Blog
Google Online Security Blog
Google Online Security Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
AI
AI
N
News and Events Feed by Topic
S
Secure Thoughts
www.infosecurity-magazine.com
www.infosecurity-magazine.com
The Cloudflare Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tailwind CSS Blog
Vercel News
Vercel News
V
Vulnerabilities – Threatpost
Spread Privacy
Spread Privacy
Know Your Adversary
Know Your Adversary
人人都是产品经理
人人都是产品经理
I
Intezer
Schneier on Security
Schneier on Security
Martin Fowler
Martin Fowler
J
Java Code Geeks
K
Kaspersky official blog
H
Heimdal Security Blog
O
OpenAI News
I
InfoQ
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
云风的 BLOG
云风的 BLOG
Hacker News - Newest:
Hacker News - Newest: "LLM"
Blog — PlanetScale
Blog — PlanetScale
S
Schneier on Security
S
Security @ Cisco Blogs
Security Latest
Security Latest
PCI Perspectives
PCI Perspectives
H
Hacker News: Front Page
C
CERT Recently Published Vulnerability Notes
博客园_首页
The Last Watchdog
The Last Watchdog
罗磊的独立博客
L
LINUX DO - 热门话题
U
Unit 42
月光博客
月光博客
Security Archives - TechRepublic
Security Archives - TechRepublic
Scott Helme
Scott Helme

Jiajun的技术笔记

你好,2026! TiDB 源码阅读(六):TiDB Coprocessor 源码解析 性能优化的核心思想 TiDB 源码阅读(五):索引 TiDB 源码阅读(四):AST、逻辑计划、物理计划 CockroachDB Serverless Architecture podman 无故退出 Cursor Control-L (CTRL-L) Keyboard Shortcuts in Terminal Replace docker with podman Using xmonad with xfce4 A RC script for freebsd frpc 自己动手写一个k8s controller AI 会取代你的(编程)岗位吗? 自建DERP服务器提升Tailscale连接速度(使用Nginx转发) 自动升级Docker容器 再读《程序员修炼之道-从小工到专家》 让浏览器下载文件 再读《软件随想录》/《黑客与画家》/《软技能》 HTTP 压力测试中的 Coordinated Omission 2的补码 编程语言中的 context 是什么? flutter macOS 构建出错 Flatpak 使用小记 Golang CAS 操作是怎么实现的 PostgreSQL 当MQ来使用 Clash 结合 工作VPN 的网络设计 使用 PostgreSQL 搭建 JuiceFS PostgreSQL 配置优化和日志分析 有GitHub Copilot?那就可以搭建你的ChatGPT4服务 窗口函数的使用(以PG为例) 读《为什么学生不喜欢上学》 OpenAI Prompt Engineering 摘录和总结 读《打造真正的新产品》 VueJS 总结 Linux 自动挂载 alist 提供的webdav FreeBSD 使用 vm-bhyve 安装Debian虚拟机 FreeBSD 和 Linux 网卡聚合实现提速 GPT 帮我搞定了时区转换问题 长任务系统如何处理? macOS/Linux 编译 InputLeap 使用开源软KVM - synergy-core 解决 macOS 终端hostname一直变化问题 KVM 共享 Intel 集成显卡 PromQL 备忘 读《格鲁夫给经理人的第一课》 读《打开心智》 为什么要把复杂的联表操作拆成多个单表查询? 红包系统的设计 MySQL Index Condition Pushdown Optimization Go mod 简明教程 OpenWRT 使用 Android/iOS USB 网络 搭建旁路由 Golang gRPC 错误处理 编写可维护的单元测试代码 OAuth 2 详解(六):Authorization Code Flow with PKCE OAuth 2 详解(五):Device Authorization Flow OAuth 2 详解(三):Resource Owner Password Credentials Grant OAuth 2 详解(四):Client Credentials Flow OAuth 2 详解(二):Implict Grant Flow OAuth 2 详解(一):简介及 Authorization Code 模式 ElasticSearch 学习笔记 三种git流程以及发版模型 错误处理实践 权限模型(RBAC/ABAC) OIDC(OpenID Connect) 简介 任务队列简介 PostgreSQL 操作笔记 使用Drone CI构建CI/CD系统 Golang migrate 做数据库变更管理 使用PostgreSQL做搜索引擎 Nginx 源码阅读(三): 连接池、内存池 Nginx 源码阅读(二): 请求处理 Nginx 源码阅读(一): 启动流程 Go 泛型简明教程 使用 HTTP Router 处理 Telegram Bot 按钮回调 使用反射(reflect)对结构体赋值 GIN 是如何绑定参数的 你好 2022(2021 年终总结) 用Go导入大型CSV到PostgreSQL 使用 OpenWRT 搭建软路由 使用软KVM切换器 barrier 共享键鼠 SQL 防注入及原理 使用 gomock 测试 Go 代码 gevent不是黑魔法(二): gevent 实现 gevent不是黑魔法(一): greenlet 实现 用 entgo 替代 gorm 应用内使用crontab不是那么方便 单测时要不要 mock 数据库? Sentry 自建指南 用selenium完成自动化任务 用闲置的安卓手机做垃圾电话短信过滤 推荐三个时间管理工具 一次事故反思 当JS遇到uint64:JS整数溢出问题 SQLite3 存储以及ACID原理 Redis源码阅读:pub/sub实现 Redis源码阅读:zset实现 Redis源码阅读:bitmap 位图的运算 Redis源码阅读:set是怎么做交并集运算的? Redis源码阅读:list实现(ziplist, quicklist)
KVM 显卡穿透给 Windows
Jiajun Huang · 2022-03-15 · via Jiajun的技术笔记

很久以前就想这么玩,但是碍于各种条件,一直没有实现,直到最近,得到一块额外的亮机卡,于是就有了这次折腾。 那么通过显卡穿透,我们可以做啥呢?比如:我们可以用Linux做宿主机,虚拟化一个Windows出来,但是Windows使用独显打游戏; 或者我们可以把显卡透传给虚拟机挖矿,等等。我的宿主机是AMD平台,宿主机使用AMD显卡,虚拟机使用Nvidia显卡。

准备

  • 首先我们需要有一个可扩展性较强的电脑,必须要有两个PCIe插槽,分别插上两个显卡,当然如果是Intel的卡,那么可以让宿主机 使用集成显卡,而虚拟机使用独立显卡
  • 要主板和CPU都支持IOMMU,如果不了解这个是什么,那么简单一句话来说,就是支持高性能虚拟化和透传的功能,基本上近几年生产 的主板和CPU都支持,如果想要确认一下,可以参考 wiki 中的做法
  • 安装 libvirt、OVMF 和 virt-manager,我们使用 virt-manager 来配置,这样会方便很多;OVMF是开源的UEFI固件
  • 如果可以的话,准备两个显示器,如果没有的话,那就只能自己把 HDMI 线来回插拔了

开始

设置BIOS并且编辑GRUB

首先我们要设置BIOS,打开IOMMU功能,不过我的是AMD的主板,所以默认就是打开的,接下来则需要编辑GRUB,在启动的时候就告诉 Linux内核要启用透传。

编辑 /etc/default/grub 文件,找到 GRUB_CMDLINE_LINUX_DEFAULT,添加 quiet iommu=pt,因为我的是AMD,所以只要这样 就可以,Intel的我没试过,但是网上说要编辑成:quiet intel_iommu=on iommu=pt

接着重新生成一下GRUB配置文件:

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

将硬件加入黑名单

首先我们要做的事情就是,让 Linux 宿主机忽略某一个显卡,通常,显卡在 Linux 中都会有两个设备,一个 Video 输出,一个 Audio 输出,Linux会为每一个硬件都分配一个ID,我们要找到他们,使用这个脚本,他会自动把 IOMMU 分组情况打印出来:

#!/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 Group 1:
	00:01.0 PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port [8086:0151] (rev 09)
IOMMU Group 2:
	00:14.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller [8086:0e31] (rev 04)
IOMMU Group 4:
	00:1a.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 [8086:0e2d] (rev 04)
IOMMU Group 10:
	00:1d.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 [8086:0e26] (rev 04)
IOMMU Group 13:
	06:00.0 VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] [10de:13c2] (rev a1)
	06:00.1 Audio device: NVIDIA Corporation GM204 High Definition Audio Controller [10de:0fbb] (rev a1)

其中的 8086:01518086:0e3110de:13c2 这些就是硬件ID,我们之后要屏蔽硬件,就靠这个ID。我这里是宿主机使用AMD显卡, 虚拟机使用Nvidia显卡,分别找到它们的硬件ID。

接下来我们编辑文件 /etc/modprobe.d/vfio.conf

softdep nouveau pre: vfio-pci
options vfio-pci ids=8086:0151,8086:0e31,10de:13c2

第一行表示,让 vfio-pci 驱动先于 nouveau 加载,vfio-pci 加载以后,就会把硬件占着,nouveau 是Nvidia显卡的开源驱动, 第二行表示,我们要占用的硬件ID,多个ID用英文逗号连接。

接着重新生成启动镜像:

$ sudo update-initramfs -u

接下来很重要的一步,就是重启。这样我们第一步和第二步所做的更改,才能产生效果。

创建Windows虚拟机

我使用的是Windows 10 LTSC,就和普通创建流程一样,但是在最后一步,勾选 Customize before install,然后在Overview里, 把BISO改成 UEFI,Chipset 改成 i440,UEFI固件选择 /usr/share/OVMF/OVMF_CODE_4M.fd。将磁盘驱动改成VirtIO,添加 virtio-win.iso ,这里面包含的是VirtIO的各种驱动,如果没有的话,从 https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/ 找到最新的下载。

一定要UEFI,否则虚拟机能检测到显卡,但是无法输出信号。我的尝试结果是这样。

接下来就是正常安装了,这里我不会事无巨细的贴出来,因为如果你不会安装的话,穿透是基本没戏了。

透传硬件

安装完成之后,关闭虚拟机,点开详情,点添加,然后选择 PCI Host Device,把前面我们要透传的设备添加进去,记得一定要同时 添加 Video 和 Audio 设备。

接下里很重要的一步,就是要隐藏虚拟机特性,因为Nvidia不让在虚拟机里使用,但是我们可以通过隐藏虚拟机特性规避。 执行 sudo virsh edit --domain win 来编辑你的虚拟机,记得替换成你自己的虚拟机名字。

  • <os> 标签里面,增加 <smbios mode='host'/>
  • <features> 里,增加

    <kvm>
    <hidden state='on'/>
    </kvm>
    
  • <hyperv> 标签里,删掉其他的内容,增加 <vendor_id state='on' value='1234567890ab'/>

然后保存配置,启动虚拟机。打开虚拟机之后,在Windows里安装驱动,或者点击驱动管理,让 Windows 10 自己安装驱动,基本上就搞定了。

穿透声卡和USB

按照上面的步骤,是没有声音的,有两个方案:

  • 继续查看声卡和USB是否是多个IOMMU组,我的是,所以我直接穿透了,虚拟机关机的时候,宿主机照用,虚拟机开机的时候,虚拟机占用
  • 仅穿透USB,或者选择 Add Hardware -> USB Host Device 然后把具体的声音输入输出、USB传进去

最后

最后我们要做什么呢?前文说到,我们如果有两个显示器的话,就比较方便,每个显卡上插一个显示器,如果没有的话,就只能把HDMI 线插到你要用的那个显卡上,或者有的显示器支持两个输入线,然后在显示器的设置里切换信号源。

对于键鼠,如果不想用两套的话,可以在 VirtManager 里分别把USB设备传进去,又或者可以参考 这一篇文章 使用 barrier 来共享一套键鼠。

大功告成!接下里就是愉快的折腾和玩耍了。


参考资料: