From a707324aa8d87eef3ed54e6b65c295b9d72425a9 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 2 Jul 2026 11:35:27 +0800 Subject: [PATCH 1/4] cap storage hw queue count to 4 --- src/windows/service/exe/HcsVirtualMachine.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/windows/service/exe/HcsVirtualMachine.cpp b/src/windows/service/exe/HcsVirtualMachine.cpp index 17fd76a63..c0235503b 100644 --- a/src/windows/service/exe/HcsVirtualMachine.cpp +++ b/src/windows/service/exe/HcsVirtualMachine.cpp @@ -30,6 +30,7 @@ using helpers::WindowsBuildNumbers; using wsl::windows::service::wslc::HcsVirtualMachine; constexpr auto MAX_VM_CRASH_FILES = 3; +constexpr auto MAX_STORAGE_HW_QUEUES = 4; constexpr auto SAVED_STATE_FILE_EXTENSION = L".vmrs"; constexpr auto SAVED_STATE_FILE_PREFIX = L"saved-state-"; @@ -169,6 +170,12 @@ HcsVirtualMachine::HcsVirtualMachine(_In_ const WSLCSessionSettings* Settings) kernelCmdLine += std::format(L" nr_cpus={}", Settings->CpuCount); helpers::AppendCommonKernelCommandLine(kernelCmdLine, pageReportingOrder, swiotlbSizeBytes); + // Cap the storage hw queue count. Default is CPU count. + if (Settings->CpuCount > MAX_STORAGE_HW_QUEUES) + { + kernelCmdLine += std::format(L" hv_storvsc.storvsc_max_hw_queues={}", MAX_STORAGE_HW_QUEUES); + } + // Setup dmesg collector with optional DmesgOutput handle. // TODO: move dmesg collector to user session process. // N.B. 'DmesgOutput' needs to be duplicated since COM will close it when this call completes. From cf79f9ebe5d36bd38ed455ee017d28e7909b2623 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 2 Jul 2026 14:17:39 +0800 Subject: [PATCH 2/4] resolve comments --- src/windows/service/exe/HcsVirtualMachine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows/service/exe/HcsVirtualMachine.cpp b/src/windows/service/exe/HcsVirtualMachine.cpp index c0235503b..e33423f76 100644 --- a/src/windows/service/exe/HcsVirtualMachine.cpp +++ b/src/windows/service/exe/HcsVirtualMachine.cpp @@ -30,7 +30,7 @@ using helpers::WindowsBuildNumbers; using wsl::windows::service::wslc::HcsVirtualMachine; constexpr auto MAX_VM_CRASH_FILES = 3; -constexpr auto MAX_STORAGE_HW_QUEUES = 4; +constexpr ULONG MAX_STORAGE_HW_QUEUES = 4; constexpr auto SAVED_STATE_FILE_EXTENSION = L".vmrs"; constexpr auto SAVED_STATE_FILE_PREFIX = L"saved-state-"; From d4b10fdcb20a3357fbdf5fd7911640bb4e40327b Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Fri, 3 Jul 2026 11:01:37 +0800 Subject: [PATCH 3/4] apply change to both wslc and wsl --- src/windows/common/helpers.cpp | 11 ++++++++++- src/windows/common/helpers.hpp | 2 +- src/windows/service/exe/HcsVirtualMachine.cpp | 9 +-------- src/windows/service/exe/WslCoreVm.cpp | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/windows/common/helpers.cpp b/src/windows/common/helpers.cpp index f8f3cdaa4..b37bc8c6c 100644 --- a/src/windows/common/helpers.cpp +++ b/src/windows/common/helpers.cpp @@ -39,6 +39,8 @@ using wsl::windows::common::helpers::LaunchWslRelayFlags; constexpr auto c_WslSupportInterfaceKey = L"Software\\Classes\\Interface\\{46f3c96d-ffa3-42f0-b052-52f5e7ecbb08}"; constexpr auto c_WslSupportInterfaceName = L"IWslSupport"; +constexpr ULONG c_MaxStorageHwQueues = 4; + namespace { class ProcessLauncher @@ -762,7 +764,8 @@ try } CATCH_LOG() -void wsl::windows::common::helpers::AppendCommonKernelCommandLine(_Inout_ std::wstring& kernelCmdLine, _In_ int pageReportingOrder, _In_ ULONG64 swiotlbSizeBytes) +void wsl::windows::common::helpers::AppendCommonKernelCommandLine( + _Inout_ std::wstring& kernelCmdLine, _In_ int pageReportingOrder, _In_ ULONG64 swiotlbSizeBytes, _In_ ULONG cpuCount) { // Enable timesync workaround to sync on resume from sleep in modern standby. kernelCmdLine += L" hv_utils.timesync_implicit=1"; @@ -778,6 +781,12 @@ void wsl::windows::common::helpers::AppendCommonKernelCommandLine(_Inout_ std::w { kernelCmdLine += std::format(L" swiotlb=force hv_pci_swiotlb={}", swiotlbSizeBytes); } + + // Cap the storage hw queue count. Default is CPU count. + if (cpuCount > c_MaxStorageHwQueues) + { + kernelCmdLine += std::format(L" hv_storvsc.storvsc_max_hw_queues={}", c_MaxStorageHwQueues); + } } UINT64 wsl::windows::common::helpers::ComputeDefaultSwiotlbConfig(_In_ UINT64 memoryBytes) diff --git a/src/windows/common/helpers.hpp b/src/windows/common/helpers.hpp index e83fc1832..2253ace99 100644 --- a/src/windows/common/helpers.hpp +++ b/src/windows/common/helpers.hpp @@ -205,7 +205,7 @@ bool TryAttachConsole(); void RegisterWithDcat(_In_ bool IncludeVersionNumber = true); -void AppendCommonKernelCommandLine(_Inout_ std::wstring& kernelCmdLine, _In_ int pageReportingOrder, _In_ ULONG64 swiotlbSizeBytes); +void AppendCommonKernelCommandLine(_Inout_ std::wstring& kernelCmdLine, _In_ int pageReportingOrder, _In_ ULONG64 swiotlbSizeBytes, _In_ ULONG cpuCount); UINT64 ComputeDefaultSwiotlbConfig(_In_ UINT64 memoryBytes); diff --git a/src/windows/service/exe/HcsVirtualMachine.cpp b/src/windows/service/exe/HcsVirtualMachine.cpp index e33423f76..2eceb7ae9 100644 --- a/src/windows/service/exe/HcsVirtualMachine.cpp +++ b/src/windows/service/exe/HcsVirtualMachine.cpp @@ -30,7 +30,6 @@ using helpers::WindowsBuildNumbers; using wsl::windows::service::wslc::HcsVirtualMachine; constexpr auto MAX_VM_CRASH_FILES = 3; -constexpr ULONG MAX_STORAGE_HW_QUEUES = 4; constexpr auto SAVED_STATE_FILE_EXTENSION = L".vmrs"; constexpr auto SAVED_STATE_FILE_PREFIX = L"saved-state-"; @@ -168,13 +167,7 @@ HcsVirtualMachine::HcsVirtualMachine(_In_ const WSLCSessionSettings* Settings) // Initialize kernel command line. std::wstring kernelCmdLine = L"initrd=\\" LXSS_VM_MODE_INITRD_NAME L" " TEXT(WSLC_ROOT_INIT_ENV) L"=1 panic=-1"; kernelCmdLine += std::format(L" nr_cpus={}", Settings->CpuCount); - helpers::AppendCommonKernelCommandLine(kernelCmdLine, pageReportingOrder, swiotlbSizeBytes); - - // Cap the storage hw queue count. Default is CPU count. - if (Settings->CpuCount > MAX_STORAGE_HW_QUEUES) - { - kernelCmdLine += std::format(L" hv_storvsc.storvsc_max_hw_queues={}", MAX_STORAGE_HW_QUEUES); - } + helpers::AppendCommonKernelCommandLine(kernelCmdLine, pageReportingOrder, swiotlbSizeBytes, Settings->CpuCount); // Setup dmesg collector with optional DmesgOutput handle. // TODO: move dmesg collector to user session process. diff --git a/src/windows/service/exe/WslCoreVm.cpp b/src/windows/service/exe/WslCoreVm.cpp index 7cdcae3cf..550750988 100644 --- a/src/windows/service/exe/WslCoreVm.cpp +++ b/src/windows/service/exe/WslCoreVm.cpp @@ -1579,7 +1579,7 @@ std::wstring WslCoreVm::GenerateConfigJson() kernelCmdLine += std::format(L" nr_cpus={}", m_vmConfig.ProcessorCount); // Append common kernel parameters shared between WSL2 and WSLC. - helpers::AppendCommonKernelCommandLine(kernelCmdLine, m_pageReportingOrder, m_vmConfig.SwiotlbSizeBytes); + helpers::AppendCommonKernelCommandLine(kernelCmdLine, m_pageReportingOrder, m_vmConfig.SwiotlbSizeBytes, m_vmConfig.ProcessorCount); if (m_vmConfig.EnableVirtio && helpers::IsVirtioSerialConsoleSupported()) { From cb2d460df979a53989a341191ffc7d319a38c84d Mon Sep 17 00:00:00 2001 From: "Feng Wang (from Dev Box)" Date: Tue, 7 Jul 2026 11:02:40 +0800 Subject: [PATCH 4/4] move nr_cpus to common kernel cmd --- src/windows/common/helpers.cpp | 3 +++ src/windows/service/exe/HcsVirtualMachine.cpp | 1 - src/windows/service/exe/WslCoreVm.cpp | 3 --- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/windows/common/helpers.cpp b/src/windows/common/helpers.cpp index b37bc8c6c..7027a2992 100644 --- a/src/windows/common/helpers.cpp +++ b/src/windows/common/helpers.cpp @@ -767,6 +767,9 @@ CATCH_LOG() void wsl::windows::common::helpers::AppendCommonKernelCommandLine( _Inout_ std::wstring& kernelCmdLine, _In_ int pageReportingOrder, _In_ ULONG64 swiotlbSizeBytes, _In_ ULONG cpuCount) { + // Set number of processors. + kernelCmdLine += std::format(L" nr_cpus={}", cpuCount); + // Enable timesync workaround to sync on resume from sleep in modern standby. kernelCmdLine += L" hv_utils.timesync_implicit=1"; diff --git a/src/windows/service/exe/HcsVirtualMachine.cpp b/src/windows/service/exe/HcsVirtualMachine.cpp index 2eceb7ae9..c11a1f78e 100644 --- a/src/windows/service/exe/HcsVirtualMachine.cpp +++ b/src/windows/service/exe/HcsVirtualMachine.cpp @@ -166,7 +166,6 @@ HcsVirtualMachine::HcsVirtualMachine(_In_ const WSLCSessionSettings* Settings) // Initialize kernel command line. std::wstring kernelCmdLine = L"initrd=\\" LXSS_VM_MODE_INITRD_NAME L" " TEXT(WSLC_ROOT_INIT_ENV) L"=1 panic=-1"; - kernelCmdLine += std::format(L" nr_cpus={}", Settings->CpuCount); helpers::AppendCommonKernelCommandLine(kernelCmdLine, pageReportingOrder, swiotlbSizeBytes, Settings->CpuCount); // Setup dmesg collector with optional DmesgOutput handle. diff --git a/src/windows/service/exe/WslCoreVm.cpp b/src/windows/service/exe/WslCoreVm.cpp index 550750988..9705e9cc2 100644 --- a/src/windows/service/exe/WslCoreVm.cpp +++ b/src/windows/service/exe/WslCoreVm.cpp @@ -1575,9 +1575,6 @@ std::wstring WslCoreVm::GenerateConfigJson() // Initialize kernel command line. std::wstring kernelCmdLine = L"initrd=\\" LXSS_VM_MODE_INITRD_NAME L" " TEXT(WSL_ROOT_INIT_ENV) L"=1 panic=-1"; - // Set number of processors. - kernelCmdLine += std::format(L" nr_cpus={}", m_vmConfig.ProcessorCount); - // Append common kernel parameters shared between WSL2 and WSLC. helpers::AppendCommonKernelCommandLine(kernelCmdLine, m_pageReportingOrder, m_vmConfig.SwiotlbSizeBytes, m_vmConfig.ProcessorCount);