Skip to content

Nested virtualization unconditionally disabled on Windows 10 in lifted WSL (regression from inbox WSL2) #40735

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?

  • 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:
    [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:

// 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 (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 (#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 and in Set up a WSL development 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions