TianoCore EDK2 master
Loading...
Searching...
No Matches
IoMmuBuffer.c
Go to the documentation of this file.
1
8#include <Library/BaseLib.h>
10#include <Library/DebugLib.h>
14#include <Library/PcdLib.h>
17#include "IoMmuInternal.h"
18
19extern BOOLEAN mReservedSharedMemSupported;
20
21#define SIZE_OF_MEM_RANGE(MemRange) (MemRange->HeaderSize + MemRange->DataSize)
22
23#define RESERVED_MEM_BITMAP_4K_MASK 0xf
24#define RESERVED_MEM_BITMAP_32K_MASK 0xff0
25#define RESERVED_MEM_BITMAP_128K_MASK 0x3000
26#define RESERVED_MEM_BITMAP_1M_MASK 0x40000
27#define RESERVED_MEM_BITMAP_2M_MASK 0x180000
28#define RESERVED_MEM_BITMAP_MASK 0x1fffff
29
65 { RESERVED_MEM_BITMAP_4K_MASK, 0, 4, SIZE_4KB, SIZE_4KB, 0 },
66 { RESERVED_MEM_BITMAP_32K_MASK, 4, 8, SIZE_32KB, SIZE_4KB, 0 },
67 { RESERVED_MEM_BITMAP_128K_MASK, 12, 2, SIZE_128KB, SIZE_4KB, 0 },
68 { RESERVED_MEM_BITMAP_1M_MASK, 14, 1, SIZE_1MB, SIZE_4KB, 0 },
69 { RESERVED_MEM_BITMAP_2M_MASK, 15, 2, SIZE_2MB, SIZE_4KB, 0 },
70};
71
72//
73// Bitmap of the allocation of reserved memory.
74//
75STATIC UINT32 mReservedMemBitmap = 0;
76
77//
78// Start address of the reserved memory region.
79//
80STATIC EFI_PHYSICAL_ADDRESS mReservedSharedMemAddress = 0;
81
82//
83// Total size of the reserved memory region.
84//
85STATIC UINT32 mReservedSharedMemSize = 0;
86
93UINT32
95 VOID
96 )
97{
98 UINT32 Index;
100
101 if (mReservedSharedMemSize != 0) {
102 return mReservedSharedMemSize;
103 }
104
105 for (Index = 0; Index < ARRAY_SIZE (mReservedMemRanges); Index++) {
106 MemRange = &mReservedMemRanges[Index];
107 mReservedSharedMemSize += (SIZE_OF_MEM_RANGE (MemRange) * MemRange->Slots);
108 }
109
110 return mReservedSharedMemSize;
111}
112
137 VOID
138 )
139{
140 EFI_STATUS Status;
141 UINT32 Index1, Index2;
142 UINTN TotalPages;
143 IOMMU_RESERVED_MEM_RANGE *MemRange;
144 EFI_PHYSICAL_ADDRESS PhysicalAddress;
145 UINT64 SharedAddress;
146
147 if (!mReservedSharedMemSupported) {
148 return EFI_UNSUPPORTED;
149 }
150
152
153 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePages (TotalPages);
154 DEBUG ((
155 DEBUG_VERBOSE,
156 "%a: ReservedMem (%d pages) address = 0x%llx\n",
157 __func__,
158 TotalPages,
159 PhysicalAddress
160 ));
161
162 mReservedMemBitmap = 0;
163 mReservedSharedMemAddress = PhysicalAddress;
164
165 for (Index1 = 0; Index1 < ARRAY_SIZE (mReservedMemRanges); Index1++) {
166 MemRange = &mReservedMemRanges[Index1];
167 MemRange->StartAddressOfMemRange = PhysicalAddress;
168
169 for (Index2 = 0; Index2 < MemRange->Slots; Index2++) {
170 SharedAddress = (UINT64)(UINTN)(MemRange->StartAddressOfMemRange + Index2 * SIZE_OF_MEM_RANGE (MemRange) + MemRange->HeaderSize);
171
172 if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
174 0,
175 SharedAddress,
176 EFI_SIZE_TO_PAGES (MemRange->DataSize)
177 );
178 ASSERT (!EFI_ERROR (Status));
179 } else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
181 0,
182 SharedAddress,
183 EFI_SIZE_TO_PAGES (MemRange->DataSize)
184 );
185 ASSERT (!EFI_ERROR (Status));
186 } else {
187 ASSERT (FALSE);
188 }
189 }
190
191 PhysicalAddress += (MemRange->Slots * SIZE_OF_MEM_RANGE (MemRange));
192 }
193
194 return EFI_SUCCESS;
195}
196
204 BOOLEAN MemoryMapLocked
205 )
206{
207 EFI_STATUS Status;
208 UINT32 Index1, Index2;
209 IOMMU_RESERVED_MEM_RANGE *MemRange;
210 UINT64 SharedAddress;
211
212 if (!mReservedSharedMemSupported) {
213 return EFI_SUCCESS;
214 }
215
216 for (Index1 = 0; Index1 < ARRAY_SIZE (mReservedMemRanges); Index1++) {
217 MemRange = &mReservedMemRanges[Index1];
218 for (Index2 = 0; Index2 < MemRange->Slots; Index2++) {
219 SharedAddress = (UINT64)(UINTN)(MemRange->StartAddressOfMemRange + Index2 * SIZE_OF_MEM_RANGE (MemRange) + MemRange->HeaderSize);
220
221 if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
223 0,
224 SharedAddress,
225 EFI_SIZE_TO_PAGES (MemRange->DataSize)
226 );
227 ASSERT (!EFI_ERROR (Status));
228 } else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
230 0,
231 SharedAddress,
232 EFI_SIZE_TO_PAGES (MemRange->DataSize)
233 );
234 ASSERT (!EFI_ERROR (Status));
235 } else {
236 ASSERT (FALSE);
237 }
238 }
239 }
240
241 if (!MemoryMapLocked) {
242 FreePages ((VOID *)(UINTN)mReservedSharedMemAddress, EFI_SIZE_TO_PAGES (CalcuateReservedMemSize ()));
243 mReservedSharedMemAddress = 0;
244 mReservedMemBitmap = 0;
245 }
246
247 mReservedSharedMemSupported = FALSE;
248
249 return EFI_SUCCESS;
250}
251
266STATIC
270 IN EFI_MEMORY_TYPE MemoryType,
271 IN UINTN Pages,
272 OUT UINT32 *ReservedMemBit,
273 IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
274 )
275{
276 UINT32 MemBitmap;
277 UINT32 ReservedMemBitmap;
278 UINT8 Index;
279 IOMMU_RESERVED_MEM_RANGE *MemRange;
280 UINTN PagesOfLastMemRange;
281
282 *ReservedMemBit = 0;
283
284 if (Pages == 0) {
285 ASSERT (FALSE);
286 return EFI_INVALID_PARAMETER;
287 }
288
289 if (!mReservedSharedMemSupported) {
290 goto LegacyAllocateBuffer;
291 }
292
293 if (mReservedSharedMemAddress == 0) {
294 goto LegacyAllocateBuffer;
295 }
296
297 PagesOfLastMemRange = 0;
298
299 for (Index = 0; Index < ARRAY_SIZE (mReservedMemRanges); Index++) {
300 if ((Pages > PagesOfLastMemRange) && (Pages <= EFI_SIZE_TO_PAGES (mReservedMemRanges[Index].DataSize))) {
301 break;
302 }
303
304 PagesOfLastMemRange = EFI_SIZE_TO_PAGES (mReservedMemRanges[Index].DataSize);
305 }
306
307 if (Index == ARRAY_SIZE (mReservedMemRanges)) {
308 // There is no suitable size of reserved memory. Turn to legacy allocate.
309 goto LegacyAllocateBuffer;
310 }
311
312 MemRange = &mReservedMemRanges[Index];
313
314 do {
315 ReservedMemBitmap = mReservedMemBitmap;
316
317 if ((ReservedMemBitmap & MemRange->BitmapMask) == MemRange->BitmapMask) {
318 // The reserved memory is exhausted. Turn to legacy allocate.
319 goto LegacyAllocateBuffer;
320 }
321
322 MemBitmap = (ReservedMemBitmap & MemRange->BitmapMask) >> MemRange->Shift;
323
324 for (Index = 0; Index < MemRange->Slots; Index++) {
325 if ((MemBitmap & (UINT8)(1<<Index)) == 0) {
326 break;
327 }
328 }
329
330 ASSERT (Index != MemRange->Slots);
331
332 *PhysicalAddress = MemRange->StartAddressOfMemRange + Index * SIZE_OF_MEM_RANGE (MemRange) + MemRange->HeaderSize;
333 *ReservedMemBit = (UINT32)(1 << (Index + MemRange->Shift));
334 } while (ReservedMemBitmap != InterlockedCompareExchange32 (
335 &mReservedMemBitmap,
336 ReservedMemBitmap,
337 ReservedMemBitmap | *ReservedMemBit
338 ));
339
340 DEBUG ((
341 DEBUG_VERBOSE,
342 "%a: range-size: %lx, start-address=0x%llx, pages=0x%llx, bits=0x%lx, bitmap: %lx => %lx\n",
343 __func__,
344 MemRange->DataSize,
345 *PhysicalAddress,
346 Pages,
347 *ReservedMemBit,
348 ReservedMemBitmap,
349 ReservedMemBitmap | *ReservedMemBit
350 ));
351
352 return EFI_SUCCESS;
353
354LegacyAllocateBuffer:
355
356 *ReservedMemBit = 0;
357 return gBS->AllocatePages (Type, MemoryType, Pages, PhysicalAddress);
358}
359
374 IN EFI_MEMORY_TYPE MemoryType,
375 IN OUT MAP_INFO *MapInfo
376 )
377{
378 EFI_STATUS Status;
379
380 Status = InternalAllocateBuffer (
381 Type,
382 MemoryType,
383 MapInfo->NumberOfPages,
384 &MapInfo->ReservedMemBitmap,
385 &MapInfo->PlainTextAddress
386 );
387 ASSERT (Status == EFI_SUCCESS);
388
389 return Status;
390}
391
397STATIC
398VOID
400 IN UINT32 ReservedMemBit
401 )
402{
403 UINT32 ReservedMemBitmap;
404
405 do {
406 ReservedMemBitmap = mReservedMemBitmap;
407 } while (ReservedMemBitmap != InterlockedCompareExchange32 (
408 &mReservedMemBitmap,
409 ReservedMemBitmap,
410 ReservedMemBitmap & ~ReservedMemBit
411 ));
412}
413
422 IN OUT MAP_INFO *MapInfo
423 )
424{
425 if (MapInfo->ReservedMemBitmap == 0) {
426 gBS->FreePages (MapInfo->PlainTextAddress, MapInfo->NumberOfPages);
427 } else {
428 DEBUG ((
429 DEBUG_VERBOSE,
430 "%a: PlainTextAddress=0x%Lx, bits=0x%Lx, bitmap: %Lx => %Lx\n",
431 __func__,
432 MapInfo->PlainTextAddress,
433 MapInfo->ReservedMemBitmap,
434 mReservedMemBitmap,
435 mReservedMemBitmap & ((UINT32)(~MapInfo->ReservedMemBitmap))
436 ));
437 ClearReservedMemBit (MapInfo->ReservedMemBitmap);
438 MapInfo->PlainTextAddress = 0;
439 MapInfo->ReservedMemBitmap = 0;
440 }
441
442 return EFI_SUCCESS;
443}
444
458 IN EFI_MEMORY_TYPE MemoryType,
459 IN UINTN CommonBufferPages,
460 OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress,
461 OUT UINT32 *ReservedMemBitmap
462 )
463{
464 EFI_STATUS Status;
465
466 Status = InternalAllocateBuffer (
468 MemoryType,
469 CommonBufferPages,
470 ReservedMemBitmap,
471 PhysicalAddress
472 );
473 ASSERT (Status == EFI_SUCCESS);
474
475 if (*ReservedMemBitmap != 0) {
476 *PhysicalAddress -= SIZE_4KB;
477 }
478
479 return Status;
480}
481
493 IN COMMON_BUFFER_HEADER *CommonBufferHeader,
494 IN UINTN CommonBufferPages
495 )
496{
497 if (!mReservedSharedMemSupported) {
498 goto LegacyFreeCommonBuffer;
499 }
500
501 if (CommonBufferHeader->ReservedMemBitmap == 0) {
502 goto LegacyFreeCommonBuffer;
503 }
504
505 DEBUG ((
506 DEBUG_VERBOSE,
507 "%a: CommonBuffer=0x%Lx, bits=0x%Lx, bitmap: %Lx => %Lx\n",
508 __func__,
509 (UINT64)(UINTN)CommonBufferHeader + SIZE_4KB,
510 CommonBufferHeader->ReservedMemBitmap,
511 mReservedMemBitmap,
512 mReservedMemBitmap & ((UINT32)(~CommonBufferHeader->ReservedMemBitmap))
513 ));
514
515 ClearReservedMemBit (CommonBufferHeader->ReservedMemBitmap);
516 return EFI_SUCCESS;
517
518LegacyFreeCommonBuffer:
519 return gBS->FreePages ((UINTN)CommonBufferHeader, CommonBufferPages);
520}
UINT64 UINTN
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
STATIC EFI_STATUS InternalAllocateBuffer(IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, OUT UINT32 *ReservedMemBit, IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress)
Definition: IoMmuBuffer.c:268
EFI_STATUS IoMmuAllocateCommonBuffer(IN EFI_MEMORY_TYPE MemoryType, IN UINTN CommonBufferPages, OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress, OUT UINT32 *ReservedMemBitmap)
Definition: IoMmuBuffer.c:457
EFI_STATUS IoMmuFreeBounceBuffer(IN OUT MAP_INFO *MapInfo)
Definition: IoMmuBuffer.c:421
EFI_STATUS IoMmuFreeCommonBuffer(IN COMMON_BUFFER_HEADER *CommonBufferHeader, IN UINTN CommonBufferPages)
Definition: IoMmuBuffer.c:492
EFI_STATUS IoMmuInitReservedSharedMem(VOID)
Definition: IoMmuBuffer.c:136
EFI_STATUS IoMmuReleaseReservedSharedMem(BOOLEAN MemoryMapLocked)
Definition: IoMmuBuffer.c:203
EFI_STATUS IoMmuAllocateBounceBuffer(IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN OUT MAP_INFO *MapInfo)
Definition: IoMmuBuffer.c:372
STATIC VOID ClearReservedMemBit(IN UINT32 ReservedMemBit)
Definition: IoMmuBuffer.c:399
STATIC UINT32 CalcuateReservedMemSize(VOID)
Definition: IoMmuBuffer.c:94
STATIC IOMMU_RESERVED_MEM_RANGE mReservedMemRanges[]
Definition: IoMmuBuffer.c:64
#define STATIC
Definition: Base.h:264
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFIAPI MemEncryptSevClearPageEncMask(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages)
RETURN_STATUS EFIAPI MemEncryptSevSetPageEncMask(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages)
RETURN_STATUS EFIAPI MemEncryptTdxSetPageSharedBit(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages)
RETURN_STATUS EFIAPI MemEncryptTdxClearPageSharedBit(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages)
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
VOID *EFIAPI AllocatePages(IN UINTN Pages)
UINT32 EFIAPI InterlockedCompareExchange32(IN OUT volatile UINT32 *Value, IN UINT32 CompareValue, IN UINT32 ExchangeValue)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_MEMORY_TYPE
EFI_ALLOCATE_TYPE
Definition: UefiSpec.h:29
@ AllocateMaxAddress
Definition: UefiSpec.h:38