From: Brijesh Singh <brijesh.si...@amd.com> When SEV is enabled, the DMA operations must be performed on a shared (i.e unencrypted) pages. The patch adds SEV specific hooks to use the bounce buffer when caller map/unmap host address to a DMA address and similarly clears/set memory encryption attribute when caller allocates or free the DMA pages.
Signed-off-by: Brijesh Singh <brijesh.si...@amd.com> --- OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.inf | 3 +- OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.c | 60 +++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.inf b/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.inf index 4ddb27d578bc..fb97caa79827 100644 --- a/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.inf +++ b/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.inf @@ -29,6 +29,7 @@ [Sources.common] [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec [LibraryClasses] BaseLib @@ -37,5 +38,5 @@ [LibraryClasses] DxeServicesTableLib MemoryAllocationLib UefiBootServicesTableLib - + MemEncryptSevLib diff --git a/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.c b/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.c index 4a6a704f9aa5..7a79c7091004 100644 --- a/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.c +++ b/OvmfPkg/Library/DxeBmDmaLib/DxeBmDmaLib.c @@ -25,6 +25,7 @@ #include <Library/MemoryAllocationLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/BmDmaLib.h> +#include <Library/MemEncryptSevLib.h> #define FORCE_BELOW_4GB_TRUE TRUE @@ -100,6 +101,15 @@ AllocateBounceBuffer ( } // + // Clear C-bit on DMA pages + // + if (MemEncryptSevIsEnabled ()) { + Status = MemEncryptSevClearPageEncMask (MapInfo->MappedHostAddress, MapInfo->NumberOfPages, TRUE); + if (Status != EFI_SUCCESS) { + return Status; + } + } + // // If this is a read operation from the Bus Master's point of view, // then copy the contents of the real buffer into the mapped buffer // so the Bus Master can read the contents of the real buffer. @@ -170,6 +180,23 @@ BmDmaMap ( PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; if (DmaAbove4GB || (PhysicalAddress + *NumberOfBytes) <= SIZE_4GB) { + + // + // When SEV is enabled the DMA operation must be performed on shared pages. We force to use the + // bounce buffer path which will take care of allocating shared Dma buffers mapping + // + if (MemEncryptSevIsEnabled () && + (Operation == DmaOperationBusMasterRead || Operation == DmaOperationBusMasterWrite)) { + return AllocateBounceBuffer ( + FORCE_BELOW_4GB_FALSE, + Operation, + PhysicalAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + } + // // If we CAN handle DMA above 4GB or the transfer is below 4GB, // the DeviceAddress is simply the HostAddress @@ -218,7 +245,8 @@ BmDmaUnmap ( IN VOID *Mapping ) { - MAP_INFO *MapInfo; + MAP_INFO *MapInfo; + EFI_STATUS Status; // // Check for invalid inputs @@ -251,6 +279,17 @@ BmDmaUnmap ( } // + // When SEV is enabled then Dma buffer allocate by bounce buffer have C-bit cleared, + // restore the C-bit before we release the resources + // + if (MemEncryptSevIsEnabled ()) { + Status = MemEncryptSevSetPageEncMask (MapInfo->MappedHostAddress, MapInfo->NumberOfPages, TRUE); + if (Status != EFI_SUCCESS) { + return Status; + } + } + + // // Free the mapped buffer and the MAP_INFO structure. // gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages); @@ -322,8 +361,15 @@ BmDmaAllocateBuffer ( ); if (!EFI_ERROR (Status)) { *HostAddress = (VOID *) (UINTN) PhysicalAddress; + // + // Clear C-bit on Dma pages + // + if (MemEncryptSevIsEnabled ()) { + Status = MemEncryptSevClearPageEncMask (PhysicalAddress, Pages, TRUE); + } } + return Status; } @@ -346,6 +392,18 @@ BmDmaFreeBuffer ( IN UINTN Pages ) { + EFI_STATUS Status; + + // + // Restore the C-bit on DMA pages + // + if (MemEncryptSevIsEnabled ()) { + Status = MemEncryptSevSetPageEncMask ((UINTN) HostAddress, Pages, TRUE); + if (Status != EFI_SUCCESS) { + return Status; + } + } + return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages); } -- 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel