master
h 159 lines 5.92 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 HcsVirtualMachine.h
8
9 Abstract:
10
11 Implementation of IWSLCVirtualMachine - represents a single HCS-based VM instance.
12 This class encapsulates a VM and all operations on it.
13
14 --*/
15
16 #pragma once
17
18 #include <atomic>
19 #include "wslc.h"
20 #include "hcs.hpp"
21 #include "GuestDeviceManager.h"
22 #include "Dmesg.h"
23 #include "INetworkingEngine.h"
24 #include "WslCoreConfig.h"
25 #include <filesystem>
26 #include <map>
27 #include <optional>
28 #include <string>
29
30 #define MAX_VHD_COUNT 254
31
32 namespace wsl::windows::service::wslc {
33
34 class HcsVirtualMachine
35 : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>, IWSLCVirtualMachine, IFastRundown>
36 {
37 public:
38 HcsVirtualMachine(_In_ const WSLCSessionSettings* Settings);
39 ~HcsVirtualMachine();
40
41 // IWSLCVirtualMachine implementation
42 IFACEMETHOD(GetId)(_Out_ GUID* VmId) override;
43 IFACEMETHOD(AcceptConnection)(_Out_ HANDLE* Socket) override;
44 IFACEMETHOD(ConfigureNetworking)(_In_ HANDLE GnsSocket, _In_opt_ HANDLE* DnsSocket) override;
45 IFACEMETHOD(AttachDisk)(_In_ LPCWSTR Path, _In_ BOOL ReadOnly, _Out_ ULONG* Lun) override;
46 IFACEMETHOD(DetachDisk)(_In_ ULONG Lun) override;
47 IFACEMETHOD(AddShare)(_In_ LPCWSTR WindowsPath, _In_ BOOL ReadOnly, _Out_ GUID* ShareId) override;
48 IFACEMETHOD(RemoveShare)(_In_ REFGUID ShareId) override;
49 IFACEMETHOD(ApplyGuestCapabilities)(_In_ const WSLCGuestCapabilities* Capabilities) override;
50 IFACEMETHOD(GetTerminationEvent)(_Out_ HANDLE* Event) override;
51 IFACEMETHOD(MapVirtioNetPort)
52 (_In_ USHORT HostPort, _In_ USHORT GuestPort, _In_ int Protocol, _In_ LPCSTR ListenAddress, _Out_ USHORT* AllocatedHostPort) override;
53 IFACEMETHOD(UnmapVirtioNetPort)
54 (_In_ USHORT HostPort, _In_ USHORT GuestPort, _In_ int Protocol, _In_ LPCSTR ListenAddress) override;
55 IFACEMETHOD(GetTerminationReason)(_Out_ WSLCVirtualMachineTerminationReason* Reason, _Out_ LPWSTR* Details) override;
56
57 private:
58 struct DiskInfo
59 {
60 std::wstring Path;
61 bool AccessGranted = false;
62 };
63
64 bool FeatureEnabled(WSLCFeatureFlags Value) const;
65 static void CALLBACK OnVmExitCallback(HCS_EVENT* Event, void* Context);
66 void OnExit(const HCS_EVENT* Event);
67 void OnCrash(const HCS_EVENT* Event);
68
69 std::filesystem::path GetCrashDumpFolder();
70 void CreateVmSavedStateFile(HANDLE UserToken);
71 void EnforceVmSavedStateFileLimit();
72 void WriteCrashLog(const std::wstring& crashLog);
73
74 ULONG AllocateLun();
75 void FreeLun(ULONG Lun);
76
77 std::recursive_mutex m_lock;
78
79 wsl::windows::common::hcs::unique_hcs_system m_computeSystem;
80 GUID m_vmId{};
81 std::wstring m_vmIdString;
82 ULONG m_bootTimeoutMs{};
83
84 wil::shared_handle m_userToken;
85 WSLCFeatureFlags m_featureFlags{};
86 WSLCNetworkingMode m_networkingMode{};
87 std::string m_hostLoopback;
88
89 bool m_swiotlbConfigured = false;
90
91 wil::unique_socket m_listenSocket;
92 wil::unique_event m_vmExitEvent{wil::EventOptions::ManualReset};
93 std::shared_ptr<DmesgCollector> m_dmesgCollector;
94 std::shared_ptr<GuestDeviceManager> m_guestDeviceManager;
95 std::optional<wsl::core::Config> m_natConfig;
96 std::unique_ptr<wsl::core::INetworkingEngine> m_networkEngine;
97
98 std::map<ULONG, DiskInfo> m_attachedDisks;
99 std::bitset<MAX_VHD_COUNT> m_lunBitmap;
100
101 // Shares: key is ShareId, value is nullopt for Plan9 or the aggregate DeviceInstanceId for VirtioFS.
102 std::map<GUID, std::optional<GUID>, wsl::windows::common::helpers::GuidLess> m_shares;
103 wil::com_ptr<IPlan9FileSystem> m_plan9Server;
104 std::optional<GUID> m_virtioFsDevice;
105
106 std::filesystem::path m_vmSavedStateFile;
107 std::filesystem::path m_crashDumpFolder;
108 std::atomic<bool> m_vmSavedStateCaptured = false;
109 std::atomic<bool> m_crashLogCaptured = false;
110
111 // Termination reason and details, cached in OnExit before m_vmExitEvent is signaled and never
112 // modified afterward. Publication relies on the event: readers (GetTerminationReason) only access
113 // these after observing m_vmExitEvent signaled, so no lock is needed. Keeping them lock-free also
114 // avoids contending for m_lock from the HCS exit callback, which the destructor holds while the
115 // callback is drained.
116 WSLCVirtualMachineTerminationReason m_terminationReason{WSLCVirtualMachineTerminationReasonUnknown};
117 std::wstring m_terminationDetails;
118 };
119
120 //
121 // WSLCVirtualMachineFactory - Implements IWSLCVirtualMachineFactory.
122 //
123 // Owns a deep copy of the WSLCSessionSettings needed to construct a VM and creates a
124 // fresh HcsVirtualMachine on demand. This lets the per-user session recreate a VM that
125 // was idle-terminated, without the SYSTEM service holding a VM up front.
126 //
127 class WSLCVirtualMachineFactory
128 : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWSLCVirtualMachineFactory, IFastRundown>
129 {
130 public:
131 explicit WSLCVirtualMachineFactory(_In_ const WSLCSessionSettings* Settings);
132
133 IFACEMETHOD(CreateVirtualMachine)(_Out_ IWSLCVirtualMachine** Vm) override;
134
135 private:
136 // Rebuilds a WSLCSessionSettings that points at this factory's owned storage.
137 // The returned struct is only valid while this factory is alive.
138 WSLCSessionSettings BuildSettings();
139
140 std::wstring m_displayName;
141 std::wstring m_storagePath;
142 std::optional<std::wstring> m_rootVhdOverride;
143 std::optional<std::string> m_rootVhdTypeOverride;
144
145 // Duplicated dmesg sink (best-effort): only the first VM is guaranteed a live sink;
146 // subsequent VMs reuse this duplicate, whose writes simply fail if the sink is gone.
147 wil::unique_handle m_dmesgOutput;
148
149 ULONGLONG m_maximumStorageSizeMb{};
150 ULONG m_cpuCount{};
151 ULONG m_memoryMb{};
152 ULONG m_bootTimeoutMs{};
153 WSLCNetworkingMode m_networkingMode{};
154 WSLCFeatureFlags m_featureFlags{};
155 std::string m_hostLoopback;
156 WSLCSessionStorageFlags m_storageFlags{};
157 };
158
159 } // namespace wsl::windows::service::wslc