]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/IoMmuDxe/CcIoMmu.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / IoMmuDxe / CcIoMmu.c
1 /** @file
2
3 The protocol provides support to allocate, free, map and umap a DMA buffer
4 for bus master (e.g PciHostBridge). When SEV or TDX is enabled, the DMA
5 operations must be performed on unencrypted buffer hence we use a bounce
6 buffer to map the guest buffer into an unencrypted DMA buffer.
7
8 Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
9 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
10
11 SPDX-License-Identifier: BSD-2-Clause-Patent
12
13 **/
14
15 #include <Library/PcdLib.h>
16 #include <ConfidentialComputingGuestAttr.h>
17 #include "CcIoMmu.h"
18 #include "IoMmuInternal.h"
19
20 //
21 // List of the MAP_INFO structures that have been set up by IoMmuMap() and not
22 // yet torn down by IoMmuUnmap(). The list represents the full set of mappings
23 // currently in effect.
24 //
25 STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos);
26
27 //
28 // Indicate if the feature of reserved memory is supported in DMA operation.
29 //
30 BOOLEAN mReservedSharedMemSupported = FALSE;
31
32 //
33 // ASCII names for EDKII_IOMMU_OPERATION constants, for debug logging.
34 //
35 STATIC CONST CHAR8 *CONST
36 mBusMasterOperationName[EdkiiIoMmuOperationMaximum] = {
37 "Read",
38 "Write",
39 "CommonBuffer",
40 "Read64",
41 "Write64",
42 "CommonBuffer64"
43 };
44
45 /**
46 Provides the controller-specific addresses required to access system memory
47 from a DMA bus master. On SEV/TDX guest, the DMA operations must be performed on
48 shared buffer hence we allocate a bounce buffer to map the HostAddress to a
49 DeviceAddress. The Encryption attribute is removed from the DeviceAddress
50 buffer.
51
52 @param This The protocol instance pointer.
53 @param Operation Indicates if the bus master is going to read or
54 write to system memory.
55 @param HostAddress The system memory address to map to the PCI
56 controller.
57 @param NumberOfBytes On input the number of bytes to map. On output
58 the number of bytes that were mapped.
59 @param DeviceAddress The resulting map address for the bus master
60 PCI controller to use to access the hosts
61 HostAddress.
62 @param Mapping A resulting value to pass to Unmap().
63
64 @retval EFI_SUCCESS The range was mapped for the returned
65 NumberOfBytes.
66 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
67 buffer.
68 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
69 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
70 lack of resources.
71 @retval EFI_DEVICE_ERROR The system hardware could not map the requested
72 address.
73
74 **/
75 EFI_STATUS
76 EFIAPI
77 IoMmuMap (
78 IN EDKII_IOMMU_PROTOCOL *This,
79 IN EDKII_IOMMU_OPERATION Operation,
80 IN VOID *HostAddress,
81 IN OUT UINTN *NumberOfBytes,
82 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
83 OUT VOID **Mapping
84 )
85 {
86 EFI_STATUS Status;
87 MAP_INFO *MapInfo;
88 EFI_ALLOCATE_TYPE AllocateType;
89 COMMON_BUFFER_HEADER *CommonBufferHeader;
90 VOID *DecryptionSource;
91
92 DEBUG ((
93 DEBUG_VERBOSE,
94 "%a: Operation=%a Host=0x%p Bytes=0x%Lx\n",
95 __FUNCTION__,
96 ((Operation >= 0 &&
97 Operation < ARRAY_SIZE (mBusMasterOperationName)) ?
98 mBusMasterOperationName[Operation] :
99 "Invalid"),
100 HostAddress,
101 (UINT64)((NumberOfBytes == NULL) ? 0 : *NumberOfBytes)
102 ));
103
104 if ((HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) ||
105 (Mapping == NULL))
106 {
107 return EFI_INVALID_PARAMETER;
108 }
109
110 Status = EFI_SUCCESS;
111
112 //
113 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
114 // called later.
115 //
116 MapInfo = AllocatePool (sizeof (MAP_INFO));
117 if (MapInfo == NULL) {
118 Status = EFI_OUT_OF_RESOURCES;
119 goto Failed;
120 }
121
122 //
123 // Initialize the MAP_INFO structure, except the PlainTextAddress field
124 //
125 ZeroMem (&MapInfo->Link, sizeof MapInfo->Link);
126 MapInfo->Signature = MAP_INFO_SIG;
127 MapInfo->Operation = Operation;
128 MapInfo->NumberOfBytes = *NumberOfBytes;
129 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
130 MapInfo->CryptedAddress = (UINTN)HostAddress;
131 MapInfo->ReservedMemBitmap = 0;
132
133 //
134 // In the switch statement below, we point "MapInfo->PlainTextAddress" to the
135 // plaintext buffer, according to Operation. We also set "DecryptionSource".
136 //
137 MapInfo->PlainTextAddress = MAX_ADDRESS;
138 AllocateType = AllocateAnyPages;
139 DecryptionSource = (VOID *)(UINTN)MapInfo->CryptedAddress;
140 switch (Operation) {
141 //
142 // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer
143 // is necessary regardless of whether the original (crypted) buffer crosses
144 // the 4GB limit or not -- we have to allocate a separate plaintext buffer.
145 // The only variable is whether the plaintext buffer should be under 4GB.
146 //
147 case EdkiiIoMmuOperationBusMasterRead:
148 case EdkiiIoMmuOperationBusMasterWrite:
149 MapInfo->PlainTextAddress = BASE_4GB - 1;
150 AllocateType = AllocateMaxAddress;
151 //
152 // fall through
153 //
154 case EdkiiIoMmuOperationBusMasterRead64:
155 case EdkiiIoMmuOperationBusMasterWrite64:
156 //
157 // Allocate the implicit plaintext bounce buffer.
158 //
159 Status = IoMmuAllocateBounceBuffer (
160 AllocateType,
161 EfiBootServicesData,
162 MapInfo
163 );
164 if (EFI_ERROR (Status)) {
165 goto FreeMapInfo;
166 }
167
168 break;
169
170 //
171 // For BusMasterCommonBuffer[64] operations, a to-be-plaintext buffer and a
172 // stash buffer (for in-place decryption) have been allocated already, with
173 // AllocateBuffer(). We only check whether the address of the to-be-plaintext
174 // buffer is low enough for the requested operation.
175 //
176 case EdkiiIoMmuOperationBusMasterCommonBuffer:
177 if ((MapInfo->CryptedAddress > BASE_4GB) ||
178 (EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages) >
179 BASE_4GB - MapInfo->CryptedAddress))
180 {
181 //
182 // CommonBuffer operations cannot be remapped. If the common buffer is
183 // above 4GB, then it is not possible to generate a mapping, so return an
184 // error.
185 //
186 Status = EFI_UNSUPPORTED;
187 goto FreeMapInfo;
188 }
189
190 //
191 // fall through
192 //
193 case EdkiiIoMmuOperationBusMasterCommonBuffer64:
194 //
195 // The buffer at MapInfo->CryptedAddress comes from AllocateBuffer().
196 //
197 MapInfo->PlainTextAddress = MapInfo->CryptedAddress;
198 //
199 // Stash the crypted data.
200 //
201 CommonBufferHeader = (COMMON_BUFFER_HEADER *)(
202 (UINTN)MapInfo->CryptedAddress - EFI_PAGE_SIZE
203 );
204 ASSERT (CommonBufferHeader->Signature == COMMON_BUFFER_SIG);
205 CopyMem (
206 CommonBufferHeader->StashBuffer,
207 (VOID *)(UINTN)MapInfo->CryptedAddress,
208 MapInfo->NumberOfBytes
209 );
210 //
211 // Point "DecryptionSource" to the stash buffer so that we decrypt
212 // it to the original location, after the switch statement.
213 //
214 DecryptionSource = CommonBufferHeader->StashBuffer;
215 MapInfo->ReservedMemBitmap = CommonBufferHeader->ReservedMemBitmap;
216 break;
217
218 default:
219 //
220 // Operation is invalid
221 //
222 Status = EFI_INVALID_PARAMETER;
223 goto FreeMapInfo;
224 }
225
226 if (MapInfo->ReservedMemBitmap == 0) {
227 //
228 // If MapInfo->ReservedMemBitmap is 0, it means the bounce buffer is not allocated
229 // from the pre-allocated shared memory, so it must be converted to shared memory here.
230 //
231 if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
232 //
233 // Clear the memory encryption mask on the plaintext buffer.
234 //
235 Status = MemEncryptSevClearPageEncMask (
236 0,
237 MapInfo->PlainTextAddress,
238 MapInfo->NumberOfPages
239 );
240 } else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
241 //
242 // Set the memory shared bit.
243 //
244 Status = MemEncryptTdxSetPageSharedBit (
245 0,
246 MapInfo->PlainTextAddress,
247 MapInfo->NumberOfPages
248 );
249 } else {
250 ASSERT (FALSE);
251 }
252 }
253
254 ASSERT_EFI_ERROR (Status);
255 if (EFI_ERROR (Status)) {
256 CpuDeadLoop ();
257 }
258
259 //
260 // If this is a read operation from the Bus Master's point of view,
261 // then copy the contents of the real buffer into the mapped buffer
262 // so the Bus Master can read the contents of the real buffer.
263 //
264 // For BusMasterCommonBuffer[64] operations, the CopyMem() below will decrypt
265 // the original data (from the stash buffer) back to the original location.
266 //
267 if ((Operation == EdkiiIoMmuOperationBusMasterRead) ||
268 (Operation == EdkiiIoMmuOperationBusMasterRead64) ||
269 (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer) ||
270 (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64))
271 {
272 CopyMem (
273 (VOID *)(UINTN)MapInfo->PlainTextAddress,
274 DecryptionSource,
275 MapInfo->NumberOfBytes
276 );
277 }
278
279 //
280 // Track all MAP_INFO structures.
281 //
282 InsertHeadList (&mMapInfos, &MapInfo->Link);
283 //
284 // Populate output parameters.
285 //
286 *DeviceAddress = MapInfo->PlainTextAddress;
287 *Mapping = MapInfo;
288
289 DEBUG ((
290 DEBUG_VERBOSE,
291 "%a: Mapping=0x%p Device(PlainText)=0x%Lx Crypted=0x%Lx Pages=0x%Lx, ReservedMemBitmap=0x%Lx\n",
292 __FUNCTION__,
293 MapInfo,
294 MapInfo->PlainTextAddress,
295 MapInfo->CryptedAddress,
296 (UINT64)MapInfo->NumberOfPages,
297 MapInfo->ReservedMemBitmap
298 ));
299
300 return EFI_SUCCESS;
301
302 FreeMapInfo:
303 FreePool (MapInfo);
304
305 Failed:
306 *NumberOfBytes = 0;
307 return Status;
308 }
309
310 /**
311 Completes the Map() operation and releases any corresponding resources.
312
313 This is an internal worker function that only extends the Map() API with
314 the MemoryMapLocked parameter.
315
316 @param This The protocol instance pointer.
317 @param Mapping The mapping value returned from Map().
318 @param MemoryMapLocked The function is executing on the stack of
319 gBS->ExitBootServices(); changes to the UEFI
320 memory map are forbidden.
321
322 @retval EFI_SUCCESS The range was unmapped.
323 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
324 Map().
325 @retval EFI_DEVICE_ERROR The data was not committed to the target system
326 memory.
327 **/
328 STATIC
329 EFI_STATUS
330 EFIAPI
331 IoMmuUnmapWorker (
332 IN EDKII_IOMMU_PROTOCOL *This,
333 IN VOID *Mapping,
334 IN BOOLEAN MemoryMapLocked
335 )
336 {
337 MAP_INFO *MapInfo;
338 EFI_STATUS Status;
339 COMMON_BUFFER_HEADER *CommonBufferHeader;
340 VOID *EncryptionTarget;
341
342 DEBUG ((
343 DEBUG_VERBOSE,
344 "%a: Mapping=0x%p MemoryMapLocked=%d\n",
345 __FUNCTION__,
346 Mapping,
347 MemoryMapLocked
348 ));
349
350 if (Mapping == NULL) {
351 return EFI_INVALID_PARAMETER;
352 }
353
354 MapInfo = (MAP_INFO *)Mapping;
355 Status = EFI_SUCCESS;
356 //
357 // set CommonBufferHeader to suppress incorrect compiler/analyzer warnings
358 //
359 CommonBufferHeader = NULL;
360
361 //
362 // For BusMasterWrite[64] operations and BusMasterCommonBuffer[64] operations
363 // we have to encrypt the results, ultimately to the original place (i.e.,
364 // "MapInfo->CryptedAddress").
365 //
366 // For BusMasterCommonBuffer[64] operations however, this encryption has to
367 // land in-place, so divert the encryption to the stash buffer first.
368 //
369 EncryptionTarget = (VOID *)(UINTN)MapInfo->CryptedAddress;
370
371 switch (MapInfo->Operation) {
372 case EdkiiIoMmuOperationBusMasterCommonBuffer:
373 case EdkiiIoMmuOperationBusMasterCommonBuffer64:
374 ASSERT (MapInfo->PlainTextAddress == MapInfo->CryptedAddress);
375
376 CommonBufferHeader = (COMMON_BUFFER_HEADER *)(
377 (UINTN)MapInfo->PlainTextAddress - EFI_PAGE_SIZE
378 );
379 ASSERT (CommonBufferHeader->Signature == COMMON_BUFFER_SIG);
380 EncryptionTarget = CommonBufferHeader->StashBuffer;
381 //
382 // fall through
383 //
384
385 case EdkiiIoMmuOperationBusMasterWrite:
386 case EdkiiIoMmuOperationBusMasterWrite64:
387 CopyMem (
388 EncryptionTarget,
389 (VOID *)(UINTN)MapInfo->PlainTextAddress,
390 MapInfo->NumberOfBytes
391 );
392 break;
393
394 default:
395 //
396 // nothing to encrypt after BusMasterRead[64] operations
397 //
398 break;
399 }
400
401 if (MapInfo->ReservedMemBitmap == 0) {
402 if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
403 //
404 // Restore the memory encryption mask on the area we used to hold the
405 // plaintext.
406 //
407 Status = MemEncryptSevSetPageEncMask (
408 0,
409 MapInfo->PlainTextAddress,
410 MapInfo->NumberOfPages
411 );
412 } else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
413 //
414 // Restore the memory shared bit mask on the area we used to hold the
415 // plaintext.
416 //
417 Status = MemEncryptTdxClearPageSharedBit (
418 0,
419 MapInfo->PlainTextAddress,
420 MapInfo->NumberOfPages
421 );
422 } else {
423 ASSERT (FALSE);
424 }
425 }
426
427 ASSERT_EFI_ERROR (Status);
428 if (EFI_ERROR (Status)) {
429 CpuDeadLoop ();
430 }
431
432 //
433 // For BusMasterCommonBuffer[64] operations, copy the stashed data to the
434 // original (now encrypted) location.
435 //
436 // For all other operations, fill the late bounce buffer (which existed as
437 // plaintext at some point) with zeros, and then release it (unless the UEFI
438 // memory map is locked).
439 //
440 if ((MapInfo->Operation == EdkiiIoMmuOperationBusMasterCommonBuffer) ||
441 (MapInfo->Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64))
442 {
443 CopyMem (
444 (VOID *)(UINTN)MapInfo->CryptedAddress,
445 CommonBufferHeader->StashBuffer,
446 MapInfo->NumberOfBytes
447 );
448 } else {
449 ZeroMem (
450 (VOID *)(UINTN)MapInfo->PlainTextAddress,
451 EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages)
452 );
453
454 if (!MemoryMapLocked) {
455 IoMmuFreeBounceBuffer (MapInfo);
456 }
457 }
458
459 //
460 // Forget the MAP_INFO structure, then free it (unless the UEFI memory map is
461 // locked).
462 //
463 RemoveEntryList (&MapInfo->Link);
464 if (!MemoryMapLocked) {
465 FreePool (MapInfo);
466 }
467
468 return EFI_SUCCESS;
469 }
470
471 /**
472 Completes the Map() operation and releases any corresponding resources.
473
474 @param This The protocol instance pointer.
475 @param Mapping The mapping value returned from Map().
476
477 @retval EFI_SUCCESS The range was unmapped.
478 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
479 Map().
480 @retval EFI_DEVICE_ERROR The data was not committed to the target system
481 memory.
482 **/
483 EFI_STATUS
484 EFIAPI
485 IoMmuUnmap (
486 IN EDKII_IOMMU_PROTOCOL *This,
487 IN VOID *Mapping
488 )
489 {
490 return IoMmuUnmapWorker (
491 This,
492 Mapping,
493 FALSE // MemoryMapLocked
494 );
495 }
496
497 /**
498 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
499 OperationBusMasterCommonBuffer64 mapping.
500
501 @param This The protocol instance pointer.
502 @param Type This parameter is not used and must be ignored.
503 @param MemoryType The type of memory to allocate,
504 EfiBootServicesData or EfiRuntimeServicesData.
505 @param Pages The number of pages to allocate.
506 @param HostAddress A pointer to store the base system memory
507 address of the allocated range.
508 @param Attributes The requested bit mask of attributes for the
509 allocated range.
510
511 @retval EFI_SUCCESS The requested memory pages were allocated.
512 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
513 attribute bits are MEMORY_WRITE_COMBINE and
514 MEMORY_CACHED.
515 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
516 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
517
518 **/
519 EFI_STATUS
520 EFIAPI
521 IoMmuAllocateBuffer (
522 IN EDKII_IOMMU_PROTOCOL *This,
523 IN EFI_ALLOCATE_TYPE Type,
524 IN EFI_MEMORY_TYPE MemoryType,
525 IN UINTN Pages,
526 IN OUT VOID **HostAddress,
527 IN UINT64 Attributes
528 )
529 {
530 EFI_STATUS Status;
531 EFI_PHYSICAL_ADDRESS PhysicalAddress;
532 VOID *StashBuffer;
533 UINTN CommonBufferPages;
534 COMMON_BUFFER_HEADER *CommonBufferHeader;
535 UINT32 ReservedMemBitmap;
536
537 DEBUG ((
538 DEBUG_VERBOSE,
539 "%a: MemoryType=%u Pages=0x%Lx Attributes=0x%Lx\n",
540 __FUNCTION__,
541 (UINT32)MemoryType,
542 (UINT64)Pages,
543 Attributes
544 ));
545
546 //
547 // Validate Attributes
548 //
549 if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
550 return EFI_UNSUPPORTED;
551 }
552
553 //
554 // Check for invalid inputs
555 //
556 if (HostAddress == NULL) {
557 return EFI_INVALID_PARAMETER;
558 }
559
560 //
561 // The only valid memory types are EfiBootServicesData and
562 // EfiRuntimeServicesData
563 //
564 if ((MemoryType != EfiBootServicesData) &&
565 (MemoryType != EfiRuntimeServicesData))
566 {
567 return EFI_INVALID_PARAMETER;
568 }
569
570 //
571 // We'll need a header page for the COMMON_BUFFER_HEADER structure.
572 //
573 if (Pages > MAX_UINTN - 1) {
574 return EFI_OUT_OF_RESOURCES;
575 }
576
577 CommonBufferPages = Pages + 1;
578
579 //
580 // Allocate the stash in EfiBootServicesData type memory.
581 //
582 // Map() will temporarily save encrypted data in the stash for
583 // BusMasterCommonBuffer[64] operations, so the data can be decrypted to the
584 // original location.
585 //
586 // Unmap() will temporarily save plaintext data in the stash for
587 // BusMasterCommonBuffer[64] operations, so the data can be encrypted to the
588 // original location.
589 //
590 // StashBuffer always resides in encrypted memory.
591 //
592 StashBuffer = AllocatePages (Pages);
593 if (StashBuffer == NULL) {
594 return EFI_OUT_OF_RESOURCES;
595 }
596
597 PhysicalAddress = (UINTN)-1;
598 if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
599 //
600 // Limit allocations to memory below 4GB
601 //
602 PhysicalAddress = SIZE_4GB - 1;
603 }
604
605 Status = IoMmuAllocateCommonBuffer (
606 MemoryType,
607 CommonBufferPages,
608 &PhysicalAddress,
609 &ReservedMemBitmap
610 );
611
612 if (EFI_ERROR (Status)) {
613 goto FreeStashBuffer;
614 }
615
616 CommonBufferHeader = (VOID *)(UINTN)PhysicalAddress;
617 PhysicalAddress += EFI_PAGE_SIZE;
618
619 CommonBufferHeader->Signature = COMMON_BUFFER_SIG;
620 CommonBufferHeader->StashBuffer = StashBuffer;
621 CommonBufferHeader->ReservedMemBitmap = ReservedMemBitmap;
622
623 *HostAddress = (VOID *)(UINTN)PhysicalAddress;
624
625 DEBUG ((
626 DEBUG_VERBOSE,
627 "%a: Host=0x%Lx Stash=0x%p\n",
628 __FUNCTION__,
629 PhysicalAddress,
630 StashBuffer
631 ));
632 return EFI_SUCCESS;
633
634 FreeStashBuffer:
635 FreePages (StashBuffer, Pages);
636 return Status;
637 }
638
639 /**
640 Frees memory that was allocated with AllocateBuffer().
641
642 @param This The protocol instance pointer.
643 @param Pages The number of pages to free.
644 @param HostAddress The base system memory address of the allocated
645 range.
646
647 @retval EFI_SUCCESS The requested memory pages were freed.
648 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
649 Pages was not allocated with AllocateBuffer().
650
651 **/
652 EFI_STATUS
653 EFIAPI
654 IoMmuFreeBuffer (
655 IN EDKII_IOMMU_PROTOCOL *This,
656 IN UINTN Pages,
657 IN VOID *HostAddress
658 )
659 {
660 UINTN CommonBufferPages;
661 COMMON_BUFFER_HEADER *CommonBufferHeader;
662
663 DEBUG ((
664 DEBUG_VERBOSE,
665 "%a: Host=0x%p Pages=0x%Lx\n",
666 __FUNCTION__,
667 HostAddress,
668 (UINT64)Pages
669 ));
670
671 CommonBufferPages = Pages + 1;
672 CommonBufferHeader = (COMMON_BUFFER_HEADER *)(
673 (UINTN)HostAddress - EFI_PAGE_SIZE
674 );
675
676 //
677 // Check the signature.
678 //
679 ASSERT (CommonBufferHeader->Signature == COMMON_BUFFER_SIG);
680 if (CommonBufferHeader->Signature != COMMON_BUFFER_SIG) {
681 return EFI_INVALID_PARAMETER;
682 }
683
684 //
685 // Free the stash buffer. This buffer was always encrypted, so no need to
686 // zero it.
687 //
688 FreePages (CommonBufferHeader->StashBuffer, Pages);
689
690 //
691 // Release the common buffer itself. Unmap() has re-encrypted it in-place, so
692 // no need to zero it.
693 //
694 return IoMmuFreeCommonBuffer (CommonBufferHeader, CommonBufferPages);
695 }
696
697 /**
698 Set IOMMU attribute for a system memory.
699
700 If the IOMMU protocol exists, the system memory cannot be used
701 for DMA by default.
702
703 When a device requests a DMA access for a system memory,
704 the device driver need use SetAttribute() to update the IOMMU
705 attribute to request DMA access (read and/or write).
706
707 The DeviceHandle is used to identify which device submits the request.
708 The IOMMU implementation need translate the device path to an IOMMU device
709 ID, and set IOMMU hardware register accordingly.
710 1) DeviceHandle can be a standard PCI device.
711 The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.
712 The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.
713 The memory for BusMasterCommonBuffer need set
714 EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE.
715 After the memory is used, the memory need set 0 to keep it being
716 protected.
717 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).
718 The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or
719 EDKII_IOMMU_ACCESS_WRITE.
720
721 @param[in] This The protocol instance pointer.
722 @param[in] DeviceHandle The device who initiates the DMA access
723 request.
724 @param[in] Mapping The mapping value returned from Map().
725 @param[in] IoMmuAccess The IOMMU access.
726
727 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range
728 specified by DeviceAddress and Length.
729 @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
730 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
731 Map().
732 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination
733 of access.
734 @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
735 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported
736 by the IOMMU.
737 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range
738 specified by Mapping.
739 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
740 modify the IOMMU access.
741 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while
742 attempting the operation.
743
744 **/
745 EFI_STATUS
746 EFIAPI
747 IoMmuSetAttribute (
748 IN EDKII_IOMMU_PROTOCOL *This,
749 IN EFI_HANDLE DeviceHandle,
750 IN VOID *Mapping,
751 IN UINT64 IoMmuAccess
752 )
753 {
754 return EFI_UNSUPPORTED;
755 }
756
757 EDKII_IOMMU_PROTOCOL mIoMmu = {
758 EDKII_IOMMU_PROTOCOL_REVISION,
759 IoMmuSetAttribute,
760 IoMmuMap,
761 IoMmuUnmap,
762 IoMmuAllocateBuffer,
763 IoMmuFreeBuffer,
764 };
765
766 /**
767 Notification function that is queued when gBS->ExitBootServices() signals the
768 EFI_EVENT_GROUP_EXIT_BOOT_SERVICES event group. This function signals another
769 event, received as Context, and returns.
770
771 Signaling an event in this context is safe. The UEFI spec allows
772 gBS->SignalEvent() to return EFI_SUCCESS only; EFI_OUT_OF_RESOURCES is not
773 listed, hence memory is not allocated. The edk2 implementation also does not
774 release memory (and we only have to care about the edk2 implementation
775 because EDKII_IOMMU_PROTOCOL is edk2-specific anyway).
776
777 @param[in] Event Event whose notification function is being invoked.
778 Event is permitted to request the queueing of this
779 function at TPL_CALLBACK or TPL_NOTIFY task
780 priority level.
781
782 @param[in] EventToSignal Identifies the EFI_EVENT to signal. EventToSignal
783 is permitted to request the queueing of its
784 notification function only at TPL_CALLBACK level.
785 **/
786 STATIC
787 VOID
788 EFIAPI
789 IoMmuExitBoot (
790 IN EFI_EVENT Event,
791 IN VOID *EventToSignal
792 )
793 {
794 //
795 // (1) The NotifyFunctions of all the events in
796 // EFI_EVENT_GROUP_EXIT_BOOT_SERVICES will have been queued before
797 // IoMmuExitBoot() is entered.
798 //
799 // (2) IoMmuExitBoot() is executing minimally at TPL_CALLBACK.
800 //
801 // (3) IoMmuExitBoot() has been queued in unspecified order relative to the
802 // NotifyFunctions of all the other events in
803 // EFI_EVENT_GROUP_EXIT_BOOT_SERVICES whose NotifyTpl is the same as
804 // Event's.
805 //
806 // Consequences:
807 //
808 // - If Event's NotifyTpl is TPL_CALLBACK, then some other NotifyFunctions
809 // queued at TPL_CALLBACK may be invoked after IoMmuExitBoot() returns.
810 //
811 // - If Event's NotifyTpl is TPL_NOTIFY, then some other NotifyFunctions
812 // queued at TPL_NOTIFY may be invoked after IoMmuExitBoot() returns; plus
813 // *all* NotifyFunctions queued at TPL_CALLBACK will be invoked strictly
814 // after all NotifyFunctions queued at TPL_NOTIFY, including
815 // IoMmuExitBoot(), have been invoked.
816 //
817 // - By signaling EventToSignal here, whose NotifyTpl is TPL_CALLBACK, we
818 // queue EventToSignal's NotifyFunction after the NotifyFunctions of *all*
819 // events in EFI_EVENT_GROUP_EXIT_BOOT_SERVICES.
820 //
821 DEBUG ((DEBUG_VERBOSE, "%a\n", __FUNCTION__));
822 gBS->SignalEvent (EventToSignal);
823 }
824
825 /**
826 Notification function that is queued after the notification functions of all
827 events in the EFI_EVENT_GROUP_EXIT_BOOT_SERVICES event group. The same memory
828 map restrictions apply.
829
830 This function unmaps all currently existing IOMMU mappings.
831
832 @param[in] Event Event whose notification function is being invoked. Event
833 is permitted to request the queueing of this function
834 only at TPL_CALLBACK task priority level.
835
836 @param[in] Context Ignored.
837 **/
838 STATIC
839 VOID
840 EFIAPI
841 IoMmuUnmapAllMappings (
842 IN EFI_EVENT Event,
843 IN VOID *Context
844 )
845 {
846 LIST_ENTRY *Node;
847 LIST_ENTRY *NextNode;
848 MAP_INFO *MapInfo;
849
850 DEBUG ((DEBUG_VERBOSE, "%a\n", __FUNCTION__));
851
852 //
853 // All drivers that had set up IOMMU mappings have halted their respective
854 // controllers by now; tear down the mappings.
855 //
856 for (Node = GetFirstNode (&mMapInfos); Node != &mMapInfos; Node = NextNode) {
857 NextNode = GetNextNode (&mMapInfos, Node);
858 MapInfo = CR (Node, MAP_INFO, Link, MAP_INFO_SIG);
859 IoMmuUnmapWorker (
860 &mIoMmu, // This
861 MapInfo, // Mapping
862 TRUE // MemoryMapLocked
863 );
864 }
865
866 //
867 // Release the reserved shared memory as well.
868 //
869 IoMmuReleaseReservedSharedMem (TRUE);
870 }
871
872 /**
873 Initialize Iommu Protocol.
874
875 **/
876 EFI_STATUS
877 EFIAPI
878 InstallIoMmuProtocol (
879 VOID
880 )
881 {
882 EFI_STATUS Status;
883 EFI_EVENT UnmapAllMappingsEvent;
884 EFI_EVENT ExitBootEvent;
885 EFI_HANDLE Handle;
886
887 //
888 // Create the "late" event whose notification function will tear down all
889 // left-over IOMMU mappings.
890 //
891 Status = gBS->CreateEvent (
892 EVT_NOTIFY_SIGNAL, // Type
893 TPL_CALLBACK, // NotifyTpl
894 IoMmuUnmapAllMappings, // NotifyFunction
895 NULL, // NotifyContext
896 &UnmapAllMappingsEvent // Event
897 );
898 if (EFI_ERROR (Status)) {
899 return Status;
900 }
901
902 //
903 // Create the event whose notification function will be queued by
904 // gBS->ExitBootServices() and will signal the event created above.
905 //
906 Status = gBS->CreateEvent (
907 EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type
908 TPL_CALLBACK, // NotifyTpl
909 IoMmuExitBoot, // NotifyFunction
910 UnmapAllMappingsEvent, // NotifyContext
911 &ExitBootEvent // Event
912 );
913 if (EFI_ERROR (Status)) {
914 goto CloseUnmapAllMappingsEvent;
915 }
916
917 Handle = NULL;
918 Status = gBS->InstallMultipleProtocolInterfaces (
919 &Handle,
920 &gEdkiiIoMmuProtocolGuid,
921 &mIoMmu,
922 NULL
923 );
924 if (EFI_ERROR (Status)) {
925 goto CloseExitBootEvent;
926 }
927
928 //
929 // For CC guests, use reserved shared memory for DMA operation.
930 //
931 mReservedSharedMemSupported = TRUE;
932 Status = IoMmuInitReservedSharedMem ();
933 if (EFI_ERROR (Status)) {
934 mReservedSharedMemSupported = FALSE;
935 } else {
936 DEBUG ((DEBUG_INFO, "%a: Feature of reserved memory for DMA is supported.\n", __FUNCTION__));
937 }
938
939 return EFI_SUCCESS;
940
941 CloseExitBootEvent:
942 gBS->CloseEvent (ExitBootEvent);
943
944 CloseUnmapAllMappingsEvent:
945 gBS->CloseEvent (UnmapAllMappingsEvent);
946
947 return Status;
948 }