]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/TdxDxe/TdxDxe.c
nasm_ext_dep.yaml: Remove leading zero in patch version
[mirror_edk2.git] / OvmfPkg / TdxDxe / TdxDxe.c
1 /** @file
2
3 TDX Dxe driver. This driver is dispatched early in DXE, due to being list
4 in APRIORI.
5
6 This module is responsible for:
7 - Sets max logical cpus based on TDINFO
8 - Sets PCI PCDs based on resource hobs
9 - Alter MATD table to record address of Mailbox
10
11 Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
12
13 SPDX-License-Identifier: BSD-2-Clause-Patent
14
15 **/
16
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/DxeServicesTableLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/UefiLib.h>
24 #include <Library/HobLib.h>
25 #include <Protocol/Cpu.h>
26 #include <Protocol/MpInitLibDepProtocols.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <ConfidentialComputingGuestAttr.h>
29 #include <IndustryStandard/Tdx.h>
30 #include <Library/PlatformInitLib.h>
31 #include <Library/TdxLib.h>
32 #include <TdxAcpiTable.h>
33 #include <Library/MemEncryptTdxLib.h>
34
35 VOID
36 SetPcdSettings (
37 EFI_HOB_PLATFORM_INFO *PlatformInfoHob
38 )
39 {
40 RETURN_STATUS PcdStatus;
41
42 PcdStatus = PcdSet64S (PcdConfidentialComputingGuestAttr, PlatformInfoHob->PcdConfidentialComputingGuestAttr);
43 ASSERT_RETURN_ERROR (PcdStatus);
44 PcdStatus = PcdSetBoolS (PcdSetNxForStack, PlatformInfoHob->PcdSetNxForStack);
45 ASSERT_RETURN_ERROR (PcdStatus);
46
47 DEBUG ((
48 DEBUG_INFO,
49 "HostBridgeDevId=0x%x, CCAttr=0x%x, SetNxForStack=%x\n",
50 PlatformInfoHob->HostBridgeDevId,
51 PlatformInfoHob->PcdConfidentialComputingGuestAttr,
52 PlatformInfoHob->PcdSetNxForStack
53 ));
54
55 PcdStatus = PcdSet32S (PcdCpuBootLogicalProcessorNumber, PlatformInfoHob->PcdCpuBootLogicalProcessorNumber);
56 ASSERT_RETURN_ERROR (PcdStatus);
57 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber);
58 ASSERT_RETURN_ERROR (PcdStatus);
59
60 DEBUG ((
61 DEBUG_INFO,
62 "MaxCpuCount=0x%x, BootCpuCount=0x%x\n",
63 PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber,
64 PlatformInfoHob->PcdCpuBootLogicalProcessorNumber
65 ));
66
67 PcdSet64S (PcdEmuVariableNvStoreReserved, PlatformInfoHob->PcdEmuVariableNvStoreReserved);
68
69 if (TdIsEnabled ()) {
70 PcdStatus = PcdSet64S (PcdTdxSharedBitMask, TdSharedPageMask ());
71 ASSERT_RETURN_ERROR (PcdStatus);
72 DEBUG ((DEBUG_INFO, "TdxSharedBitMask=0x%llx\n", PcdGet64 (PcdTdxSharedBitMask)));
73 }
74
75 PcdStatus = PcdSet64S (PcdPciMmio64Base, PlatformInfoHob->PcdPciMmio64Base);
76 ASSERT_RETURN_ERROR (PcdStatus);
77 PcdStatus = PcdSet64S (PcdPciMmio64Size, PlatformInfoHob->PcdPciMmio64Size);
78 ASSERT_RETURN_ERROR (PcdStatus);
79 PcdStatus = PcdSet64S (PcdPciMmio32Base, PlatformInfoHob->PcdPciMmio32Base);
80 ASSERT_RETURN_ERROR (PcdStatus);
81 PcdStatus = PcdSet64S (PcdPciMmio32Size, PlatformInfoHob->PcdPciMmio32Size);
82 ASSERT_RETURN_ERROR (PcdStatus);
83 PcdStatus = PcdSet64S (PcdPciIoBase, PlatformInfoHob->PcdPciIoBase);
84 ASSERT_RETURN_ERROR (PcdStatus);
85 PcdStatus = PcdSet64S (PcdPciIoSize, PlatformInfoHob->PcdPciIoSize);
86 ASSERT_RETURN_ERROR (PcdStatus);
87 }
88
89 /**
90 Location of resource hob matching type and starting address
91
92 @param[in] Type The type of resource hob to locate.
93
94 @param[in] Start The resource hob must at least begin at address.
95
96 @retval pointer to resource Return pointer to a resource hob that matches or NULL.
97 **/
98 STATIC
99 EFI_HOB_RESOURCE_DESCRIPTOR *
100 GetResourceDescriptor (
101 EFI_RESOURCE_TYPE Type,
102 EFI_PHYSICAL_ADDRESS Start,
103 EFI_PHYSICAL_ADDRESS End
104 )
105 {
106 EFI_PEI_HOB_POINTERS Hob;
107 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor = NULL;
108
109 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
110 while (Hob.Raw != NULL) {
111 DEBUG ((
112 DEBUG_INFO,
113 "%a:%d: resource type 0x%x %llx %llx\n",
114 __func__,
115 __LINE__,
116 Hob.ResourceDescriptor->ResourceType,
117 Hob.ResourceDescriptor->PhysicalStart,
118 Hob.ResourceDescriptor->ResourceLength
119 ));
120
121 if ((Hob.ResourceDescriptor->ResourceType == Type) &&
122 (Hob.ResourceDescriptor->PhysicalStart >= Start) &&
123 ((Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength) < End))
124 {
125 ResourceDescriptor = Hob.ResourceDescriptor;
126 break;
127 }
128
129 Hob.Raw = GET_NEXT_HOB (Hob);
130 Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
131 }
132
133 return ResourceDescriptor;
134 }
135
136 /**
137 Location of resource hob matching type and highest address below end
138
139 @param[in] Type The type of resource hob to locate.
140
141 @param[in] End The resource hob return is the closest to the End address
142
143 @retval pointer to resource Return pointer to a resource hob that matches or NULL.
144 **/
145 STATIC
146 EFI_HOB_RESOURCE_DESCRIPTOR *
147 GetHighestResourceDescriptor (
148 EFI_RESOURCE_TYPE Type,
149 EFI_PHYSICAL_ADDRESS End
150 )
151 {
152 EFI_PEI_HOB_POINTERS Hob;
153 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor = NULL;
154
155 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
156 while (Hob.Raw != NULL) {
157 if ((Hob.ResourceDescriptor->ResourceType == Type) &&
158 (Hob.ResourceDescriptor->PhysicalStart < End))
159 {
160 if (!ResourceDescriptor ||
161 (ResourceDescriptor->PhysicalStart < Hob.ResourceDescriptor->PhysicalStart))
162 {
163 ResourceDescriptor = Hob.ResourceDescriptor;
164 }
165 }
166
167 Hob.Raw = GET_NEXT_HOB (Hob);
168 Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
169 }
170
171 return ResourceDescriptor;
172 }
173
174 /**
175 Set the shared bit for mmio region in Tdx guest.
176
177 In Tdx guest there are 2 ways to access mmio, TdVmcall or direct access.
178 For direct access, the shared bit of the PageTableEntry should be set.
179 The mmio region information is retrieved from hob list.
180
181 @retval EFI_SUCCESS The shared bit is set successfully.
182 @retval EFI_UNSUPPORTED Setting the shared bit of memory region
183 is not supported
184 **/
185 EFI_STATUS
186 SetMmioSharedBit (
187 VOID
188 )
189 {
190 EFI_PEI_HOB_POINTERS Hob;
191
192 Hob.Raw = (UINT8 *)GetHobList ();
193
194 //
195 // Parse the HOB list until end of list or matching type is found.
196 //
197 while (!END_OF_HOB_LIST (Hob)) {
198 if ( (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR)
199 && (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_MAPPED_IO))
200 {
201 MemEncryptTdxSetPageSharedBit (
202 0,
203 Hob.ResourceDescriptor->PhysicalStart,
204 EFI_SIZE_TO_PAGES (Hob.ResourceDescriptor->ResourceLength)
205 );
206 }
207
208 Hob.Raw = GET_NEXT_HOB (Hob);
209 }
210
211 return EFI_SUCCESS;
212 }
213
214 EFI_STATUS
215 EFIAPI
216 TdxDxeEntryPoint (
217 IN EFI_HANDLE ImageHandle,
218 IN EFI_SYSTEM_TABLE *SystemTable
219 )
220 {
221 EFI_STATUS Status;
222 RETURN_STATUS PcdStatus;
223 EFI_HOB_RESOURCE_DESCRIPTOR *Res = NULL;
224 EFI_HOB_RESOURCE_DESCRIPTOR *MemRes = NULL;
225 EFI_HOB_PLATFORM_INFO *PlatformInfo = NULL;
226 EFI_HOB_GUID_TYPE *GuidHob;
227 UINT32 CpuMaxLogicalProcessorNumber;
228 TD_RETURN_DATA TdReturnData;
229 EFI_EVENT QemuAcpiTableEvent;
230 void *Registration;
231
232 GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);
233
234 if (GuidHob == NULL) {
235 return EFI_UNSUPPORTED;
236 }
237
238 //
239 // Both Td and Non-Td guest have PlatformInfoHob which contains the HostBridgePciDevId
240 //
241 PlatformInfo = (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob);
242 ASSERT (PlatformInfo->HostBridgeDevId != 0);
243 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfo->HostBridgeDevId);
244 ASSERT_RETURN_ERROR (PcdStatus);
245
246 #ifdef TDX_PEI_LESS_BOOT
247 //
248 // For Pei-less boot, PlatformInfo contains more information and
249 // need to set PCDs based on these information.
250 //
251 SetPcdSettings (PlatformInfo);
252 #endif
253
254 if (!TdIsEnabled ()) {
255 //
256 // If it is Non-Td guest, we install gEfiMpInitLibMpDepProtocolGuid so that
257 // MpInitLib will be used in CpuDxe driver.
258 //
259 gBS->InstallProtocolInterface (
260 &ImageHandle,
261 &gEfiMpInitLibMpDepProtocolGuid,
262 EFI_NATIVE_INTERFACE,
263 NULL
264 );
265
266 return EFI_SUCCESS;
267 }
268
269 SetMmioSharedBit ();
270
271 //
272 // It is Td guest, we install gEfiMpInitLibUpDepProtocolGuid so that
273 // MpInitLibUp will be used in CpuDxe driver.
274 //
275 gBS->InstallProtocolInterface (
276 &ImageHandle,
277 &gEfiMpInitLibUpDepProtocolGuid,
278 EFI_NATIVE_INTERFACE,
279 NULL
280 );
281
282 //
283 // Call TDINFO to get actual number of cpus in domain
284 //
285 Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
286 ASSERT (Status == EFI_SUCCESS);
287
288 CpuMaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
289
290 //
291 // Adjust PcdCpuMaxLogicalProcessorNumber, if needed. If firmware is configured for
292 // more than number of reported cpus, update.
293 //
294 if (CpuMaxLogicalProcessorNumber > TdReturnData.TdInfo.NumVcpus) {
295 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, TdReturnData.TdInfo.NumVcpus);
296 ASSERT_RETURN_ERROR (PcdStatus);
297 }
298
299 //
300 // Register for protocol notifications to call the AlterAcpiTable(),
301 // the protocol will be installed in AcpiPlatformDxe when the ACPI
302 // table provided by Qemu is ready.
303 //
304 Status = gBS->CreateEvent (
305 EVT_NOTIFY_SIGNAL,
306 TPL_CALLBACK,
307 AlterAcpiTable,
308 NULL,
309 &QemuAcpiTableEvent
310 );
311
312 Status = gBS->RegisterProtocolNotify (
313 &gQemuAcpiTableNotifyProtocolGuid,
314 QemuAcpiTableEvent,
315 &Registration
316 );
317
318 #define INIT_PCDSET(NAME, RES) do {\
319 PcdStatus = PcdSet64S (NAME##Base, (RES)->PhysicalStart); \
320 ASSERT_RETURN_ERROR (PcdStatus); \
321 PcdStatus = PcdSet64S (NAME##Size, (RES)->ResourceLength); \
322 ASSERT_RETURN_ERROR (PcdStatus); \
323 } while(0)
324
325 if (PlatformInfo) {
326 PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfo->HostBridgeDevId);
327
328 if ((Res = GetResourceDescriptor (EFI_RESOURCE_MEMORY_MAPPED_IO, (EFI_PHYSICAL_ADDRESS)0x100000000, (EFI_PHYSICAL_ADDRESS)-1)) != NULL) {
329 INIT_PCDSET (PcdPciMmio64, Res);
330 }
331
332 if ((Res = GetResourceDescriptor (EFI_RESOURCE_IO, 0, 0x10001)) != NULL) {
333 INIT_PCDSET (PcdPciIo, Res);
334 }
335
336 //
337 // To find low mmio, first find top of low memory, and then search for io space.
338 //
339 if ((MemRes = GetHighestResourceDescriptor (EFI_RESOURCE_SYSTEM_MEMORY, 0xffc00000)) != NULL) {
340 if ((Res = GetResourceDescriptor (EFI_RESOURCE_MEMORY_MAPPED_IO, MemRes->PhysicalStart, 0x100000000)) != NULL) {
341 INIT_PCDSET (PcdPciMmio32, Res);
342 }
343 }
344 }
345
346 return EFI_SUCCESS;
347 }