TianoCore EDK2 master
Loading...
Searching...
No Matches
AmdSevDxe.c
Go to the documentation of this file.
1
14#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
22#include <Library/PcdLib.h>
23#include <Pi/PiDxeCis.h>
26#include <Uefi/UefiSpec.h>
27
28// Present, initialized, tested bits defined in MdeModulePkg/Core/Dxe/DxeMain.h
29#define EFI_MEMORY_INTERNAL_MASK 0x0700000000000000ULL
30
33AllocateConfidentialComputingBlob (
34 OUT CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION **CcBlobPtr
35 )
36{
37 EFI_STATUS Status;
38 CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION *CcBlob;
39
40 Status = gBS->AllocatePool (
42 sizeof (CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION),
43 (VOID **)&CcBlob
44 );
45 if (EFI_ERROR (Status)) {
46 return Status;
47 }
48
49 CcBlob->Header = SIGNATURE_32 ('A', 'M', 'D', 'E');
50 CcBlob->Version = 1;
51 CcBlob->Reserved = 0;
52 CcBlob->SecretsPhysicalAddress = (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfSnpSecretsBase);
53 CcBlob->SecretsSize = FixedPcdGet32 (PcdOvmfSnpSecretsSize);
54 CcBlob->Reserved1 = 0;
55 CcBlob->CpuidPhysicalAddress = (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfCpuidBase);
56 CcBlob->CpuidLSize = FixedPcdGet32 (PcdOvmfCpuidSize);
57 CcBlob->Reserved2 = 0;
58
59 *CcBlobPtr = CcBlob;
60
61 return EFI_SUCCESS;
62}
63
64STATIC EFI_HANDLE mAmdSevDxeHandle = NULL;
65
66STATIC BOOLEAN mAcceptAllMemoryAtEBS = TRUE;
67
68STATIC EFI_EVENT mAcceptAllMemoryEvent = NULL;
69
72EFIAPI
73AmdSevMemoryAccept (
75 IN EFI_PHYSICAL_ADDRESS StartAddress,
76 IN UINTN Size
77 )
78{
79 //
80 // The StartAddress must be page-aligned, and the Size must be a positive
81 // multiple of SIZE_4KB. Use an assert instead of returning an erros since
82 // this is an EDK2-internal protocol.
83 //
84 ASSERT (IS_ALIGNED (StartAddress, SIZE_4KB));
85 ASSERT (IS_ALIGNED (Size, SIZE_4KB));
86 ASSERT (Size != 0);
87
89 StartAddress,
91 );
92
93 return EFI_SUCCESS;
94}
95
98AcceptAllMemory (
99 VOID
100 )
101{
103 UINTN NumEntries;
104 UINTN Index;
105 EFI_STATUS Status;
106
107 DEBUG ((DEBUG_INFO, "Accepting all memory\n"));
108
109 /*
110 * Get a copy of the memory space map to iterate over while
111 * changing the map.
112 */
113 Status = gDS->GetMemorySpaceMap (&NumEntries, &AllDescMap);
114 if (EFI_ERROR (Status)) {
115 return Status;
116 }
117
118 for (Index = 0; Index < NumEntries; Index++) {
120
121 Desc = &AllDescMap[Index];
122 if (Desc->GcdMemoryType != EfiGcdMemoryTypeUnaccepted) {
123 continue;
124 }
125
126 Status = AmdSevMemoryAccept (
127 NULL,
128 Desc->BaseAddress,
129 Desc->Length
130 );
131 if (EFI_ERROR (Status)) {
132 break;
133 }
134
135 Status = gDS->RemoveMemorySpace (Desc->BaseAddress, Desc->Length);
136 if (EFI_ERROR (Status)) {
137 break;
138 }
139
140 Status = gDS->AddMemorySpace (
142 Desc->BaseAddress,
143 Desc->Length,
144 // Allocable system memory resource capabilities as masked
145 // in MdeModulePkg/Core/Dxe/Mem/Page.c:PromoteMemoryResource
146 Desc->Capabilities & ~(EFI_MEMORY_INTERNAL_MASK | EFI_MEMORY_RUNTIME)
147 );
148 if (EFI_ERROR (Status)) {
149 break;
150 }
151 }
152
153 gBS->FreePool (AllDescMap);
154 gBS->CloseEvent (mAcceptAllMemoryEvent);
155 return Status;
156}
157
158VOID
159EFIAPI
160ResolveUnacceptedMemory (
161 IN EFI_EVENT Event,
162 IN VOID *Context
163 )
164{
165 EFI_STATUS Status;
166
167 if (!mAcceptAllMemoryAtEBS) {
168 return;
169 }
170
171 Status = AcceptAllMemory ();
172 ASSERT_EFI_ERROR (Status);
173}
174
175STATIC
177EFIAPI
178AllowUnacceptedMemory (
180 )
181{
182 mAcceptAllMemoryAtEBS = FALSE;
183 return EFI_SUCCESS;
184}
185
186STATIC
188 mMemoryAcceptanceProtocol = { AllowUnacceptedMemory };
189
190STATIC EDKII_MEMORY_ACCEPT_PROTOCOL mMemoryAcceptProtocol = {
191 AmdSevMemoryAccept
192};
193
195EFIAPI
196AmdSevDxeEntryPoint (
197 IN EFI_HANDLE ImageHandle,
198 IN EFI_SYSTEM_TABLE *SystemTable
199 )
200{
201 EFI_STATUS Status;
203 UINTN NumEntries;
204 UINTN Index;
205 CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION *SnpBootDxeTable;
206
207 //
208 // Do nothing when SEV is not enabled
209 //
210 if (!MemEncryptSevIsEnabled ()) {
211 return EFI_UNSUPPORTED;
212 }
213
214 //
215 // Iterate through the GCD map and clear the C-bit from MMIO and NonExistent
216 // memory space. The NonExistent memory space will be used for mapping the
217 // MMIO space added later (eg PciRootBridge). By clearing both known MMIO and
218 // NonExistent memory space can gurantee that current and furture MMIO adds
219 // will have C-bit cleared.
220 //
221 Status = gDS->GetMemorySpaceMap (&NumEntries, &AllDescMap);
222 if (!EFI_ERROR (Status)) {
223 for (Index = 0; Index < NumEntries; Index++) {
225
226 Desc = &AllDescMap[Index];
227 if ((Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) ||
228 (Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent))
229 {
231 0,
232 Desc->BaseAddress,
233 EFI_SIZE_TO_PAGES (Desc->Length)
234 );
235 ASSERT_EFI_ERROR (Status);
236 }
237 }
238
239 FreePool (AllDescMap);
240 }
241
242 //
243 // If PCI Express is enabled, the MMCONFIG area has been reserved, rather
244 // than marked as MMIO, and so the C-bit won't be cleared by the above walk
245 // through the GCD map. Check for the MMCONFIG area and clear the C-bit for
246 // the range.
247 //
248 if (PcdGet16 (PcdOvmfHostBridgePciDevId) == INTEL_Q35_MCH_DEVICE_ID) {
250 0,
251 FixedPcdGet64 (PcdPciExpressBaseAddress),
252 EFI_SIZE_TO_PAGES (SIZE_256MB)
253 );
254
255 ASSERT_EFI_ERROR (Status);
256 }
257
258 //
259 // When SMM is enabled, clear the C-bit from SMM Saved State Area
260 //
261 // NOTES: The SavedStateArea address cleared here is before SMBASE
262 // relocation. Currently, we do not clear the SavedStateArea address after
263 // SMBASE is relocated due to the following reasons:
264 //
265 // 1) Guest BIOS never access the relocated SavedStateArea.
266 //
267 // 2) The C-bit works on page-aligned address, but the SavedStateArea
268 // address is not a page-aligned. Theoretically, we could roundup the address
269 // and clear the C-bit of aligned address but looking carefully we found
270 // that some portion of the page contains code -- which will causes a bigger
271 // issues for SEV guest. When SEV is enabled, all the code must be encrypted
272 // otherwise hardware will cause trap.
273 //
274 // We restore the C-bit for this SMM Saved State Area after SMBASE relocation
275 // is completed (See OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c).
276 //
277 if (FeaturePcdGet (PcdSmmSmramRequire)) {
278 UINTN MapPagesBase;
279 UINTN MapPagesCount;
280
282 &MapPagesBase,
283 &MapPagesCount
284 );
285 ASSERT_EFI_ERROR (Status);
286
287 //
288 // Although these pages were set aside (i.e., allocated) by PlatformPei, we
289 // could be after a warm reboot from the OS. Don't leak any stale OS data
290 // to the hypervisor.
291 //
292 ZeroMem ((VOID *)MapPagesBase, EFI_PAGES_TO_SIZE (MapPagesCount));
293
295 0, // Cr3BaseAddress -- use current CR3
296 MapPagesBase, // BaseAddress
297 MapPagesCount // NumPages
298 );
299 if (EFI_ERROR (Status)) {
300 DEBUG ((
301 DEBUG_ERROR,
302 "%a: MemEncryptSevClearPageEncMask(): %r\n",
303 __func__,
304 Status
305 ));
306 ASSERT (FALSE);
307 CpuDeadLoop ();
308 }
309 }
310
311 Status = AllocateConfidentialComputingBlob (&SnpBootDxeTable);
312 if (EFI_ERROR (Status)) {
313 DEBUG ((
314 DEBUG_ERROR,
315 "%a: AllocateConfidentialComputingBlob(): %r\n",
316 __func__,
317 Status
318 ));
319 ASSERT (FALSE);
320 CpuDeadLoop ();
321 }
322
324 //
325 // Memory acceptance began being required in SEV-SNP, so install the
326 // memory accept protocol implementation for a SEV-SNP active guest.
327 //
328 Status = gBS->InstallMultipleProtocolInterfaces (
329 &mAmdSevDxeHandle,
330 &gEdkiiMemoryAcceptProtocolGuid,
331 &mMemoryAcceptProtocol,
332 &gOvmfSevMemoryAcceptanceProtocolGuid,
333 &mMemoryAcceptanceProtocol,
334 NULL
335 );
336 ASSERT_EFI_ERROR (Status);
337
338 // SEV-SNP support does not automatically imply unaccepted memory support,
339 // so make ExitBootServices accept all unaccepted memory if support is
340 // not communicated.
341 Status = gBS->CreateEventEx (
342 EVT_NOTIFY_SIGNAL,
343 TPL_CALLBACK,
344 ResolveUnacceptedMemory,
345 NULL,
346 &gEfiEventBeforeExitBootServicesGuid,
347 &mAcceptAllMemoryEvent
348 );
349
350 if (EFI_ERROR (Status)) {
351 DEBUG ((DEBUG_ERROR, "AllowUnacceptedMemory event creation for EventBeforeExitBootServices failed.\n"));
352 }
353
354 //
355 // If its SEV-SNP active guest then install the CONFIDENTIAL_COMPUTING_SEV_SNP_BLOB.
356 // It contains the location for both the Secrets and CPUID page.
357 //
358 return gBS->InstallConfigurationTable (
359 &gConfidentialComputingSevSnpBlobGuid,
360 SnpBootDxeTable
361 );
362 }
363
364 return EFI_SUCCESS;
365}
UINT64 UINTN
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_DXE_SERVICES * gDS
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IS_ALIGNED(Value, Alignment)
Definition: Base.h:912
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define SIGNATURE_32(A, B, C, D)
Definition: Base.h:1310
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFIAPI MemEncryptSevClearPageEncMask(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages)
BOOLEAN EFIAPI MemEncryptSevSnpIsEnabled(VOID)
BOOLEAN EFIAPI MemEncryptSevIsEnabled(VOID)
VOID EFIAPI MemEncryptSevSnpPreValidateSystemRam(IN PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages)
RETURN_STATUS EFIAPI MemEncryptSevLocateInitialSmramSaveStateMapPages(OUT UINTN *BaseAddress, OUT UINTN *NumberOfPages)
RETURN_STATUS EFIAPI MemEncryptSevClearMmioPageEncMask(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages)
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
#define FixedPcdGet32(TokenName)
Definition: PcdLib.h:92
#define FixedPcdGet64(TokenName)
Definition: PcdLib.h:106
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
@ EfiGcdMemoryTypeNonExistent
Definition: PiDxeCis.h:26
@ EfiGcdMemoryTypeUnaccepted
Definition: PiDxeCis.h:63
@ EfiGcdMemoryTypeSystemMemory
Definition: PiDxeCis.h:38
@ EfiGcdMemoryTypeMemoryMappedIo
Definition: PiDxeCis.h:44
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ EfiACPIReclaimMemory