OvmfPkg: Update IoMmuDxe to support TDX

RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429

The IOMMU protocol driver provides capabilities to set a DMA access
attribute and methods to allocate, free, map and unmap the DMA memory
for the PCI Bus devices.

The current IoMmuDxe driver supports DMA operations inside SEV guest.
To support DMA operation in TDX guest,
CC_GUEST_IS_XXX (PcdConfidentialComputingGuestAttr) is used to determine
if it is SEV guest or TDX guest.

Due to security reasons all DMA operations inside the SEV/TDX guest must
be performed on shared pages. The IOMMU protocol driver for the SEV/TDX
guest uses a bounce buffer to map guest DMA buffer to shared pages in
order to provide the support for DMA operations inside SEV/TDX guest.

The call of SEV or TDX specific function to set/clear EncMask/SharedBit
is determined by CC_GUEST_IS_XXX (PcdConfidentialComputingGuestAttr).

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
This commit is contained in:
Min Xu 2021-09-22 20:49:05 +08:00 committed by mergify[bot]
parent 07c721fea7
commit 2520182122
10 changed files with 85 additions and 42 deletions

View File

@ -174,6 +174,7 @@
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
BlobVerifierLib|OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf BlobVerifierLib|OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
!if $(SOURCE_DEBUG_ENABLE) == TRUE !if $(SOURCE_DEBUG_ENABLE) == TRUE
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf

View File

@ -169,6 +169,7 @@
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf

View File

@ -184,6 +184,7 @@
!endif !endif
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
!if $(SOURCE_DEBUG_ENABLE) == TRUE !if $(SOURCE_DEBUG_ENABLE) == TRUE
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf

View File

