Add nested virtualization support for WSLC containers - #41257
Add nested virtualization support for WSLC containers#41257Ben Hillis (benhillis) wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds opt-in nested virtualization support for WSLC (wslc) container sessions by introducing a feature flag that enables virtualization extensions in the utility VM, mounting kernel modules via a dedicated guest protocol message, loading the appropriate KVM module in the guest, and exposing /dev/kvm inside containers.
Changes:
- Add
WslcFeatureFlagsNestedVirtualization/WSLC_SESSION_FEATURE_FLAG_NESTED_VIRTUALIZATIONand wire it through service + SDK flag validation/mapping. - Gate
ExposeVirtualizationExtensionson HCS nested-virt support, failing session creation with a localized user error when unsupported. - Add a new guest protocol message to mount the modules VHD and optionally load the vendor-specific KVM module; pass
/dev/kvminto containers for nested-virt sessions.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/windows/wslcsession/WSLCVirtualMachine.h | Adds MountModules helper declaration for the new modules-mount protocol. |
| src/windows/wslcsession/WSLCVirtualMachine.cpp | Switches modules VHD mounting to MountModules and implements the new transaction/message. |
| src/windows/wslcsession/WSLCContainer.cpp | Adds /dev/kvm device passthrough when nested virtualization is enabled for the session. |
| src/windows/WslcSDK/wslcsdk.h | Exposes nested virtualization as an SDK session feature flag constant. |
| src/windows/WslcSDK/wslcsdk.cpp | Updates SDK ↔ service flag mapping/validation to include nested virtualization. |
| src/windows/service/inc/WSLCShared.idl | Adds WslcFeatureFlagsNestedVirtualization and updates the valid-flags mask. |
| src/windows/service/exe/WslCoreVm.cpp | Reuses a shared HCS helper for nested-virt support detection in the WSL2 VM path. |
| src/windows/service/exe/HcsVirtualMachine.cpp | Enables virtualization extensions when flagged, and rejects unsupported hosts with a localized user error. |
| src/windows/common/hcs.hpp | Declares IsNestedVirtualizationSupported() for shared capability detection. |
| src/windows/common/hcs.cpp | Implements IsNestedVirtualizationSupported() (Windows 11+ + HCS processor feature check). |
| src/shared/inc/lxinitshared.h | Adds LxMessageWSLCMountModules and the WSLC_MOUNT_MODULES message struct; removes KernelModules flag from WSLC_MOUNT. |
| src/linux/init/WSLCInit.cpp | Handles WSLC_MOUNT_MODULES to mount modules and optionally modprobe the vendor KVM module via CPUID. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/windows/wslcsession/WSLCVirtualMachine.cpp:902
- MountModules() discards the init-side error code by always throwing E_FAIL when response.Result != 0. Since WSLC_MOUNT_RESULT::Result already carries the HRESULT from the guest (wil::ResultFromCaughtException), callers lose the specific failure and only see a generic E_FAIL.
THROW_HR_IF(E_FAIL, response.Result != 0);
a212e54 to
1398e2f
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/linux/init/WSLCInit.cpp:712
- LoadKvmModule() unconditionally throws ENOTSUP on non-x86_64 builds. Since MountModules passes LoadKvm based only on the feature flag, enabling nested virtualization would cause session initialization to fail on non-x86_64 guests (e.g., ARM64) even if HCS exposes virtualization extensions. Consider either supporting the appropriate KVM module(s) for non-x86_64 kernels or gating LoadKvm/feature enablement by guest architecture and returning a user-friendly error.
#else
THROW_ERRNO(ENOTSUP);
#endif
src/windows/wslcsession/WSLCVirtualMachine.cpp:1000
- MountModules() currently throws a generic E_FAIL whenever the guest reports a non-zero Result. Since the guest side sets Result via wil::ResultFromCaughtException(), this masks the underlying HRESULT (e.g., ENOTSUP mapped to HRESULT_FROM_WIN32). Propagating the guest HRESULT would make failures significantly easier to diagnose than a blanket E_FAIL.
WSL_LOG(
"WSLCMountModules",
TraceLoggingValue(Source, "Source"),
TraceLoggingValue(LoadKvm, "LoadKvm"),
TraceLoggingValue(response.Result, "Result"));
THROW_HR_IF(E_FAIL, response.Result != 0);
}
| module = "kvm_amd"; | ||
| } | ||
|
|
||
| THROW_ERRNO_IF(ENOTSUP, module == nullptr); |
There was a problem hiding this comment.
An error message that includes vendor might be useful.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/windows/service/exe/HcsVirtualMachine.cpp:157
- No automated test exercises this new feature branch: the only test change moves the invalid-feature mask to
0x80, whereas the analogous GPU feature has enabled/disabled session and container coverage inWSLCTests.cpp:4001-4061plus SDK tests. Add capability-aware coverage for the unsupported localized failure and, on a supported host, session creation and/dev/kvmaccess inside a container so regressions in the HCS, guest-protocol, module-loading, and device-mapping path are detected.
if (FeatureEnabled(WslcFeatureFlagsNestedVirtualization))
{
THROW_HR_WITH_USER_ERROR_IF(
HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED),
wsl::shared::Localization::MessageNestedVirtualizationNotSupported(),
!hcs::IsNestedVirtualizationSupported());
src/windows/WslcSDK/wslcsdk.h:119
- The new public session capability is reachable only from the C API. The C#/C++ projections expose
SessionSettingsthroughwinrt/wslcsdk.idl, which has onlyEnableGpuand no raw feature-flags property, even thoughdoc/docs/api-reference/index.md:12states that all projections provide the same underlying capabilities. Add anEnableNestedVirtualizationproperty through the WinRT IDL and implementation, with corresponding projection tests and API-reference updates, so those consumers can opt in too.
WSLC_SESSION_FEATURE_FLAG_NESTED_VIRTUALIZATION = 0x00000040
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/windows/WslcSDK/wslcsdk.h:119
- The new public C SDK flag is missing from the C API reference:
doc/docs/api-reference/c/enumerations/wslcsessionfeatureflags.mdstill lists onlyNONEandENABLE_GPU, and the feature-flags setter page only demonstrates GPU. Please update those C reference pages as was done for the C#/C++ surfaces so C consumers can discover and use this flag.
WSLC_SESSION_FEATURE_FLAG_NESTED_VIRTUALIZATION = 0x00000040
src/windows/wslcsession/WSLCContainer.cpp:1943
- There is no automated test for the feature's main container contract: the added tests only cover the WinRT property and policy rejection, while this path that injects
/dev/kvm(and the companion module-loading path) is unexercised. Please add a supported-host/conditionally skipped E2E test that verifies/dev/kvmis usable in nested-virtualization sessions and absent from ordinary sessions; the existing GPU E2E coverage intest/windows/WSLCTests.cpp:4116-4135provides a similar pattern.
request.HostConfig.Devices->push_back({"/dev/kvm", "/dev/kvm", "rwm"});
9b1e412 to
d908cee
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 28 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src/windows/common/hcs.cpp:143
- The PR says support is determined by what HCS reports, and the linked issue specifically calls out Windows 10 as usable when the perfmon conflict is avoided. This unconditional OS gate discards a reported
NestedVirtcapability, so WSLC nested virtualization remains unavailable on every Windows 10 host. Query the HCS capability on those hosts and handle the Windows 10ExposeVirtualizationExtensions/perfmon incompatibility when configuring the VM instead of rejecting the OS outright.
if (!wsl::windows::common::helpers::IsWindows11OrAbove())
{
return false;
}
src/windows/service/exe/WSLCSessionManager.cpp:214
- This validates only policy at
CreateSession; host capability is checked later when the VM is lazily created. The new test consequently asserts thatCreateSessionsucceeds on an unsupported host and onlyListImagesfails, which contradicts the stated contract to fail session creation and returns clients a session that cannot be used. Perform the localized capability check at this boundary as well.
if (WI_IsFlagSet(Settings->FeatureFlags, WslcFeatureFlagsNestedVirtualization))
{
wsl::windows::policies::EnsureWslContainerNestedVirtualizationAllowed();
}
intune/en-US/WSL.adml:59
disabledis ordinary translatable prose here, but this lock directs localization to preserve the English word. Comparable policy explanations in this file (for example, lines 11–44) use “disabled” without locking it; remove this extra marker so localized policy text can translate the term.
<string id="AllowWSLContainerNestedVirtualizationExplain"><!-- _locComment_text='{Locked="WSL"}{Locked="disabled"}' -->This policy controls whether WSL container sessions can enable nested virtualization. When enabled or not configured, applications can request nested virtualization for WSL container sessions. When set to disabled, requests to create WSL container sessions with nested virtualization enabled are rejected.</string>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 28 changed files in this pull request and generated no new comments.
Suppressed comments (1)
tools/devops/validate-localization.py:263
- This turns every missing translated ADML string into a non-failing condition, so an accidental deletion of an existing policy string will now pass CI just like a newly added string awaiting localization. Please scope the warning behavior to known/pending localization gaps (or otherwise compare against the previously translated IDs) while retaining an error for regressions in existing locale files.
print(f'warning: ADML {locale_path} is missing string ids: {sorted(missing)}')
Add WslcFeatureFlagsNestedVirtualization so a wslc session can request virtualization extensions in its utility VM, exposing /dev/kvm to containers (qemu-kvm, libvirt, Firecracker, Android emulators). - Service enum bit 64 + C SDK flag 0x40 wired through FlagsTraits. - HcsVirtualMachine sets ExposeVirtualizationExtensions when requested, skipping child perfmon on Windows 10 (Hyper-V rejects the combination). - wslcsession passes /dev/kvm into the container. - Guest init loads kvm_intel/kvm_amd (best-effort) only when the session requested nested virt, signalled via a new NestedVirtualization mount flag on the kernel-modules mount. Fixes #40736 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Share HCS nested virtualization capability detection with WSL2 and fail WSLC session creation when the requested capability is unavailable. Add a dedicated kernel modules mount message and select the appropriate KVM module from the guest CPU vendor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
Use an explicit I/O error when modprobe fails instead of throwing from a potentially stale errno value. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
Expose nested virtualization through the WinRT projections and add policy enforcement for WSLC sessions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
Document the C API flag, preserve guest mount errors, and add capability-aware container coverage for KVM access. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
Treat missing translated ADML string IDs as warnings, consistent with RESW validation, while preserving failures for unexpected IDs and presentation mismatches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
Treat guest errno responses as failures and trigger VM startup when testing unsupported nested virtualization hosts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
Reject known unsupported hosts before returning a WSLC session and allow localization of policy prose. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0553ee36-2b3e-48a0-b2db-e8c6362c6f2b
5e156ea to
b9e1448
Compare
Summary
/dev/kvminto containers in nested-virtualization sessionsValidation
Fixes #40736