OvmfPkg/IoMmuDxe: Add SEV support for reserved shared memory

Add support to use the reserved shared memory within the IoMmu library.
This improves boot times for all SEV guests, with SEV-SNP benefiting the
most as it avoids the page state change call to the hypervisor.

Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
This commit is contained in:
Tom Lendacky 2022-12-15 13:18:09 +08:00 committed by mergify[bot]
parent 09f01d4efb
commit 47b9521513
2 changed files with 83 additions and 53 deletions

View File

@ -223,30 +223,32 @@ IoMmuMap (
goto FreeMapInfo; goto FreeMapInfo;
} }
if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) { if (MapInfo->ReservedMemBitmap == 0) {
// //
// Clear the memory encryption mask on the plaintext buffer.
//
Status = MemEncryptSevClearPageEncMask (
0,
MapInfo->PlainTextAddress,
MapInfo->NumberOfPages
);
} else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
//
// Set the memory shared bit.
// If MapInfo->ReservedMemBitmap is 0, it means the bounce buffer is not allocated // If MapInfo->ReservedMemBitmap is 0, it means the bounce buffer is not allocated
// from the pre-allocated shared memory, so it must be converted to shared memory here. // from the pre-allocated shared memory, so it must be converted to shared memory here.
// //
if (MapInfo->ReservedMemBitmap == 0) { if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
//
// Clear the memory encryption mask on the plaintext buffer.
//
Status = MemEncryptSevClearPageEncMask (
0,
MapInfo->PlainTextAddress,
MapInfo->NumberOfPages
);
} else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
//
// Set the memory shared bit.
//
Status = MemEncryptTdxSetPageSharedBit ( Status = MemEncryptTdxSetPageSharedBit (
0, 0,
MapInfo->PlainTextAddress, MapInfo->PlainTextAddress,
MapInfo->NumberOfPages MapInfo->NumberOfPages
); );
} else {
ASSERT (FALSE);
} }
} else {
ASSERT (FALSE);
} }
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
@ -396,30 +398,30 @@ IoMmuUnmapWorker (
break; break;
} }
if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) { if (MapInfo->ReservedMemBitmap == 0) {
// if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
// Restore the memory encryption mask on the area we used to hold the //
// plaintext. // Restore the memory encryption mask on the area we used to hold the
// // plaintext.
Status = MemEncryptSevSetPageEncMask ( //
0, Status = MemEncryptSevSetPageEncMask (
MapInfo->PlainTextAddress, 0,
MapInfo->NumberOfPages MapInfo->PlainTextAddress,
); MapInfo->NumberOfPages
} else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) { );
// } else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
// Restore the memory shared bit mask on the area we used to hold the //
// plaintext. // Restore the memory shared bit mask on the area we used to hold the
// // plaintext.
if (MapInfo->ReservedMemBitmap == 0) { //
Status = MemEncryptTdxClearPageSharedBit ( Status = MemEncryptTdxClearPageSharedBit (
0, 0,
MapInfo->PlainTextAddress, MapInfo->PlainTextAddress,
MapInfo->NumberOfPages MapInfo->NumberOfPages
); );
} else {
ASSERT (FALSE);
} }
} else {
ASSERT (FALSE);
} }
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
@ -924,16 +926,14 @@ InstallIoMmuProtocol (
} }
// //
// Currently only Tdx guest support Reserved shared memory for DMA operation. // For CC guests, use reserved shared memory for DMA operation.
// //
if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) { mReservedSharedMemSupported = TRUE;
mReservedSharedMemSupported = TRUE; Status = IoMmuInitReservedSharedMem ();
Status = IoMmuInitReservedSharedMem (); if (EFI_ERROR (Status)) {
if (EFI_ERROR (Status)) { mReservedSharedMemSupported = FALSE;
mReservedSharedMemSupported = FALSE; } else {
} else { DEBUG ((DEBUG_INFO, "%a: Feature of reserved memory for DMA is supported.\n", __FUNCTION__));
DEBUG ((DEBUG_INFO, "%a: Feature of reserved memory for DMA is supported.\n", __FUNCTION__));
}
} }
return EFI_SUCCESS; return EFI_SUCCESS;

View File

