Nested virtualization unconditionally disabled on Windows 10 in lifted WSL (regression from inbox WSL2)
- Dominant language
- C++
- Stars
- 33.7k
- Forks
- 1.8k
- Avg merge
- 3d 17h
- Merged PRs (30d)
- 116
Description
This report covers a behavior on Windows 10 hosts where `nestedVirtualization=true` in `.wslconfig` is silently overridden, even on CPUs that support nested virtualization.
### Windows Version
```
Microsoft Windows [Version 10.0.19045.7291]
```
### WSL Version
```
WSL version: 2.8.11.17
Kernel version: 6.18.26.3-1
WSLg version: 1.0.77
MSRDC version: 1.2.6676
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.26100.1-240331-1435.ge-release
Windows version: 10.0.19045.7291
Commit: 9ab38e95
```
This was a local build of `microsoft/WSL` at commit `9ab38e9`.
### Are you using WSL 1 or WSL 2?
- [x] WSL 2
### Kernel Version
```
Linux DESKTOP-67D2DFE 6.18.26.3-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Wed May 27 22:03:21 UTC 2026 x86_64
```
### Distro Version
Oracle Linux Server 9.7. Also reproduced on Ubuntu 24.04.
### Other Software
- Host CPU: Intel Core i5-6300U (Skylake-U). VMCS Shadowing is supported on Haswell and later, so this CPU is hardware-capable of nested virtualization.
- Hyper-V root partition is up. `Microsoft-Hyper-V`, `HypervisorPlatform`, and `VirtualMachinePlatform` are all enabled.
### Repro Steps
1. On a Windows 10 22H2 host with an Intel CPU that supports VMCS Shadowing, install WSL from the Microsoft Store or from a build of the open-source repo.
2. Create `%USERPROFILE%\.wslconfig` with:
```ini
[wsl2]
nestedVirtualization=true
```
3. Run `wsl --shutdown`, then start any WSL2 distro.
4. Inside the distro, run `ls /dev/kvm` and `grep -E "vmx|svm" /proc/cpuinfo`.
### Expected Behavior
`/dev/kvm` exists inside the WSL2 VM and `vmx` is present in `/proc/cpuinfo`. The `nestedVirtualization=true` setting in `.wslconfig` is honored on every host whose CPU supports nested virtualization. This was the behavior of the in-box WSL2 on Windows 10 19044 and 19045.
### Actual Behavior
`/dev/kvm` is absent and `vmx` is not present, regardless of the `.wslconfig` setting. The lifted WSL service skips the HCS processor-feature lookup on Windows 10 and writes `ExposeVirtualizationExtensions = false` into the compute system config.
The code is at [`src/windows/service/exe/WslCoreVm.cpp` lines 1508-1530](https://github.com/microsoft/WSL/blob/9ab38e9/src/windows/service/exe/WslCoreVm.cpp#L1508-L1530):
```cpp
// N.B. This is done because arm64 and some older amd64 processors do not support nested virtualization.
// Nested virtualization not supported on Windows 10.
if (m_vmConfig.EnableNestedVirtualization)
{
try
{
if (wsl::windows::common::helpers::IsWindows11OrAbove())
{
const auto& processorFeatures = wsl::windows::common::hcs::GetProcessorFeatures();
auto feature = std::find(processorFeatures.begin(), processorFeatures.end(), "NestedVirt");
m_vmConfig.EnableNestedVirtualization = (feature != processorFeatures.end());
}
else
{
m_vmConfig.EnableNestedVirtualization = false;
}
vmSettings.ComputeTopology.Processor.ExposeVirtualizationExtensions = m_vmConfig.EnableNestedVirtualization;
if (!m_vmConfig.EnableNestedVirtualization)
{
EMIT_USER_WARNING(wsl::shared::Localization::MessageNestedVirtualizationNotSupported());
}
}
...
}
```
The check is on the Windows major version, not on the underlying CPU. A Win10 host with an i9-13900K is treated the same as a host with an Atom that genuinely cannot do nested virtualization. The HCS feature query that already exists for the Win11 path (`hcs::GetProcessorFeatures()` looking for `"NestedVirt"`) would answer the same question correctly on Win10.
### When the gate landed
The disable-on-Win10 effect was present at the initial open-source release. Commit [`697572d6`](https://github.com/microsoft/WSL/commit/697572d664c9371abbc53cab9cf7b4b32be1980e) (2025-05-15, "Initial open source commit for WSL") introduced the file with `processorFeatures` retrieval already wrapped in `if (IsWindows11OrAbove())`. On Win10 the vector stayed empty, the subsequent `std::find` failed, and `EnableNestedVirtualization` collapsed to `false`. Same observable result, just implicit.
Commit [`6f47fa9b`](https://github.com/microsoft/WSL/commit/6f47fa9b202fe41704e3c559b38b33a64aaa1387) ([#13971](https://github.com/microsoft/WSL/pull/13971), 2026-01-06, "diagnostics: improve logging of hcs helper utilities on debug builds") made the disable explicit by moving the HCS lookup and the `find` inside the `IsWindows11OrAbove()` block and adding an `else { EnableNestedVirtualization = false; }` branch.
### Why I am calling this a regression
The in-box WSL2 that shipped in Windows 10 builds 19041 through 19045 exposed `vmx` to the WSL2 guest on hosts whose CPUs supported nested virtualization. After moving to the lifted WSL (Microsoft Store or open-source build), the same hardware on the same Windows 10 22H2 host no longer exposes nested virtualization, even with `nestedVirtualization=true` in `.wslconfig`.
### Suggested fixes
In increasing order of effort:
1. Remove the `IsWindows11OrAbove()` gate. Let `hcs::GetProcessorFeatures()` decide on all supported Windows versions. The existing `MessageNestedVirtualizationNotSupported` warning is already in place for hosts where HCS reports no `NestedVirt` feature.
2. Keep the gate but respect `nestedVirtualization=true` from `.wslconfig` as an explicit opt-in override on Windows 10, with a logged warning that the path is unsupported. Users on compatible hardware get the feature back. Users on incompatible hardware see a clear message instead of a silent disable.
3. Document the Windows 10 limitation in the [`.wslconfig` reference](https://learn.microsoft.com/en-us/windows/wsl/wsl-config) and in [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment). The current docs do not mention that `nestedVirtualization` is ignored on Win10.
Happy to test a patch on this hardware.
### Diagnostic Logs
None attached. The behavior is fully reproducible from the source path above. If a service trace would help, glad to capture one with `wsl --debug-shell` or similar.
Contributor guide
Research direction
Start in src/windows/service/exe/WslCoreVm.cpp around lines 1508-1530 and compare the Windows 10 and Windows 11 paths for hcs::GetProcessorFeatures(). Reproduce the issue with nestedVirtualization=true on Windows 10, then verify completion by checking that /dev/kvm exists and vmx appears in /proc/cpuinfo on supported hardware without breaking the unsupported-CPU warning path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100