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