@ -9,7 +9,9 @@
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h> #include <Library/MemoryAllocationLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/MemEncryptTdxLib.h> #include <Library/MemEncryptTdxLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
#include "IoMmuInternal.h" #include "IoMmuInternal.h"
@ -139,6 +141,7 @@ IoMmuInitReservedSharedMem (
UINTN TotalPages; UINTN TotalPages;
IOMMU_RESERVED_MEM_RANGE *MemRange; IOMMU_RESERVED_MEM_RANGE *MemRange;
EFI_PHYSICAL_ADDRESS PhysicalAddress; EFI_PHYSICAL_ADDRESS PhysicalAddress;
UINT64 SharedAddress;
if (!mReservedSharedMemSupported) { if (!mReservedSharedMemSupported) {
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
@ -163,12 +166,25 @@ IoMmuInitReservedSharedMem (
MemRange->StartAddressOfMemRange = PhysicalAddress; MemRange->StartAddressOfMemRange = PhysicalAddress;
for (Index2 = 0; Index2 < MemRange->Slots; Index2++) { for (Index2 = 0; Index2 < MemRange->Slots; Index2++) {
Status = MemEncryptTdxSetPageSharedBit ( SharedAddress = (UINT64)(UINTN)(MemRange->StartAddressOfMemRange + Index2 * SIZE_OF_MEM_RANGE (MemRange) + MemRange->HeaderSize);
0,
(UINT64)(UINTN)(MemRange->StartAddressOfMemRange + Index2 * SIZE_OF_MEM_RANGE (MemRange) + MemRange->HeaderSize), if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
EFI_SIZE_TO_PAGES (MemRange->DataSize) Status = MemEncryptSevClearPageEncMask (
); 0,
ASSERT (!EFI_ERROR (Status)); SharedAddress,
EFI_SIZE_TO_PAGES (MemRange->DataSize)
);
ASSERT (!EFI_ERROR (Status));
} else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
Status = MemEncryptTdxSetPageSharedBit (
0,
SharedAddress,
EFI_SIZE_TO_PAGES (MemRange->DataSize)
);
ASSERT (!EFI_ERROR (Status));
} else {
ASSERT (FALSE);
}
} }
PhysicalAddress += (MemRange->Slots * SIZE_OF_MEM_RANGE (MemRange)); PhysicalAddress += (MemRange->Slots * SIZE_OF_MEM_RANGE (MemRange));
@ -190,6 +206,7 @@ IoMmuReleaseReservedSharedMem (
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Index1, Index2; UINT32 Index1, Index2;
IOMMU_RESERVED_MEM_RANGE *MemRange; IOMMU_RESERVED_MEM_RANGE *MemRange;
UINT64 SharedAddress;
if (!mReservedSharedMemSupported) { if (!mReservedSharedMemSupported) {
return EFI_SUCCESS; return EFI_SUCCESS;
@ -198,12 +215,25 @@ IoMmuReleaseReservedSharedMem (
for (Index1 = 0; Index1 < ARRAY_SIZE (mReservedMemRanges); Index1++) { for (Index1 = 0; Index1 < ARRAY_SIZE (mReservedMemRanges); Index1++) {
MemRange = &mReservedMemRanges[Index1]; MemRange = &mReservedMemRanges[Index1];
for (Index2 = 0; Index2 < MemRange->Slots; Index2++) { for (Index2 = 0; Index2 < MemRange->Slots; Index2++) {
Status = MemEncryptTdxClearPageSharedBit ( SharedAddress = (UINT64)(UINTN)(MemRange->StartAddressOfMemRange + Index2 * SIZE_OF_MEM_RANGE (MemRange) + MemRange->HeaderSize);
0,
(UINT64)(UINTN)(MemRange->StartAddressOfMemRange + Index2 * SIZE_OF_MEM_RANGE (MemRange) + MemRange->HeaderSize), if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
EFI_SIZE_TO_PAGES (MemRange->DataSize) Status = MemEncryptSevSetPageEncMask (
); 0,
ASSERT (!EFI_ERROR (Status)); SharedAddress,
EFI_SIZE_TO_PAGES (MemRange->DataSize)
);
ASSERT (!EFI_ERROR (Status));
} else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
Status = MemEncryptTdxClearPageSharedBit (
0,
SharedAddress,
EFI_SIZE_TO_PAGES (MemRange->DataSize)
);
ASSERT (!EFI_ERROR (Status));
} else {
ASSERT (FALSE);
}
} }
} }