先说我这边遇到的场景吧。前阵子为了在Windows上跑ARM64的OpenEuler和Alpine镜像,我用了QEMU。当时照着一些老教程折腾,为了让QEMU的TCG模拟不那么卡,我在BIOS里关了虚拟化,也跟着把Windows的“虚拟机平台”功能给勾掉了。结果等我想回WSL2里继续跑CUDA相关的东西时,WSL2直接起不来了,提示虚拟化已禁用。最麻烦的是,本来在WSL2里配好的PyTorch和CUDA环境全部报废,ComfyUI那类依赖torch.cuda的脚本在Windows侧跑也各种报错。这篇文章就是把当时一步步排查、恢复WSL2虚拟化、最后重新跑通CUDA的完整过程记录下来,给同样被QEMU折腾完又卡在WSL2上的朋友一个参考。
1. 事故现场:WSL2 起不来,torch.cuda 先报警
1.1 症状清单:不是“WSL 启动慢”,而是虚拟化底座整个掉了
当时的情况很有代表性。我先在Windows终端里执行了wsl --status,输出显示默认版本是2,但下面直接跟着一行“虚拟化已禁用”。再尝试启动Ubuntu-24.04,窗口闪一下就没了,有时候还会弹WSL 2 尚未准备就绪的错误框。这不是平时那种“WSL启动慢”或者“下载发行版超时”的问题,而是WSL2赖以运行的Hypervisor层根本没加载。
同一时间,Windows侧的PyTorch也出现了奇怪的问题。在我常用的ComfyUI环境里,Python路径是d:\comfyui_image\python\lib\site-packages\torch\cuda\__init__.py,运行时出现了CUDA initialization的UserWarning。具体表现是torch.cuda.is_available()返回False,或者报“NVIDIA driver too old”这类奇怪信息。我知道Windows侧驱动其实是正常的,因为游戏和普通桌面应用都能用GPU,问题出在WSL2里的Linux侧完全失去了GPU直通能力。
如果你手头也有VMware或其他虚拟机软件,症状会更明显。VMware Workstation会直接弹“此平台不支持虚拟化的AMD-V/RVI”,或者报“模块tv启动失败”。另外VBox弹类似“硬件虚拟化已禁用”也常见。这些表面上看是VMware/QEMU的问题,根子都在Windows虚拟化栈上。
下面是当时我整理的快速症状对照表:
| 现象 | 可能的直接原因 | 最先排查的方向 |
|---|---|---|
wsl --status显示虚拟化已禁用 | Hypervisor未随系统启动,或虚拟机平台功能被关 | bcdedit /enum、Windows功能列表 |
| WSL2发行版启动闪退 | Hyper-V后端缺失,或“虚拟机平台”可选功能未启用 | “启用或关闭Windows功能”勾选状态 |
| VMware报“AMD-V/RVI不支持” | BIOS虚拟化被关,或hypervisorlaunchtype=Off | BIOS设置、bcdedit输出 |
| PyTorch报CUDA初始化失败/Warning | WSL2 GPU直通链路断裂,和Windows驱动无关 | WSL内ls /dev/dxg、nvidia-smi |
1.2 为什么 CUDA 用户最怕 WSL2 挂掉
很多人不理解,为什么WSL2挂了会牵连CUDA。WSL2的GPU方案和传统虚拟机不一样:它不是把GPU设备整个直通给Linux,而是Windows侧的NVIDIA驱动维护一个GPU paravirtualization接口,Linux侧通过/dev/dxg访问这个接口。CUDA Toolkit在WSL-Ubuntu版本里会调用这个设备节点,从而把计算请求转发到Windows驱动,再落到物理显卡上。
这个架构的优点很明确:Linux侧不需要单独装NVIDIA Linux驱动,只要Windows侧驱动版本够新,WSL2里就能用CUDA。缺点也明显:一旦WSL2虚拟机无法启动,或者/dev/dxg不能正常暴露,Linux侧所有CUDA程序瞬间瘫痪。对依赖Linux侧生态的人来说,比如跑PyTorch、ComfyUI、深度学习训练脚本,WSL2挂掉意味着整套本地实验环境都断了,不是“重装个驱动”能解决的事。
我自己的习惯是:CPU多核重型编译放到Windows直接跑,Python和GPU计算尽量在WSL2里做,环境隔离干净,不像在Windows原生Python里容易被各种路径问题搞乱。所以WSL2一旦起不来,我的开发流就卡死了。
2. 根因拆解:QEMU 为什么能把 Windows 的虚拟化栈搞崩
2.1 WSL2 和 Hyper-V 的依赖关系,先把它理清楚
WSL2本质上是一个轻量级虚拟机,它跑在微软自己的Hypervisor上。Windows里有一个叫“虚拟机平台”的可选功能,开启后系统会启用Hyper-V的虚拟化底座。与此同时,还有一个更底层的开关叫hypervisorlaunchtype,它决定Windows在引导时是否把Hypervisor加载起来。
很多人以为只有安装了“Hyper-V管理器”才算开启了Hyper-V,这是误解。就算你从来不用Hyper-V管理器界面,只要WSL2能用,说明Hypervisor已经以系统服务的形式在底层运行了。你看到的“Hyper-V”开关只是管理界面,真正的Hypervisor是开机时通过引导配置加载的,和界面完全无关。
QEMU的问题就在这。QEMU在Windows上跑ARM64镜像时,经常要跟这个Hypervisor打交道。很多教程会告诉你“关闭Hyper-V,不然QEMU性能差”,这个建议在某些远古版本的QEMU上确实没错,因为旧版QEMU的WHPX后端还不成熟,TCG纯软件模拟反而更稳定。但关掉Hyper-V的同时,WSL2的命根子也没了。我当初就是照着这种教程,把虚拟化相关的东西能关就关,结果把自己坑了。
2.2 QEMU 的两条运行路径:TCG 和 WHPX,分别踩了哪些雷
QEMU在Windows下模拟ARM64有两种主要加速方式。
第一种是TCG,全称Tiny Code Generator。它不依赖硬件虚拟化,通过动态二进制翻译来模拟CPU指令。这种方式兼容性最好,哪怕CPU完全不支持虚拟化也能跑,但速度感人,尤其是在模拟ARM64这种跨架构场景下,指令翻译开销极大。网上那些“为了QEMU性能关闭硬件虚拟化”的建议,通常就是针对TCG模式说的。在Windows上跑ARM64系统,如果不开WHPX,TCG就是默认后端。问题是,为了TCG跑得顺,去把BIOS虚拟化关了、把虚拟机平台关了,最终受影响的包括WSL2、Windows沙盒、甚至部分安全功能。这是第一类大坑。
第二种是WHPX,全称Windows Hypervisor Platform。它需要Windows的Hypervisor已经启动,也就是说hypervisorlaunchtype=auto且“虚拟机平台”功能已开启。WHPX把QEMU的虚拟机执行请求转交给Hyper-V的Hypervisor处理,性能比TCG好太多,特别是CPU密集型的ARM64模拟,能接近原生虚拟化的体验。但它依赖的正是WSL2也依赖的那套底座。如果这套底座本身坏了,比如hypervisorlaunchtype被改成Off,QEMU的WHPX后端同样会报错。
所以真相是:QEMU本身并不会“故意”弄坏WSL2,真正的问题在于我们为了QEMU的某些模式,手动把虚拟化相关的开关关掉了,结果把WSL2的依赖一并拆掉。
2.3 还有一个暗坑:VBS 和内存完整性,也会被误伤
除了上面两条路线,Windows 11还有一个容易被忽视的组件:基于虚拟化的安全,也就是VBS。Win11默认开启内核隔离里的内存完整性功能,它依赖Hypervisor来保护内核。部分优化教程为了让QEMU或者老游戏跑得更顺,会指导用户关闭“内存完整性”,甚至通过注册表把VBS整个关掉。
问题在于,VBS和WSL2共享同一个Hypervisor基础。如果你把VBS关了,系统里某些依赖虚拟化安全的组件会进入异常状态,WSL2虽然不一定立刻崩,但和VMware、QEMU共存时容易出现各种玄学问题,比如VMware启动时报“模块hv启动失败”,或者Windows沙盒打不开。更隐蔽的是注册表里的Device Guard设置,它可以在界面完全看不出来的情况下影响Hypervisor的加载状态。
这台机器当初为了QEMU折腾过一轮,VBS状态已经不可控了。后来排查时发现,Win32_DeviceGuard里的VirtualizationBasedSecurityStatus显示为0,也就是VBS彻底关闭状态,这基本就是注册表被改过或者内存完整性被关过的痕迹。
3. 排查五步走:从 BIOS 到事件日志,逐层定位故障点
3.1 第一步:重启进 BIOS,确认 VT-x/AMD-V 没被关
排查的首要任务,是先把最底层的硬件虚拟化开关确认一遍。按机器不同,进BIOS的按键可能是Del、F2、F10或Esc。重点找这几项:
| 平台 | BIOS项名称 | 需要的状态 |
|---|---|---|
| Intel | Intel Virtualization Technology / VT-x | Enabled |
| AMD | SVM Mode | Enabled |
| Intel | VT-d(可选) | Enabled,和WSL2关系不大,但影响DMA直通 |
我见过不少案例是恢复BIOS默认设置后,VT-x被恢复成Disabled,而用户毫不知情。Windows里看起来“系统信息”显示虚拟化已启用,但BIOS实际关了,这种不一致最容易误导人。
进入Windows后,按Ctrl+Shift+Esc打开任务管理器,切到“性能”标签,点CPU,右下角能看到“虚拟化”状态。如果是“已启用”,说明BIOS层面OK;如果是“已禁用”,先回去把BIOS打开再说。这一步不做好,后面所有Windows层面的修复都白搭。
3.2 第二步:检查 Windows 可选功能,勾选状态要三个一起看
按Win+R,输入optionalfeatures打开“启用或关闭Windows功能”。重点关注以下几项:
- 虚拟机平台(VirtualMachinePlatform)
- 适用于Linux的Windows子系统(Microsoft-Windows-Subsystem-Linux)
- Windows虚拟机监控程序平台(HypervisorPlatform,也就是WHPX的接口)
- Hyper-V(包含管理工具和Hyper-V平台,可选但建议装)
这里有个常见误区:有人只勾了“适用于Linux的Windows子系统”,漏了“虚拟机平台”,结果WSL2要么跑不了,要么从WSL1升级到WSL2时一直卡住。还有人只装了“Hyper-V”而没装“虚拟机平台”,WSL2依然不正常。正确做法是“虚拟机平台”必勾,“适用于Linux的Windows子系统”必勾,“Windows虚拟机监控程序平台”建议勾,因为它正是QEMU的WHPX后端需要的东西,也能让虚拟机软件更好地和Hyper-V共存。
勾选完成后会提示重启,但先别急,后面还要用命令行确认一遍,因为图形界面的勾选有时候不会完整生效。
3.3 第三步:用 msinfo32 看 Hyper-V 底座的最终状态
这是很多人忽略的一步。按Win+R,输入msinfo32,打开系统信息,拉到最下面的“Hyper-V要求”一栏。正常情况下会显示三行:
- 固件中已启用虚拟化:是
- 虚拟化已启用:是
- Hyper-V:检测到Hyper-V。此计算机上运行的虚拟机监控程序可保护虚拟机管理器的安全。
如果第三行显示的是“出现错误”,或者“未检测到Hyper-V”,说明Hypervisor没有正确加载。这个信息比WSL2自己的报错更底层,因为它直接涉及Windows引导加载的Hypervisor状态。
我当时看到的就是第三行那里出现了错误。这也解释了为什么WSL2和VMware同时报“虚拟化不可用”之类的问题,因为Windows层面的Hypervisor根本没起来。
3.4 第四步:用 bcdedit 和 wsl --status 做双保险确认
打开管理员权限的命令提示符或PowerShell,依次执行:
bcdedit /enum {current}在输出里找到hypervisorlaunchtype这一项。正常值是Auto,如果显示Off,那基本就是问题根源。执行下面的命令查看WSL状态:
wsl --status如果WSL2可用,会显示“默认版本:2”以及内核版本等信息;如果显示“虚拟化已禁用”,那就是Hypervisor没加载。
另外建议看一眼事件查看器。打开事件查看器,展开“Windows日志”->“系统”,筛选来源为Hyper-V或Hyper-V-High Availability的错误,时间点对应WSL2开始出问题的时间,可以帮助确认是不是有组件在启动时失败。
这一步走完,就能确定故障层:是BIOS关了、Windows功能没勾、还是hypervisorlaunchtype被改成了Off。绝大多数因为QEMU折腾过机器的案例,都栽在最后一个。
4. 修复方案:一条 bcdedit 命令加上 Windows 功能重开
4.1 最直接的修复:hypervisorlaunchtype 改成 auto
既然问题出在Hypervisor没随系统启动,那最核心的一步就是把引导配置改回来。在管理员命令提示符里执行:
bcdedit /set hypervisorlaunchtype auto然后重启电脑。这一步的意义是告诉Windows引导加载器:开机时要把Hypervisor装载起来。只有Hypervisor跑起来了,WSL2、Windows沙盒、VMware的Hyper-V共存模式才能正常工作。
重启后再次确认:
bcdedit /enum {current}看到hypervisorlaunchtype的值是Auto就没问题了。同时msinfo32里Hyper-V那一项应该也能看到“检测到Hyper-V”而不是“出现错误”。
有些极端情况是hypervisorlaunchtype这一项根本不存在,此时可先执行bcdedit /set hypervisorlaunchtype auto,正常情况下它会自动创建该项并设为Auto。
4.2 用 DISM 把可选功能重新装配好,比手动勾选更靠谱
光改引导配置还不够,Windows功能里的“虚拟机平台”也得确保开启。推荐用DISM命令而不是图形界面,因为DISM能明确显示每个功能的启用状态,还能避免漏项。
管理员PowerShell里依次执行:
dism /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart dism /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism /online /enable-feature /featurename:HypervisorPlatform /all /norestart如果想把Hyper-V管理工具也一并装回来:
dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /all /norestart执行完后再重启一次。重启后打开optionalfeatures确认三项都已勾选。如果之前某个功能是被手动卸载过的,这种DISM方式能把它们完整装回来,比图形界面更可靠。
另外建议顺手更新一下WSL内核:
wsl --update这个命令会把WSL2内核更新到最新版本,有时候旧内核和新Hypervisor之间也有兼容问题。
4.3 如果 QEMU 动过 VBS/Device Guard:把虚拟化安全找回来
如果你像我一样曾经为了让QEMU更流畅而关过VBS,那还需要把虚拟化安全相关设置恢复。在管理员PowerShell里检查当前状态:
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard | Select-Object VirtualizationBasedSecurityStatusVirtualizationBasedSecurityStatus的值:
| 值 | 含义 |
|---|---|
| 0 | VBS已关闭 |
| 1 | VBS已启用但未运行 |
| 2 | VBS已启用且正在运行 |
如果显示0,说明VBS被关了。最简单的恢复方式是打开“Windows安全中心”->“设备安全性”->“内核隔离”,开启“内存完整性”,然后重启。如果界面开关是灰的,或者提示设备不支持,可以检查注册表:
HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard在右侧新建或修改DWORD值EnableVirtualizationBasedSecurity为1。同时检查:
HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity把Enabled的值设为1。
注意:开启内存完整性后,部分老驱动可能不兼容,如果有驱动签名问题,需要先更新驱动再开启。VBS本身不是WSL2的绝对依赖,但关闭它会导致和QEMU、VMware共存时出现各种莫名冲突,所以我个人建议能开就开。
4.4 清理 QEMU 相关的残留影响
如果你的QEMU是安装版,或者手动添加过环境变量、系统服务,建议检查一下有没有自带开机启动项、虚拟网卡或驱动残留。这些不一定会直接影响WSL2,但有概率干扰Hyper-V的某些组件。检查方式:
- 按Win+R输入
services.msc,看有没有QEMU相关的服务。 - 打开设备管理器,查看网络适配器中有没有QEMU虚拟网卡,如果有且不再使用,右键卸载。
- 检查环境变量Path里是否还有QEMU的路径,留着没问题,但确认没有多个QEMU版本混用。
真正要注意的是,如果当初为了QEMU安装过WinPcap之类的抓包组件,它和WSL2的虚拟交换机偶尔会有DNS或网络层面的冲突。不需要的时候可以卸载,但这跟虚拟化启停没有直接关系。
5. 验证闭环:WSL2 活了,CUDA 也得验一遍
5.1 WSL 侧检查内核和 GPU 设备节点
修复完成后,先打开WSL2终端,确认虚拟化底座和WSL2内核都正常:
uname -r能看到类似5.15.x.x-microsoft-standard-WSL2的输出就说明WSL2内核跑起来了。再检查GPU直通设备:
ls /dev/dxg如果存在/dev/dxg,说明WSL2的GPU paravirtualization接口已经暴露给Linux侧。接着运行:
nvidia-smi正常情况下能看到显卡型号和驱动版本。这里显示的驱动版本号是Windows侧驱动的版本,因为WSL2里不装Linux驱动,全靠Windows驱动转发。如果nvidia-smi不存在,说明CUDA Toolkit还没装好,或者PATH里没有NVIDIA的bin目录。
5.2 Windows 侧 NVIDIA 驱动需要配合 WSL2,别装反了
WSL2的CUDA方案有个容易踩的坑:在WSL2里安装NVIDIA的Linux版驱动。这是完全错误且没必要的操作。WSL2里的GPU不是通过PCIe直通访问的,而是通过微软的GPU虚拟化接口转给Windows驱动,所以Linux侧只需要CUDA Toolkit,绝对不要安装NVIDIA-Linux-x86_64.run这种驱动包。一旦装了,反而可能把/dev/dxg链路弄乱,导致nvidia-smi识别异常。
Windows侧则必须安装支持WSL2的NVIDIA驱动。现在的主流Game Ready和Studio驱动都支持WSL2,关键是版本不能太旧。建议直接去NVIDIA官网下载最新驱动,安装时选择“自定义安装”,勾选“执行清洁安装”。装完重启,再回WSL2里跑一次nvidia-smi。
5.3 用一个小矩阵跑通 CUDA 和 PyTorch
验证CUDA最稳的方法,是编译运行NVIDIA官方的deviceQuery示例,或者直接用Python调一下PyTorch。先装CUDA Toolkit,推荐用WSL-Ubuntu对应的runfile版本。这里以CUDA 12.8为例,从NVIDIA官网下载cuda_12.8.x_linux.run后执行:
wget https://developer.download.nvidia.com/compute/cuda/12.8.0/local_installers/cuda_12.8.0_550.54.15_linux.run sudo sh cuda_12.8.0_550.54.15_linux.run --toolkit --silent注意加--toolkit,只装Toolkit,不装驱动。装完后配置环境变量:
echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc然后验证:
nvcc -V能输出版本信息说明Toolkit装好了。再去编译官方示例:
cd /usr/local/cuda/samples/1_Utilities/deviceQuery sudo make ./deviceQuery如果看到Result = PASS,说明CUDA链路完全打通。
要是你主要跑PyTorch,直接在WSL里装对应版本的torch即可:
pip install torch --index-url https://download.pytorch.org/whl/cu124装完后执行:
python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))"输出类似2.x.x True NVIDIA GeForce RTX 4060 Ti,就代表WSL2里的CUDA环境彻底恢复了。如果输出False,多半是Windows侧驱动版本和PyTorch要求的CUDA版本不匹配,先升级Windows驱动。
6. 防再炸经验:QEMU、WSL2、VMware 共存的三个底线
6.1 永远先确认 hypervisorlaunchtype,再谈第三方虚拟化
这台机器折腾完以后,我的经验教训就一条:既然主力开发环境是WSL2,那Windows的Hypervisor决不能关。任何第三方虚拟化软件,包括QEMU、VMware、VirtualBox,都要在Hypervisor已启动的前提下使用,而不是试图关闭Hypervisor来绕过兼容性问题。
QEMU在Windows上跑ARM64镜像时,优先使用WHPX后端,命令大致是:
qemu-system-aarch64 -machine virt -cpu cortex-a76 -accel whpx ...这样QEMU和WSL2共用同一个Hypervisor,互不干扰。虽然WHPX模式在QEMU上对某些版本可能有小问题,但比TCG快太多,也安全太多。
至于VMware,新版Workstation在Windows 10/11上可以使用Windows Hypervisor Platform实现共存,不需要关闭Hyper-V。旧版本确实和Hyper-V冲突,那种情况就该弃用旧版,而不是关Hyper-V。
6.2 动“Windows功能”和BIOS之前,先备份 bcd
修改引导配置前,务必做个备份。一条命令的事:
bcdedit /export C:\bcd_backup需要恢复时执行:
bcdedit /import C:\bcd_backup另外,改BIOS设置前用手机拍张照记录原设置,改Windows功能勾选项前也一样。我这次排查浪费了不少时间,就是因为不记得当初到底关了哪些东西,只能全凭猜。
如果你按本文的顺序操作完,WSL2能正常启动,但某天又突然出现“虚拟化已禁用”或者VMware报“模块hv启动失败”,先别急着重装系统,按下面这个顺序查一遍:
| 检查项 | 命令/位置 | 正常值 |
|---|---|---|
| BIOS虚拟化 | 开机进BIOS,或任务管理器CPU页 | 已启用 |
| hypervisorlaunchtype | bcdedit /enum {current} | Auto |
| 虚拟机平台功能 | optionalfeatures | 已勾选 |
| VBS状态 | PowerShell查Win32_DeviceGuard | 2 |
| WSL内核 | wsl --update | 最新 |
6.3 遇到“此平台不支持虚拟化”不再慌:一份快速自查清单
最后分享一个快速自查的顺序,这基本上是我遇到所有虚拟化相关报错都会走一遍的路径:
- 先看任务管理器CPU页的“虚拟化”是否“已启用”。
- 运行
msinfo32,看“Hyper-V要求”第三行。 - 管理员命令行里跑
bcdedit /enum {current},确认hypervisorlaunchtype。 - 打开
optionalfeatures,确认“虚拟机平台”和“适用于Linux的Windows子系统”都勾着。 - 管理员PowerShell里确认VBS状态。
这套走下来,90%的“此平台不支持虚拟化”“模块hv启动失败”“虚拟化已禁用”问题都能定位到具体是哪一层断了。
我自己后来在Windows上跑ARM64镜像,只走QEMU加WHPX这条路,GPU计算全部交给WSL2,两边相安无事。这套组合稳定跑了大半年,再没出过虚拟化方面的幺蛾子。如果看完这篇文章的你也正好卡在同一个坑里,按上面的顺序走一遍,大概率不用重装系统就能救回来。