From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by mx.groups.io with SMTP id smtpd.web08.9100.1645271933337984887 for ; Sat, 19 Feb 2022 03:59:02 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=d/TqLHwF; spf=pass (domain: intel.com, ip: 192.55.52.151, mailfrom: min.m.xu@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645271942; x=1676807942; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=K/Jx3QONH5xiFTgwa9e1FQr7Tf/82hRiASCCehpn9nU=; b=d/TqLHwFt/GNyJbei9hKtqq+Vm3yRKsT1UKrxIyDyUqfsTalBMv2e9ix YWNEk5efU1ldtpuSylSoYPFKkZ+lrepTC5KkDYGvcV87pXA6ip9Kum+D7 BKgkfUNYQQel4Ad5Z++vqr2UzmQJ95zMP7+XVUMmNisjHhw73iKRQf9aj i6TnisWAip5edK0LT24C3WVzpsff7xL84SD5cX4otW8xVE1YYLgdEP8Hu vHTQRWRJdQ+jVy+Tmdy/PP9J8nzSNXrT70dYD7d0/iHejs5oBiJrgRlIg lywcm1aodmU9+YoWInLZD4e0AE9/wmI+SxOLNe3W1BPngP8FsWVa+o7Oq g==; X-IronPort-AV: E=McAfee;i="6200,9189,10262"; a="231915654" X-IronPort-AV: E=Sophos;i="5.88,381,1635231600"; d="scan'208";a="231915654" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Feb 2022 03:59:02 -0800 X-IronPort-AV: E=Sophos;i="5.88,381,1635231600"; d="scan'208";a="546691532" Received: from mxu9-mobl1.ccr.corp.intel.com ([10.249.175.253]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Feb 2022 03:59:00 -0800 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky , Gerd Hoffmann Subject: [PATCH V6 39/42] OvmfPkg: Update IoMmuDxe to support TDX Date: Sat, 19 Feb 2022 19:56:52 +0800 Message-Id: <4c4e475ad6ddea701c87419de12782b97bd1f453.1645261991.git.min.m.xu@intel.com> X-Mailer: git-send-email 2.29.2.windows.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Gerd Hoffmann Acked-by: Gerd Hoffmann Signed-off-by: Min Xu --- OvmfPkg/AmdSev/AmdSevX64.dsc | 1 + OvmfPkg/Bhyve/BhyveX64.dsc | 1 + OvmfPkg/CloudHv/CloudHvX64.dsc | 1 + OvmfPkg/IoMmuDxe/AmdSevIoMmu.c | 103 +++++++++++++++++++++------------ OvmfPkg/IoMmuDxe/AmdSevIoMmu.h | 6 +- OvmfPkg/IoMmuDxe/IoMmuDxe.c | 6 +- OvmfPkg/IoMmuDxe/IoMmuDxe.inf | 5 ++ OvmfPkg/Microvm/MicrovmX64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 2 + OvmfPkg/OvmfXen.dsc | 1 + 10 files changed, 85 insertions(+), 42 deletions(-) diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index a3776c1e6269..1136d6cfd7e6 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -174,6 +174,7 @@ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf BlobVerifierLib|OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf !if $(SOURCE_DEBUG_ENABLE) == TRUE PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc index e565234fa116..bdac013b6eab 100644 --- a/OvmfPkg/Bhyve/BhyveX64.dsc +++ b/OvmfPkg/Bhyve/BhyveX64.dsc @@ -169,6 +169,7 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf diff --git a/OvmfPkg/CloudHv/CloudHvX64.dsc b/OvmfPkg/CloudHv/CloudHvX64.dsc index f43f18b7087a..968c103ce830 100644 --- a/OvmfPkg/CloudHv/CloudHvX64.dsc +++ b/OvmfPkg/CloudHv/CloudHvX64.dsc @@ -184,6 +184,7 @@ !endif CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf !if $(SOURCE_DEBUG_ENABLE) == TRUE PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c index 16b5b4eac8bc..6b65897f032a 100644 --- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c +++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c @@ -1,9 +1,9 @@ /** @file 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 - must be performed on unencrypted buffer hence we use a bounce buffer to map - the guest buffer into an unencrypted DMA buffer. + for bus master (e.g PciHostBridge). When SEV or TDX is enabled, the DMA + operations must be performed on unencrypted buffer hence we use a bounce + buffer to map the guest buffer into an unencrypted DMA buffer. Copyright (c) 2017, AMD Inc. All rights reserved.
Copyright (c) 2017, Intel Corporation. All rights reserved.
@@ -12,6 +12,8 @@ **/ +#include +#include #include "AmdSevIoMmu.h" #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 - 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 DeviceAddress. The Encryption attribute is removed from the DeviceAddress buffer. @@ -250,14 +252,28 @@ IoMmuMap ( goto FreeMapInfo; } - // - // Clear the memory encryption mask on the plaintext buffer. - // - Status = MemEncryptSevClearPageEncMask ( - 0, - MapInfo->PlainTextAddress, - MapInfo->NumberOfPages - ); + 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 ( + 0, + MapInfo->PlainTextAddress, + MapInfo->NumberOfPages + ); + } else { + ASSERT (FALSE); + } + ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { CpuDeadLoop (); @@ -358,7 +374,7 @@ IoMmuUnmapWorker ( } MapInfo = (MAP_INFO *)Mapping; - + Status = EFI_SUCCESS; // // set CommonBufferHeader to suppress incorrect compiler/analyzer warnings // @@ -404,15 +420,30 @@ IoMmuUnmapWorker ( break; } - // - // Restore the memory encryption mask on the area we used to hold the - // plaintext. - // - Status = MemEncryptSevSetPageEncMask ( - 0, - MapInfo->PlainTextAddress, - MapInfo->NumberOfPages - ); + if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) { + // + // Restore the memory encryption mask on the area we used to hold the + // plaintext. + // + Status = MemEncryptSevSetPageEncMask ( + 0, + MapInfo->PlainTextAddress, + 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); if (EFI_ERROR (Status)) { CpuDeadLoop (); @@ -739,7 +770,7 @@ IoMmuSetAttribute ( return EFI_UNSUPPORTED; } -EDKII_IOMMU_PROTOCOL mAmdSev = { +EDKII_IOMMU_PROTOCOL mIoMmu = { EDKII_IOMMU_PROTOCOL_REVISION, IoMmuSetAttribute, IoMmuMap, @@ -771,7 +802,7 @@ EDKII_IOMMU_PROTOCOL mAmdSev = { STATIC VOID EFIAPI -AmdSevExitBoot ( +IoMmuExitBoot ( IN EFI_EVENT Event, IN VOID *EventToSignal ) @@ -779,11 +810,11 @@ AmdSevExitBoot ( // // (1) The NotifyFunctions of all the events in // 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 // EFI_EVENT_GROUP_EXIT_BOOT_SERVICES whose NotifyTpl is the same as // Event's. @@ -791,13 +822,13 @@ AmdSevExitBoot ( // Consequences: // // - 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 - // 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 // 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 // queue EventToSignal's NotifyFunction after the NotifyFunctions of *all* @@ -823,7 +854,7 @@ AmdSevExitBoot ( STATIC VOID EFIAPI -AmdSevUnmapAllMappings ( +IoMmuUnmapAllMappings ( IN EFI_EVENT Event, IN VOID *Context ) @@ -842,7 +873,7 @@ AmdSevUnmapAllMappings ( NextNode = GetNextNode (&mMapInfos, Node); MapInfo = CR (Node, MAP_INFO, Link, MAP_INFO_SIG); IoMmuUnmapWorker ( - &mAmdSev, // This + &mIoMmu, // This MapInfo, // Mapping TRUE // MemoryMapLocked ); @@ -855,7 +886,7 @@ AmdSevUnmapAllMappings ( **/ EFI_STATUS EFIAPI -AmdSevInstallIoMmuProtocol ( +InstallIoMmuProtocol ( VOID ) { @@ -871,7 +902,7 @@ AmdSevInstallIoMmuProtocol ( Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, // Type TPL_CALLBACK, // NotifyTpl - AmdSevUnmapAllMappings, // NotifyFunction + IoMmuUnmapAllMappings, // NotifyFunction NULL, // NotifyContext &UnmapAllMappingsEvent // Event ); @@ -886,7 +917,7 @@ AmdSevInstallIoMmuProtocol ( Status = gBS->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type TPL_CALLBACK, // NotifyTpl - AmdSevExitBoot, // NotifyFunction + IoMmuExitBoot, // NotifyFunction UnmapAllMappingsEvent, // NotifyContext &ExitBootEvent // Event ); @@ -898,7 +929,7 @@ AmdSevInstallIoMmuProtocol ( Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gEdkiiIoMmuProtocolGuid, - &mAmdSev, + &mIoMmu, NULL ); if (EFI_ERROR (Status)) { diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h index 8244f28b57fd..8fdfa9968593 100644 --- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h +++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h @@ -21,17 +21,17 @@ #include #include #include +#include #include #include /** - Install IOMMU protocol to provide the DMA support for PciHostBridge and - MemEncryptSevLib. + Install IOMMU protocol to provide the DMA support for PciHostBridge. **/ EFI_STATUS EFIAPI -AmdSevInstallIoMmuProtocol ( +InstallIoMmuProtocol ( VOID ); diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.c b/OvmfPkg/IoMmuDxe/IoMmuDxe.c index bca8c14c4076..86777dd05c26 100644 --- a/OvmfPkg/IoMmuDxe/IoMmuDxe.c +++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.c @@ -22,11 +22,11 @@ IoMmuDxeEntryPoint ( 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. // - if (MemEncryptSevIsEnabled ()) { - Status = AmdSevInstallIoMmuProtocol (); + if (MemEncryptSevIsEnabled () || MemEncryptTdxIsEnabled ()) { + Status = InstallIoMmuProtocol (); } else { Handle = NULL; diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf index 2ebd74e5558c..e10be1dcff49 100644 --- a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf +++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf @@ -26,16 +26,21 @@ MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec OvmfPkg/OvmfPkg.dec +# UefiCpuPkg/UefiCpuPkg.dec [LibraryClasses] BaseLib BaseMemoryLib DebugLib MemEncryptSevLib + MemEncryptTdxLib MemoryAllocationLib UefiBootServicesTableLib UefiDriverEntryPoint +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr + [Protocols] gEdkiiIoMmuProtocolGuid ## SOMETIME_PRODUCES gIoMmuAbsentProtocolGuid ## SOMETIME_PRODUCES diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc index ca6bd5f106e2..d406244fcfe1 100644 --- a/OvmfPkg/Microvm/MicrovmX64.dsc +++ b/OvmfPkg/Microvm/MicrovmX64.dsc @@ -181,6 +181,7 @@ LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf !if $(SOURCE_DEBUG_ENABLE) == TRUE PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 767c324e5eec..ff792c8abca8 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -180,6 +180,8 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc index e9aa27200606..20039aed2486 100644 --- a/OvmfPkg/OvmfXen.dsc +++ b/OvmfPkg/OvmfXen.dsc @@ -170,6 +170,7 @@ LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf !if $(SOURCE_DEBUG_ENABLE) == TRUE PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf -- 2.29.2.windows.2