Add nested virtualization support for WSLC containers - #41257
Add nested virtualization support for WSLC containers#41257Ben Hillis (benhillis) wants to merge 6 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);
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
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
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
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"});
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
Summary
/dev/kvminto containers in nested-virtualization sessionsValidation
Fixes #40736