@ -1,9 +1,9 @@
/** @file /** @file
The protocol provides support to allocate, free, map and umap a DMA buffer The protocol provides support to allocate, free, map and umap a DMA buffer
for bus master (e.g PciHostBridge). When SEV is enabled, the DMA operations for bus master (e.g PciHostBridge). When SEV or TDX is enabled, the DMA
must be performed on unencrypted buffer hence we use a bounce buffer to map operations must be performed on unencrypted buffer hence we use a bounce
the guest buffer into an unencrypted DMA buffer. buffer to map the guest buffer into an unencrypted DMA buffer.
Copyright (c) 2017, AMD Inc. All rights reserved.<BR> Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
@ -12,6 +12,8 @@
**/ **/
#include <Library/PcdLib.h>
#include <ConfidentialComputingGuestAttr.h>
#include "AmdSevIoMmu.h" #include "AmdSevIoMmu.h"
#define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O') #define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O')
@ -74,7 +76,7 @@ typedef struct {
/** /**
Provides the controller-specific addresses required to access system memory Provides the controller-specific addresses required to access system memory
from a DMA bus master. On SEV guest, the DMA operations must be performed on from a DMA bus master. On SEV/TDX guest, the DMA operations must be performed on
shared buffer hence we allocate a bounce buffer to map the HostAddress to a shared buffer hence we allocate a bounce buffer to map the HostAddress to a
DeviceAddress. The Encryption attribute is removed from the DeviceAddress DeviceAddress. The Encryption attribute is removed from the DeviceAddress
buffer. buffer.
@ -250,6 +252,7 @@ IoMmuMap (
goto FreeMapInfo; goto FreeMapInfo;
} }
if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
// //
// Clear the memory encryption mask on the plaintext buffer. // Clear the memory encryption mask on the plaintext buffer.
// //
@ -258,6 +261,19 @@ IoMmuMap (
MapInfo->PlainTextAddress, MapInfo->PlainTextAddress,
MapInfo->NumberOfPages MapInfo->NumberOfPages
); );
} else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
//
// Set the memory shared bit.
//
Status = MemEncryptTdxSetPageSharedBit (
0,
MapInfo->PlainTextAddress,
MapInfo->NumberOfPages
);
} else {
ASSERT (FALSE);
}
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
CpuDeadLoop (); CpuDeadLoop ();
@ -358,7 +374,7 @@ IoMmuUnmapWorker (
} }
MapInfo = (MAP_INFO *)Mapping; MapInfo = (MAP_INFO *)Mapping;
Status = EFI_SUCCESS;
// //
// set CommonBufferHeader to suppress incorrect compiler/analyzer warnings // set CommonBufferHeader to suppress incorrect compiler/analyzer warnings
// //
@ -404,6 +420,7 @@ IoMmuUnmapWorker (
break; break;
} }
if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
// //
// Restore the memory encryption mask on the area we used to hold the // Restore the memory encryption mask on the area we used to hold the
// plaintext. // plaintext.
@ -413,6 +430,20 @@ IoMmuUnmapWorker (
MapInfo->PlainTextAddress, MapInfo->PlainTextAddress,
MapInfo->NumberOfPages MapInfo->NumberOfPages
); );
} else if (CC_GUEST_IS_TDX (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
//
// Restore the memory shared bit mask on the area we used to hold the
// plaintext.
//
Status = MemEncryptTdxClearPageSharedBit (
0,
MapInfo->PlainTextAddress,
MapInfo->NumberOfPages
);
} else {
ASSERT (FALSE);
}
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
CpuDeadLoop (); CpuDeadLoop ();
@ -739,7 +770,7 @@ IoMmuSetAttribute (
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
EDKII_IOMMU_PROTOCOL mAmdSev = { EDKII_IOMMU_PROTOCOL mIoMmu = {
EDKII_IOMMU_PROTOCOL_REVISION, EDKII_IOMMU_PROTOCOL_REVISION,
IoMmuSetAttribute, IoMmuSetAttribute,
IoMmuMap, IoMmuMap,
@ -771,7 +802,7 @@ EDKII_IOMMU_PROTOCOL mAmdSev = {
STATIC STATIC
VOID VOID
EFIAPI EFIAPI
AmdSevExitBoot ( IoMmuExitBoot (
IN EFI_EVENT Event, IN EFI_EVENT Event,
IN VOID *EventToSignal IN VOID *EventToSignal
) )
@ -779,11 +810,11 @@ AmdSevExitBoot (
// //
// (1) The NotifyFunctions of all the events in // (1) The NotifyFunctions of all the events in
// EFI_EVENT_GROUP_EXIT_BOOT_SERVICES will have been queued before // EFI_EVENT_GROUP_EXIT_BOOT_SERVICES will have been queued before
// AmdSevExitBoot() is entered. // IoMmuExitBoot() is entered.
// //
// (2) AmdSevExitBoot() is executing minimally at TPL_CALLBACK. // (2) IoMmuExitBoot() is executing minimally at TPL_CALLBACK.
// //
// (3) AmdSevExitBoot() has been queued in unspecified order relative to the // (3) IoMmuExitBoot() has been queued in unspecified order relative to the
// NotifyFunctions of all the other events in // NotifyFunctions of all the other events in
// EFI_EVENT_GROUP_EXIT_BOOT_SERVICES whose NotifyTpl is the same as // EFI_EVENT_GROUP_EXIT_BOOT_SERVICES whose NotifyTpl is the same as
// Event's. // Event's.
@ -791,13 +822,13 @@ AmdSevExitBoot (
// Consequences: // Consequences:
// //
// - If Event's NotifyTpl is TPL_CALLBACK, then some other NotifyFunctions // - If Event's NotifyTpl is TPL_CALLBACK, then some other NotifyFunctions
// queued at TPL_CALLBACK may be invoked after AmdSevExitBoot() returns. // queued at TPL_CALLBACK may be invoked after IoMmuExitBoot() returns.
// //
// - If Event's NotifyTpl is TPL_NOTIFY, then some other NotifyFunctions // - If Event's NotifyTpl is TPL_NOTIFY, then some other NotifyFunctions
// queued at TPL_NOTIFY may be invoked after AmdSevExitBoot() returns; plus // queued at TPL_NOTIFY may be invoked after IoMmuExitBoot() returns; plus
// *all* NotifyFunctions queued at TPL_CALLBACK will be invoked strictly // *all* NotifyFunctions queued at TPL_CALLBACK will be invoked strictly
// after all NotifyFunctions queued at TPL_NOTIFY, including // after all NotifyFunctions queued at TPL_NOTIFY, including
// AmdSevExitBoot(), have been invoked. // IoMmuExitBoot(), have been invoked.
// //
// - By signaling EventToSignal here, whose NotifyTpl is TPL_CALLBACK, we // - By signaling EventToSignal here, whose NotifyTpl is TPL_CALLBACK, we
// queue EventToSignal's NotifyFunction after the NotifyFunctions of *all* // queue EventToSignal's NotifyFunction after the NotifyFunctions of *all*
@ -823,7 +854,7 @@ AmdSevExitBoot (
STATIC STATIC
VOID VOID
EFIAPI EFIAPI
AmdSevUnmapAllMappings ( IoMmuUnmapAllMappings (
IN EFI_EVENT Event, IN EFI_EVENT Event,
IN VOID *Context IN VOID *Context
) )
@ -842,7 +873,7 @@ AmdSevUnmapAllMappings (
NextNode = GetNextNode (&mMapInfos, Node); NextNode = GetNextNode (&mMapInfos, Node);
MapInfo = CR (Node, MAP_INFO, Link, MAP_INFO_SIG); MapInfo = CR (Node, MAP_INFO, Link, MAP_INFO_SIG);
IoMmuUnmapWorker ( IoMmuUnmapWorker (
&mAmdSev, // This &mIoMmu, // This
MapInfo, // Mapping MapInfo, // Mapping
TRUE // MemoryMapLocked TRUE // MemoryMapLocked
); );
@ -855,7 +886,7 @@ AmdSevUnmapAllMappings (
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
AmdSevInstallIoMmuProtocol ( InstallIoMmuProtocol (
VOID VOID
) )
{ {
@ -871,7 +902,7 @@ AmdSevInstallIoMmuProtocol (
Status = gBS->CreateEvent ( Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL, // Type EVT_NOTIFY_SIGNAL, // Type
TPL_CALLBACK, // NotifyTpl TPL_CALLBACK, // NotifyTpl
AmdSevUnmapAllMappings, // NotifyFunction IoMmuUnmapAllMappings, // NotifyFunction
NULL, // NotifyContext NULL, // NotifyContext
&UnmapAllMappingsEvent // Event &UnmapAllMappingsEvent // Event
); );
@ -886,7 +917,7 @@ AmdSevInstallIoMmuProtocol (
Status = gBS->CreateEvent ( Status = gBS->CreateEvent (
EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type
TPL_CALLBACK, // NotifyTpl TPL_CALLBACK, // NotifyTpl
AmdSevExitBoot, // NotifyFunction IoMmuExitBoot, // NotifyFunction
UnmapAllMappingsEvent, // NotifyContext UnmapAllMappingsEvent, // NotifyContext
&ExitBootEvent // Event &ExitBootEvent // Event
); );
@ -898,7 +929,7 @@ AmdSevInstallIoMmuProtocol (
Status = gBS->InstallMultipleProtocolInterfaces ( Status = gBS->InstallMultipleProtocolInterfaces (
&Handle, &Handle,
&gEdkiiIoMmuProtocolGuid, &gEdkiiIoMmuProtocolGuid,
&mAmdSev, &mIoMmu,
NULL NULL
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {

View File

@ -21,17 +21,17 @@
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/MemEncryptSevLib.h> #include <Library/MemEncryptSevLib.h>
#include <Library/MemEncryptTdxLib.h>
#include <Library/MemoryAllocationLib.h> #include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
/** /**
Install IOMMU protocol to provide the DMA support for PciHostBridge and Install IOMMU protocol to provide the DMA support for PciHostBridge.
MemEncryptSevLib.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
AmdSevInstallIoMmuProtocol ( InstallIoMmuProtocol (
VOID VOID
); );

View File

@ -22,11 +22,11 @@ IoMmuDxeEntryPoint (
EFI_HANDLE Handle; EFI_HANDLE Handle;
// //
// When SEV is enabled, install IoMmu protocol otherwise install the // When SEV or TDX is enabled, install IoMmu protocol otherwise install the
// placeholder protocol so that other dependent module can run. // placeholder protocol so that other dependent module can run.
// //
if (MemEncryptSevIsEnabled ()) { if (MemEncryptSevIsEnabled () || MemEncryptTdxIsEnabled ()) {
Status = AmdSevInstallIoMmuProtocol (); Status = InstallIoMmuProtocol ();
} else { } else {
Handle = NULL; Handle = NULL;

View File

@ -26,16 +26,21 @@
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec MdeModulePkg/MdeModulePkg.dec
OvmfPkg/OvmfPkg.dec OvmfPkg/OvmfPkg.dec
# UefiCpuPkg/UefiCpuPkg.dec
[LibraryClasses] [LibraryClasses]
BaseLib BaseLib
BaseMemoryLib BaseMemoryLib
DebugLib DebugLib
MemEncryptSevLib MemEncryptSevLib
MemEncryptTdxLib
MemoryAllocationLib MemoryAllocationLib
UefiBootServicesTableLib UefiBootServicesTableLib
UefiDriverEntryPoint UefiDriverEntryPoint
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr
[Protocols] [Protocols]
gEdkiiIoMmuProtocolGuid ## SOMETIME_PRODUCES gEdkiiIoMmuProtocolGuid ## SOMETIME_PRODUCES
gIoMmuAbsentProtocolGuid ## SOMETIME_PRODUCES gIoMmuAbsentProtocolGuid ## SOMETIME_PRODUCES

View File

@ -181,6 +181,7 @@
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
!if $(SOURCE_DEBUG_ENABLE) == TRUE !if $(SOURCE_DEBUG_ENABLE) == TRUE
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf

View File

@ -187,6 +187,8 @@
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
!if $(SMM_REQUIRE) == FALSE !if $(SMM_REQUIRE) == FALSE
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
!endif !endif

View File

@ -170,6 +170,7 @@
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
!if $(SOURCE_DEBUG_ENABLE) == TRUE !if $(SOURCE_DEBUG_ENABLE) == TRUE
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf