前言
你是否被 GNU/Linux 的图形化界面 X11 所困扰,架构老旧,配置复杂,bug多。以Gentoo为例,启用X会导致安装很多库,依赖复杂不说,要是使用独显的话,开源的nouveau体验很糟糕,发挥不出显卡性能;使用官方闭源驱动nvidia-drivers,它对非x86机器支持很差 Raspberry Pi support (arm64)?,你不光要接受EULA,而且每次编译安装kernel的时候都要用nVidia那一套闭源工具重新编译和内核对应的nvidia.ko。这就太不优雅了!X11没有厂商支持,历史包袱太重,我想如果没有X,那么 Linux 新手的问题可能会减少90%。
windows 10 就不存在这个问题,用户基础巨大,上游官方支持完善。对于非Linux图形开发者来说,抛弃X11可能是一个更理智的选择。
为什么不用微软现成的windows+wsl方案呢?
- wsl本质是虚拟器,wsl的linux kernel无法直接和硬件打交道
- wsl真正支持得好的linux发行版有限,只有Windows Subsystem for ubuntu这种杂交产物用户多且稳定,用于日常工作尚可,但可定制性差,自由度差
从实现来说这和windows+wsl没有本质区别,相当于手搓一个Linux+lsw
虚拟机
如何把 Linux + windows 10 融合在一起呢?虚拟化技术使windows10虚拟机有接近原生的体验
虚拟机按照运行的层次分为两种:
type I 虚拟机是直接运行在物理硬件上,CPU 核心提供一个hypervisor层供虚拟化系统调度,一般不支持非同架构的guest。因此性能损失极小,是现代企业级虚拟化和云平台服务的基石。VMware ESXi,Microsoft Hyper-V,Xen,KVM都是type I虚拟机成功的典范。
type II 虚拟机作为应用程序运行在宿主操作系统上,依赖宿主管理硬件,通过指令翻译层可以支持跨架构虚拟化。性能较差
qemu+kvm的运行效率已经非常高了,这得益于
- intel vt-x(amd-v) 技术,cpu增加了vmx模式,在硬件层面实现了虚拟化
- Intel vt-d(IOMMU) 技术,作为vt-x的补充,为设备的PCIe passthrough直通提供可行性。允许linux kernel把设备直接呈现给虚拟机,性能如同虚拟机直接使用一样
既然微软可以拥抱开源社区,推出WSL,把 Linux 子系统集成到 windows。那我们也可以拥抱闭源社区,把 windows子系统 集成到 Linux
这样,一方面我们拥有定制kernel的自由,另一方面我们不需要折腾X11来满足日常使用
架构图
在我的机器上
- 显卡分配
- gentoo host 独占 intel 核显
- windows guest 独占 nVidia 独显
- 键盘鼠标分配:通过usb passthrough全部给guest使用
- 文件共享服务:在host安装samba server,然后在windows中映射网络驱动器
- 登录
- guest 到 host 登录: ssh 10.0.2.2 使用和管理 Linux
- host 到 guest 登录: ssh localhost :4444, 进入powershell后 运行wsl ~即可使用cuda,让封闭的nvidia软件栈在封闭的windows10中继续发挥应有的作用
主板 firmware 设置
打开主板 bios/efi 的 VT-d 和 IOMMU 选项,此时从 /proc/cpuinfo 能看到 vmx(intel) 或者 svm(amd) 。arm64需要打开 smmu。
内核配置
1 | enable iommu: |
host os可以不安装任何显卡/PCIe设备驱动。编译安装kernel
内核启动参数
1 | iommu=pt intel_iommu=on |
给系统对应的bootloader,例如grub、lilo增加内核参数
我这里没有安装bootloader,使用的 EFI stub 直接启动内核,所以需要更新 efi boot entry
1 | efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "Gentoo 6.13.0-rc4" --loader " \EFI\Gentoo_testing\bzImage-6.13.0-rc4.efi" -u "root=/dev/nvme0n1p2 intel_iom |
配置 PCIe passthrough 设备
编辑 /etc/modprobe.d/vfio.conf,让Linux对直通设备使用vfio驱动而非设备驱动
1 | options vfio-pci ids=xxxx:xxxx,xxxx:xxxx,xxxx:xxxx |
当然也可以手工卸载设备,绑定vfio驱动
1 | gpu="0000:01:00.0" |
启动虚拟机qemu
我这里用qemu 9.2.3
自己编译的话建议打开 io-uring、usb passthrough、vhost-net、virtfs 选项
创建虚拟硬盘
1 | qemu-img create -f qcow2 win11.qcow2 1024G |
启用嵌套虚拟化
为了在windows10中可以正常使用wsl或者hyper-v,需要打开kvm嵌套虚拟化
1 | cat /sys/module/kvm_intel/parameters/nested |
启动虚拟机
1 | qemu-system-x86_64 \ |
- cpu 使用host会导致 windows guest系统开启虚拟机功能无法进入系统,所以选择Skylake-Client-noTSX-IBRS
- hypervisor=off 避免kvm向windows报告它本身运行在虚拟化环境 forum.proxmox.com,否则systeminfo hyperv会返回 已检测到虚拟机监控程序。将不显示 hyper-v 所需的功能
- vmx=on 为虚拟机打开vt-x功能,默认应该就是打开的
- mpx=off 禁用后提高兼容性,否则可能进不去windows10系统 superuser.com
- vfio-pci 配置 pcie 直通
- usb-host 配置 usb键盘鼠标 直通,把host的键鼠给guest用
- hostfwd=tcp::4444-:22 映射localhost:4444 到windows10 openssh端口
安装windows10
1 | <qemu command line> -boot d -cdrom /path/to/windows10.iso |
正常安装win10即可,微软会自动下载nVidia显卡驱动,接下来安装ubuntu 24.04 Linux子系统
- 从Linux子系统登录到host系统可以直接ssh 10.0.2.2
- 如果想从host登录到Linux子系统,需要给windows10安装 Win32-OpenSSH,再从powershell进入wsl
安装pytorch
按照官方教程,在wsl安装pytorch非常容易
1 | pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126 |
值得注意的是,安装pytorch不需要安装cuda和cudnn!编译pytorch的时候才需要。很多人以讹传讹,给新手造成了困扰。仅仅是跑pytorch,pytorch+driver足够了
总结
最后,就是配置一下windows10了,安装好自己喜欢的软件 vscode、Termius/xshell/MobaXterm、steam、modelsim、vivado,远离x11,流畅的游戏,开心的使用电脑吧
如果硬件不支持IOMMU怎么办?
VFIO no-IOMMU mode for qemu
我也没有找到解决方法
树莓派、intel老架构(haswell、ivy-bridge)部分型号、龙芯等很多平台是不支持iommu的,我尝试打开noiommu模式来使用vfio-pci,这里记录下失败的经历供后来者参考
VFIO no-IOMMU mode for qemu
在没有 iommu 的平台上,通过打开 vfio enable_unsafe_noiommu_mode 强制使用vfio
1 | modprobe vfio enable_unsafe_noiommu_mode=1 |
加载vfio驱动
1 | gpu="0000:01:00.0" |
此时,可以看到字符设备
1 | /dev/vfio/noiommu-3 |
因为安全问题,qemu不支持noiommu mode,
我找到了一个比较老的patch,因为noiommu DMA安全问题而没有被接受,apply到qemu 2.12上
https://github.com/996refuse/qemu-noiommu
1 | mkdir build && cd build |
编译不需要安装,运行
1 | ./build/x86_64-softmmu/qemu-system-x86_64 -smp 2 -drive file=debian-12-nocloud-amd64.raw -m 4G -device vfio-pci,host=0000:01:00.0 -nographic -bios /usr/share/edk2-ovmf/OVMF_CODE.fd |
x86_64
报错
1 | RmInitAdapter failed! (0x25:0x65:1480) |
raspberry pi 5
在树莓派5尝试qemu-noiommu会报错
1 | Bus error |
估计和老版本qemu对arm的支持太差有关,感觉把patch移植到qemu9.2太耗费精力了,等以后有闲工夫再探索吧
有趣的是,树莓派5是支持iommu的,但板载接口PCIe2.0 x1似乎不支持走iommu。我在forum提出了这个问题
is IOMMU groups over PCIe supported by raspberrypi 5 ?
https://github.com/AlbrechtL/openwrt-docker/issues/38
https://github.com/raspberrypi/linux/issues/6834
qemu vm里无法驱动rtx 3060ti的可能性非常多,qemu、nVidia rtx3060ti、vfio、iommu 可能花费很多时间都无法修复
refer
GPU passthrough Gentoo wiki
PCI_passthrough_via_OVMF archlinux wiki
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章