diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index cdb29d5314..66bbbc80cd 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -626,6 +626,7 @@ OvmfPkg/AmdSev/SecretPei/SecretPei.inf !if $(TPM_ENABLE) == TRUE + OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf SecurityPkg/Tcg/TcgPei/TcgPei.inf SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index c0098502aa..dd0030dbf1 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -147,6 +147,7 @@ INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf INF OvmfPkg/AmdSev/SecretPei/SecretPei.inf !if $(TPM_ENABLE) == TRUE +INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf INF SecurityPkg/Tcg/TcgPei/TcgPei.inf INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 1730b6558b..33fbd76790 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -706,6 +706,7 @@ UefiCpuPkg/CpuMpPei/CpuMpPei.inf !if $(TPM_ENABLE) == TRUE + OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf SecurityPkg/Tcg/TcgPei/TcgPei.inf SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf index f400c845b9..b3c8b56f3b 100644 --- a/OvmfPkg/OvmfPkgIa32.fdf +++ b/OvmfPkg/OvmfPkgIa32.fdf @@ -162,6 +162,7 @@ INF OvmfPkg/SmmAccess/SmmAccessPei.inf INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf !if $(TPM_ENABLE) == TRUE +INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf INF SecurityPkg/Tcg/TcgPei/TcgPei.inf INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 78a559da0d..b13e5cfd90 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -719,6 +719,7 @@ UefiCpuPkg/CpuMpPei/CpuMpPei.inf !if $(TPM_ENABLE) == TRUE + OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf SecurityPkg/Tcg/TcgPei/TcgPei.inf SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf index d055552fd0..86592c2364 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -162,6 +162,7 @@ INF OvmfPkg/SmmAccess/SmmAccessPei.inf INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf !if $(TPM_ENABLE) == TRUE +INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf INF SecurityPkg/Tcg/TcgPei/TcgPei.inf INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index a7d747f6b4..999738dc39 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -718,6 +718,7 @@ UefiCpuPkg/CpuMpPei/CpuMpPei.inf !if $(TPM_ENABLE) == TRUE + OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf SecurityPkg/Tcg/TcgPei/TcgPei.inf SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index d519f85328..d6be798fca 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -174,6 +174,7 @@ INF OvmfPkg/SmmAccess/SmmAccessPei.inf INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf !if $(TPM_ENABLE) == TRUE +INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf INF SecurityPkg/Tcg/TcgPei/TcgPei.inf INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf diff --git a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf new file mode 100644 index 0000000000..51ad6d0d05 --- /dev/null +++ b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf @@ -0,0 +1,40 @@ +## @file +# Map TPM MMIO range unencrypted when SEV-ES is active. +# Install gOvmfTpmMmioAccessiblePpiGuid unconditionally. +# +# Copyright (C) 2021, Advanced Micro Devices, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 1.29 + BASE_NAME = TpmMmioSevDecryptPei + FILE_GUID = F12F698A-E506-4A1B-B32E-6920E55DA1C4 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = TpmMmioSevDecryptPeimEntryPoint + +[Sources] + TpmMmioSevDecryptPeim.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + DebugLib + MemEncryptSevLib + PcdLib + PeimEntryPoint + PeiServicesLib + +[Ppis] + gOvmfTpmMmioAccessiblePpiGuid ## PRODUCES + +[FixedPcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES + +[Depex] + gEfiPeiMemoryDiscoveredPpiGuid diff --git a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c new file mode 100644 index 0000000000..df2ad62330 --- /dev/null +++ b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c @@ -0,0 +1,87 @@ +/** @file + Map TPM MMIO range unencrypted when SEV-ES is active. + Install gOvmfTpmMmioAccessiblePpiGuid unconditionally. + + Copyright (C) 2021, Advanced Micro Devices, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + + +#include + +#include +#include +#include +#include + +STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmMmioRangeAccessible = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gOvmfTpmMmioAccessiblePpiGuid, + NULL +}; + +/** + The entry point for TPM MMIO range mapping driver. + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Describes the list of possible PEI Services. + + @retval EFI_ABORTED No need to keep this PEIM resident +**/ +EFI_STATUS +EFIAPI +TpmMmioSevDecryptPeimEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + RETURN_STATUS DecryptStatus; + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "%a\n", __FUNCTION__)); + + // + // If SEV is active, MMIO succeeds against an encrypted physical address + // because the nested page fault (NPF) that occurs on access does not + // include the encryption bit in the guest physical address provided to the + // hypervisor. + // + // If SEV-ES is active, MMIO would succeed against an encrypted physical + // address because the #VC handler uses the virtual address (which is an + // identity mapped physical address without the encryption bit) as the guest + // physical address of the MMIO target in the VMGEXIT. + // + // However, if SEV-ES is active, before performing the actual MMIO, an + // additional MMIO mitigation check is performed in the #VC handler to ensure + // that MMIO is being done to/from an unencrypted address. To prevent guest + // termination in this scenario, mark the range unencrypted ahead of access. + // + if (MemEncryptSevEsIsEnabled ()) { + DEBUG ((DEBUG_INFO, + "%a: mapping TPM MMIO address range unencrypted\n", + __FUNCTION__)); + + DecryptStatus = MemEncryptSevClearPageEncMask ( + 0, + FixedPcdGet64 (PcdTpmBaseAddress), + EFI_SIZE_TO_PAGES ((UINTN) 0x5000), + FALSE + ); + + if (RETURN_ERROR (DecryptStatus)) { + DEBUG ((DEBUG_ERROR, + "%a: failed to map TPM MMIO address range unencrypted\n", + __FUNCTION__)); + ASSERT_RETURN_ERROR (DecryptStatus); + } + } + + // + // MMIO range available + // + Status = PeiServicesInstallPpi (&mTpmMmioRangeAccessible); + ASSERT_EFI_ERROR (Status); + + return EFI_ABORTED; +}