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