master
h 180 lines 7.22 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #pragma once
4
5 #include <windowsdefs.h>
6 #include <WslDeviceHost.h>
7 #include "hcs.hpp"
8
9 namespace wrl = Microsoft::WRL;
10
11 class DeviceHostProxy
12 : public wrl::RuntimeClass<wrl::RuntimeClassFlags<wrl::RuntimeClassType::ClassicCom>, IVmDeviceHostSupport, IPlan9FileSystemHost, IWslDeviceHostCallback>
13 {
14 public:
15 DeviceHostProxy(const std::wstring& VmId, const GUID& RuntimeId, bool EnableTelemetry = true);
16
17 GUID AddNewDevice(const GUID& Type, const wil::com_ptr<IPlan9FileSystem>& Plan9Fs, const std::wstring& VirtIoTag);
18
19 GUID AddVirtioNetDevice(_In_ HANDLE UserToken, const WslVirtioNetConfig& Config, const std::vector<IpAddress>& Nameservers);
20
21 GUID AddVirtiofsDevice(
22 _In_ HANDLE UserToken, const std::wstring& Label, const std::wstring& RootPath, VirtiofsShareKind Kind, UINT32 ShmemSizeMb, const std::wstring& MountOptions);
23
24 void AddVirtiofsChild(const GUID& InstanceId, const std::wstring& Name, const std::wstring& RootPath, const std::wstring& MountOptions);
25
26 void RemoveVirtiofsChild(const GUID& InstanceId, const std::wstring& Name);
27
28 GUID AddVirtioPmemDevice(_In_ HANDLE UserToken, const std::wstring& Path, bool Writable);
29
30 void RemoveDevice(const GUID& InstanceId);
31
32 void AddRemoteFileSystem(const GUID& ImplementationClsid, const std::wstring& Tag, const wil::com_ptr<IPlan9FileSystem>& Plan9Fs);
33
34 wil::com_ptr<IPlan9FileSystem> GetRemoteFileSystem(const GUID& ImplementationClsid, std::wstring_view Tag);
35
36 wil::com_ptr<IWslVirtioNetDevice> GetVirtioNetDevice(const GUID& InstanceId);
37
38 wil::com_ptr<IWslVirtiofsDevice> GetVirtiofsDevice(const GUID& InstanceId);
39
40 void SetSwiotlb(UINT64 GpaBase, UINT64 SizeBytes);
41
42 void Shutdown();
43
44 //
45 // IVmDeviceHostSupport
46 //
47 IFACEMETHOD(RegisterDeviceHost)(_In_ IVmDeviceHost* DeviceHost, _In_ DWORD ProcessId, _Out_ UINT64* IpcSectionHandle) override;
48
49 //
50 // IPlan9FileSystemHost
51 //
52 IFACEMETHOD(NotifyAllDevicesInUse)(_In_ LPCWSTR Tag) override;
53
54 IFACEMETHOD(RegisterDoorbell)(const GUID& InstanceId, UINT8 BarIndex, UINT64 Offset, UINT64 TriggerValue, UINT64 Flags, HANDLE Event) override;
55
56 IFACEMETHOD(UnregisterDoorbell)(const GUID& InstanceId, UINT8 BarIndex, UINT64 Offset, UINT64 TriggerValue, UINT64 Flags) override;
57
58 IFACEMETHOD(CreateSectionBackedMmioRange)(
59 const GUID& InstanceId, UINT8 BarIndex, UINT64 BarOffsetInPages, UINT64 PageCount, UINT64 MappingFlags, HANDLE SectionHandle, UINT64 SectionOffsetInPages) override;
60
61 IFACEMETHOD(DestroySectionBackedMmioRange)(const GUID& InstanceId, UINT8 BarIndex, UINT64 BarOffsetInPages) override;
62
63 //
64 // IWslDeviceHostCallback
65 //
66 IFACEMETHOD(RegisterDoorbell)(GUID InstanceId, BYTE BarIndex, UINT64 Offset, UINT64 TriggerValue, UINT64 Flags, HANDLE Event) override;
67
68 IFACEMETHOD(UnregisterDoorbell)(GUID InstanceId, BYTE BarIndex, UINT64 Offset, UINT64 TriggerValue, UINT64 Flags) override;
69
70 IFACEMETHOD(CreateSectionBackedMmioRange)(
71 GUID InstanceId, BYTE BarIndex, UINT64 BarOffsetInPages, UINT64 PageCount, UINT64 MappingFlags, HANDLE SectionHandle, UINT64 SectionOffsetInPages) override;
72
73 IFACEMETHOD(DestroySectionBackedMmioRange)(GUID InstanceId, BYTE BarIndex, UINT64 BarOffsetInPages) override;
74
75 private:
76 struct RemoteFileSystemInfo
77 {
78 RemoteFileSystemInfo(GUID ImplementationClsid, const std::wstring& Tag, const wil::com_ptr<IPlan9FileSystem>& Instance, IGlobalInterfaceTable* git) :
79 ImplementationClsid{ImplementationClsid}, Tag{Tag}, m_git{git}
80 {
81 THROW_IF_FAILED(git->RegisterInterfaceInGlobal(Instance.get(), __uuidof(IPlan9FileSystem), &Cookie));
82 }
83
84 ~RemoteFileSystemInfo()
85 {
86 if (Cookie != 0)
87 {
88 LOG_IF_FAILED(m_git->RevokeInterfaceFromGlobal(Cookie));
89 }
90 }
91
92 RemoteFileSystemInfo(RemoteFileSystemInfo&& other) noexcept
93 {
94 *this = std::move(other);
95 }
96
97 RemoteFileSystemInfo& operator=(RemoteFileSystemInfo&& other) noexcept
98 {
99 if (this != &other)
100 {
101 if (Cookie != 0)
102 {
103 LOG_IF_FAILED(m_git->RevokeInterfaceFromGlobal(Cookie));
104 }
105
106 ImplementationClsid = other.ImplementationClsid;
107 Tag = std::move(other.Tag);
108 Cookie = other.Cookie;
109 m_git = other.m_git;
110 other.Cookie = 0;
111 }
112
113 return *this;
114 }
115
116 RemoteFileSystemInfo(const RemoteFileSystemInfo&) = delete;
117 RemoteFileSystemInfo& operator=(const RemoteFileSystemInfo&) = delete;
118
119 GUID ImplementationClsid{};
120 std::wstring Tag;
121 DWORD Cookie = 0;
122
123 private:
124 IGlobalInterfaceTable* m_git = nullptr;
125 };
126
127 wil::com_ptr<IGlobalInterfaceTable> m_git;
128
129 struct DeviceHostProxyEntry;
130
131 wil::com_ptr<IWslVm> GetWslVm(_In_ HANDLE UserToken);
132 wil::com_ptr<IWslDeviceHostCallback> GetCallback();
133 void AddFlexibleIoDevice(const GUID& Type, const GUID& InstanceId);
134 _Requires_lock_held_(m_lock)
135 void ConfigureSwiotlb(const wil::com_ptr<IWslVm>& Vm, bool& Configured);
136 void TeardownDevice(const wil::com_ptr<IUnknown>& Device) noexcept;
137
138 HRESULT RegisterDoorbellImpl(const GUID& InstanceId, UINT8 BarIndex, UINT64 Offset, UINT64 TriggerValue, UINT64 Flags, HANDLE Event) noexcept;
139 HRESULT UnregisterDoorbellImpl(const GUID& InstanceId, UINT8 BarIndex, UINT64 Offset, UINT64 TriggerValue, UINT64 Flags) noexcept;
140 HRESULT CreateSectionBackedMmioRangeImpl(
141 const GUID& InstanceId, UINT8 BarIndex, UINT64 BarOffsetInPages, UINT64 PageCount, UINT64 MappingFlags, HANDLE SectionHandle, UINT64 SectionOffsetInPages) noexcept;
142 HRESULT DestroySectionBackedMmioRangeImpl(const GUID& InstanceId, UINT8 BarIndex, UINT64 BarOffsetInPages) noexcept;
143
144 std::wstring m_systemId;
145 GUID m_runtimeId;
146 bool m_enableTelemetry;
147 wsl::windows::common::hcs::unique_hcs_system m_system;
148 wil::srwlock m_lock;
149 std::vector<RemoteFileSystemInfo> m_fileSystems;
150 bool m_shutdown;
151 wil::com_ptr<IWslVm> m_wslVm;
152 wil::com_ptr<IWslVm> m_adminWslVm;
153 SwiotlbConfig m_swiotlbConfig{};
154 bool m_swiotlbConfigured = false;
155 bool m_wslVmSwiotlbConfigured = false;
156 bool m_adminWslVmSwiotlbConfigured = false;
157
158 struct DeviceHostProxyEntry
159 {
160 GUID Type{};
161 wil::com_ptr<IVmFiovGuestMemoryFastNotification> MemoryNotification;
162 wil::com_ptr<IVmFiovGuestMmioMappings> MemoryMapping;
163 wil::com_ptr<IUnknown> Device;
164 size_t DoorbellCount = 0;
165 bool ShuttingDown = false;
166 };
167
168 wil::com_ptr<IVmVirtualDeviceAccess> m_deviceAccess;
169 std::mutex m_deviceLifecycleLock;
170 wil::srwlock m_devicesLock;
171 std::map<GUID, DeviceHostProxyEntry, wsl::windows::common::helpers::GuidLess> m_devices;
172 bool m_devicesShutdown;
173
174 // A kill-on-close job per device host process, held for the proxy's lifetime so the
175 // processes are terminated when the VM shuts down. Guarded by m_devicesLock.
176 std::vector<wil::unique_handle> m_processJobs;
177
178 static constexpr LPCWSTR c_hdvModuleName = L"vmdevicehost.dll";
179 static constexpr LPCWSTR c_vmwpctrlModuleName = L"vmwpctrl.dll";
180 };