3 TDX Dxe driver. This driver is dispatched early in DXE, due to being list
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
11 Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
13 SPDX-License-Identifier: BSD-2-Clause-Patent
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 <Library/UefiBootServicesTableLib.h>
27 #include <ConfidentialComputingGuestAttr.h>
28 #include <IndustryStandard/Tdx.h>
29 #include <Library/PlatformInitLib.h>
30 #include <Library/TdxLib.h>
31 #include <TdxAcpiTable.h>
32 #include <Library/MemEncryptTdxLib.h>
36 EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
39 RETURN_STATUS PcdStatus
;
41 PcdStatus
= PcdSet64S (PcdConfidentialComputingGuestAttr
, PlatformInfoHob
->PcdConfidentialComputingGuestAttr
);
42 ASSERT_RETURN_ERROR (PcdStatus
);
43 PcdStatus
= PcdSetBoolS (PcdSetNxForStack
, PlatformInfoHob
->PcdSetNxForStack
);
44 ASSERT_RETURN_ERROR (PcdStatus
);
48 "HostBridgeDevId=0x%x, CCAttr=0x%x, SetNxForStack=%x\n",
49 PlatformInfoHob
->HostBridgeDevId
,
50 PlatformInfoHob
->PcdConfidentialComputingGuestAttr
,
51 PlatformInfoHob
->PcdSetNxForStack
54 PcdStatus
= PcdSet32S (PcdCpuBootLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
);
55 ASSERT_RETURN_ERROR (PcdStatus
);
56 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
);
57 ASSERT_RETURN_ERROR (PcdStatus
);
61 "MaxCpuCount=0x%x, BootCpuCount=0x%x\n",
62 PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
,
63 PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
67 PcdStatus
= PcdSet64S (PcdTdxSharedBitMask
, TdSharedPageMask ());
68 ASSERT_RETURN_ERROR (PcdStatus
);
69 DEBUG ((DEBUG_INFO
, "TdxSharedBitMask=0x%llx\n", PcdGet64 (PcdTdxSharedBitMask
)));
71 PcdStatus
= PcdSet64S (PcdPciMmio64Base
, PlatformInfoHob
->PcdPciMmio64Base
);
72 ASSERT_RETURN_ERROR (PcdStatus
);
73 PcdStatus
= PcdSet64S (PcdPciMmio64Size
, PlatformInfoHob
->PcdPciMmio64Size
);
74 ASSERT_RETURN_ERROR (PcdStatus
);
75 PcdStatus
= PcdSet64S (PcdPciMmio32Base
, PlatformInfoHob
->PcdPciMmio32Base
);
76 ASSERT_RETURN_ERROR (PcdStatus
);
77 PcdStatus
= PcdSet64S (PcdPciMmio32Size
, PlatformInfoHob
->PcdPciMmio32Size
);
78 ASSERT_RETURN_ERROR (PcdStatus
);
79 PcdStatus
= PcdSet64S (PcdPciIoBase
, PlatformInfoHob
->PcdPciIoBase
);
80 ASSERT_RETURN_ERROR (PcdStatus
);
81 PcdStatus
= PcdSet64S (PcdPciIoSize
, PlatformInfoHob
->PcdPciIoSize
);
82 ASSERT_RETURN_ERROR (PcdStatus
);
87 Location of resource hob matching type and starting address
89 @param[in] Type The type of resource hob to locate.
91 @param[in] Start The resource hob must at least begin at address.
93 @retval pointer to resource Return pointer to a resource hob that matches or NULL.
96 EFI_HOB_RESOURCE_DESCRIPTOR
*
97 GetResourceDescriptor (
98 EFI_RESOURCE_TYPE Type
,
99 EFI_PHYSICAL_ADDRESS Start
,
100 EFI_PHYSICAL_ADDRESS End
103 EFI_PEI_HOB_POINTERS Hob
;
104 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceDescriptor
= NULL
;
106 Hob
.Raw
= GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
);
107 while (Hob
.Raw
!= NULL
) {
110 "%a:%d: resource type 0x%x %llx %llx\n",
113 Hob
.ResourceDescriptor
->ResourceType
,
114 Hob
.ResourceDescriptor
->PhysicalStart
,
115 Hob
.ResourceDescriptor
->ResourceLength
118 if ((Hob
.ResourceDescriptor
->ResourceType
== Type
) &&
119 (Hob
.ResourceDescriptor
->PhysicalStart
>= Start
) &&
120 ((Hob
.ResourceDescriptor
->PhysicalStart
+ Hob
.ResourceDescriptor
->ResourceLength
) < End
))
122 ResourceDescriptor
= Hob
.ResourceDescriptor
;
126 Hob
.Raw
= GET_NEXT_HOB (Hob
);
127 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
, Hob
.Raw
);
130 return ResourceDescriptor
;
134 Location of resource hob matching type and highest address below end
136 @param[in] Type The type of resource hob to locate.
138 @param[in] End The resource hob return is the closest to the End address
140 @retval pointer to resource Return pointer to a resource hob that matches or NULL.
143 EFI_HOB_RESOURCE_DESCRIPTOR
*
144 GetHighestResourceDescriptor (
145 EFI_RESOURCE_TYPE Type
,
146 EFI_PHYSICAL_ADDRESS End
149 EFI_PEI_HOB_POINTERS Hob
;
150 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceDescriptor
= NULL
;
152 Hob
.Raw
= GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
);
153 while (Hob
.Raw
!= NULL
) {
154 if ((Hob
.ResourceDescriptor
->ResourceType
== Type
) &&
155 (Hob
.ResourceDescriptor
->PhysicalStart
< End
))
157 if (!ResourceDescriptor
||
158 (ResourceDescriptor
->PhysicalStart
< Hob
.ResourceDescriptor
->PhysicalStart
))
160 ResourceDescriptor
= Hob
.ResourceDescriptor
;
164 Hob
.Raw
= GET_NEXT_HOB (Hob
);
165 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
, Hob
.Raw
);
168 return ResourceDescriptor
;
172 Set the shared bit for mmio region in Tdx guest.
174 In Tdx guest there are 2 ways to access mmio, TdVmcall or direct access.
175 For direct access, the shared bit of the PageTableEntry should be set.
176 The mmio region information is retrieved from hob list.
178 @retval EFI_SUCCESS The shared bit is set successfully.
179 @retval EFI_UNSUPPORTED Setting the shared bit of memory region
187 EFI_PEI_HOB_POINTERS Hob
;
189 Hob
.Raw
= (UINT8
*)GetHobList ();
192 // Parse the HOB list until end of list or matching type is found.
194 while (!END_OF_HOB_LIST (Hob
)) {
195 if ( (Hob
.Header
->HobType
== EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
)
196 && (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_MEMORY_MAPPED_IO
))
198 MemEncryptTdxSetPageSharedBit (
200 Hob
.ResourceDescriptor
->PhysicalStart
,
201 EFI_SIZE_TO_PAGES (Hob
.ResourceDescriptor
->ResourceLength
)
205 Hob
.Raw
= GET_NEXT_HOB (Hob
);
214 IN EFI_HANDLE ImageHandle
,
215 IN EFI_SYSTEM_TABLE
*SystemTable
219 RETURN_STATUS PcdStatus
;
220 EFI_HOB_RESOURCE_DESCRIPTOR
*Res
= NULL
;
221 EFI_HOB_RESOURCE_DESCRIPTOR
*MemRes
= NULL
;
222 EFI_HOB_PLATFORM_INFO
*PlatformInfo
= NULL
;
223 EFI_HOB_GUID_TYPE
*GuidHob
;
224 UINT32 CpuMaxLogicalProcessorNumber
;
225 TD_RETURN_DATA TdReturnData
;
226 EFI_EVENT QemuAcpiTableEvent
;
229 GuidHob
= GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid
);
231 if (GuidHob
== NULL
) {
232 return EFI_UNSUPPORTED
;
236 // Both Td and Non-Td guest have PlatformInfoHob which contains the HostBridgePciDevId
238 PlatformInfo
= (EFI_HOB_PLATFORM_INFO
*)GET_GUID_HOB_DATA (GuidHob
);
239 ASSERT (PlatformInfo
->HostBridgeDevId
!= 0);
240 PcdStatus
= PcdSet16S (PcdOvmfHostBridgePciDevId
, PlatformInfo
->HostBridgeDevId
);
241 ASSERT_RETURN_ERROR (PcdStatus
);
243 #ifdef TDX_PEI_LESS_BOOT
245 // For Pei-less boot, PlatformInfo contains more information and
246 // need to set PCDs based on these information.
248 SetPcdSettings (PlatformInfo
);
251 if (!TdIsEnabled ()) {
253 // If it is Non-Td guest, we're done.
261 // Call TDINFO to get actual number of cpus in domain
263 Status
= TdCall (TDCALL_TDINFO
, 0, 0, 0, &TdReturnData
);
264 ASSERT (Status
== EFI_SUCCESS
);
266 CpuMaxLogicalProcessorNumber
= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
269 // Adjust PcdCpuMaxLogicalProcessorNumber, if needed. If firmware is configured for
270 // more than number of reported cpus, update.
272 if (CpuMaxLogicalProcessorNumber
> TdReturnData
.TdInfo
.NumVcpus
) {
273 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, TdReturnData
.TdInfo
.NumVcpus
);
274 ASSERT_RETURN_ERROR (PcdStatus
);
278 // Register for protocol notifications to call the AlterAcpiTable(),
279 // the protocol will be installed in AcpiPlatformDxe when the ACPI
280 // table provided by Qemu is ready.
282 Status
= gBS
->CreateEvent (
290 Status
= gBS
->RegisterProtocolNotify (
291 &gQemuAcpiTableNotifyProtocolGuid
,
296 #define INIT_PCDSET(NAME, RES) do {\
297 PcdStatus = PcdSet64S (NAME##Base, (RES)->PhysicalStart); \
298 ASSERT_RETURN_ERROR (PcdStatus); \
299 PcdStatus = PcdSet64S (NAME##Size, (RES)->ResourceLength); \
300 ASSERT_RETURN_ERROR (PcdStatus); \
304 PcdSet16S (PcdOvmfHostBridgePciDevId
, PlatformInfo
->HostBridgeDevId
);
306 if ((Res
= GetResourceDescriptor (EFI_RESOURCE_MEMORY_MAPPED_IO
, (EFI_PHYSICAL_ADDRESS
)0x100000000, (EFI_PHYSICAL_ADDRESS
)-1)) != NULL
) {
307 INIT_PCDSET (PcdPciMmio64
, Res
);
310 if ((Res
= GetResourceDescriptor (EFI_RESOURCE_IO
, 0, 0x10001)) != NULL
) {
311 INIT_PCDSET (PcdPciIo
, Res
);
315 // To find low mmio, first find top of low memory, and then search for io space.
317 if ((MemRes
= GetHighestResourceDescriptor (EFI_RESOURCE_SYSTEM_MEMORY
, 0xffc00000)) != NULL
) {
318 if ((Res
= GetResourceDescriptor (EFI_RESOURCE_MEMORY_MAPPED_IO
, MemRes
->PhysicalStart
, 0x100000000)) != NULL
) {
319 INIT_PCDSET (PcdPciMmio32
, Res
);