On 4/22/21 9:51 AM, Tom Lendacky wrote: > On 4/22/21 2:34 AM, Laszlo Ersek wrote: >> On 04/21/21 01:13, Lendacky, Thomas wrote: >>> On 4/20/21 5:54 PM, Lendacky, Thomas via groups.io wrote: >>>> From: Tom Lendacky <thomas.lenda...@amd.com> >>>> >>>> BZ: >>>> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3345&data=04%7C01%7Cthomas.lendacky%40amd.com%7C6b8da1f9a3bf4fb5f01e08d905613998%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637546737416495415%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=5vPlHPzGlS2%2Bqu3U4RPMITpyY%2F2ZxKJlaVYfFZItONQ%3D&reserved=0 >>>> >>>> The TPM support in OVMF performs MMIO accesses during the PEI phase. At >>>> this point, MMIO ranges have not been marked un-encyrpted, so an SEV-ES >>>> guest will fail attempting to perform MMIO to an encrypted address. >> >> (1) The subject says SEV, not SEV-ES, and the code in the patch too >> suggests SEV, not SEV-ES. If that's correct, can you please update the >> commit message? > > Yes, I'll update the commit message. The action is correct for all SEV > guests in general, but it is only with SEV-ES, where the tighter MMIO > checks can be performed, that an actual issue shows up. > >> >>>> >>>> Read the PcdTpmBaseAddress and mark the specification defined range >>>> (0x5000 in length) as un-encrypted, to allow an SEV-ES guest to process >>>> the MMIO requests. >>>> >>>> Cc: Laszlo Ersek <ler...@redhat.com> >>>> Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> >>>> Cc: Jordan Justen <jordan.l.jus...@intel.com> >>>> Cc: Brijesh Singh <brijesh.si...@amd.com> >>>> Cc: James Bottomley <j...@linux.ibm.com> >>>> Cc: Jiewen Yao <jiewen....@intel.com> >>>> Cc: Min Xu <min.m...@intel.com> >>>> Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com> >>>> --- >>>> OvmfPkg/PlatformPei/PlatformPei.inf | 1 + >>>> OvmfPkg/PlatformPei/AmdSev.c | 19 +++++++++++++++++++ >>>> 2 files changed, 20 insertions(+) >>>> >>>> diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf >>>> b/OvmfPkg/PlatformPei/PlatformPei.inf >>>> index 6ef77ba7bb21..de60332e9390 100644 >>>> --- a/OvmfPkg/PlatformPei/PlatformPei.inf >>>> +++ b/OvmfPkg/PlatformPei/PlatformPei.inf >>>> @@ -113,6 +113,7 @@ [Pcd] >>>> >>>> [FixedPcd] >>>> gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress >>>> + gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress >>>> gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS >>>> gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory >>>> gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType >>>> diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c >>>> index dddffdebda4b..d524929f9e10 100644 >>>> --- a/OvmfPkg/PlatformPei/AmdSev.c >>>> +++ b/OvmfPkg/PlatformPei/AmdSev.c >>>> @@ -141,6 +141,7 @@ AmdSevInitialize ( >>>> ) >>>> { >>>> UINT64 EncryptionMask; >>>> + UINT64 TpmBaseAddress; >>>> RETURN_STATUS PcdStatus; >>>> >>>> // >>>> @@ -206,6 +207,24 @@ AmdSevInitialize ( >>>> } >>>> } >>>> >>>> + // >>>> + // PEI TPM support will perform MMIO accesses, be sure this range is not >>>> + // marked encrypted. >>>> + // >>>> + TpmBaseAddress = PcdGet64 (PcdTpmBaseAddress); >>>> + if (TpmBaseAddress != 0) { >>>> + RETURN_STATUS DecryptStatus; >>>> + >>>> + DecryptStatus = MemEncryptSevClearPageEncMask ( >>>> + 0, >>>> + TpmBaseAddress, >>>> + EFI_SIZE_TO_PAGES (0x5000), >>>> + FALSE >>>> + ); >>>> + >>>> + ASSERT_RETURN_ERROR (DecryptStatus); >>>> + } >>>> + >>> >>> Laszlo, I'm not sure if this is the best way to approach this. It is >>> simple and straight forward and the TCG/TPM support is one of the few >>> (only?) pieces of code that does actual MMIO during PEI that is bitten >>> by not having the address marked as shared/unencrypted. >> >> In SEC, I think we have MMIO access too (LAPIC -- >> InitializeApicTimer()); why does that work? >> >> Hmm... Is that because we're immediately in x2apic mode, and that means >> CPUID plus MSR accesses, and not MMIO? (I'm reminded of commit >> decb365b0016 ("OvmfPkg: select LocalApicLib instance with x2apic >> support", 2015-11-30).) And, we have #VC handling in SEC too.
Missed this question in my earlier reply... LAPIC access has a dedicated check in ValidateMmioMemory() to allow access in this case. Thanks, Tom >> >> Anyway: I think the TPM (MMIO) access you see comes from this PEIM: >> >> OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf >> >> The driver uses the following library instance: >> >> SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf >> >> This library instance is what depends on "PcdTpmBaseAddress". >> >> And it's not just that decrypting the TPM MMIO range in PlatformPei >> "looks awkward", but I don't even see it immediately why PlatformPei is >> guaranteed to be dispatched before Tcg2ConfigPei. The effective depex of >> Tcg2ConfigPei is just "gEfiPeiPcdPpiGuid" (on X64), according to the >> build report file. If Tcg2ConfigPei runs first, whatever we do in >> PlatformPei is too late. >> >> I also don't like that, with this patch, we'd decrypt the TPM range even >> if OVMF weren't built with "-D TPM_ENABLE". Namely, OVMF uses >> "PcdTpmBaseAddress" as fixed (not dynamic), inheriting the nonzero >> default from "SecurityPkg.dec". (In ArmVirtQemu, PcdTpmBaseAddress is >> set dynamically, which is why Tcg2ConfigPei has an ARM-specific depex >> too.) >> >> >> (2) So, can you please try the following, in the >> "OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf" module: > > I'll take the input from each of your emails on this and see how that all > works. Thanks for the insight and knowledge! > > Tom > >> >>> diff --git a/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf >>> b/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf >>> index 6776ec931ce0..0d0572b83599 100644 >>> --- a/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf >>> +++ b/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf >>> @@ -20,13 +20,16 @@ [Defines] >>> ENTRY_POINT = Tcg2ConfigPeimEntryPoint >>> >>> [Sources] >>> + MemEncrypt.h >>> Tcg2ConfigPeim.c >>> Tpm12Support.h >>> >>> [Sources.IA32, Sources.X64] >>> + MemEncryptSev.c >>> Tpm12Support.c >>> >>> [Sources.ARM, Sources.AARCH64] >>> + MemEncryptNull.c >>> Tpm12SupportNull.c >>> >>> [Packages] >>> @@ -43,6 +46,7 @@ [LibraryClasses] >>> >>> [LibraryClasses.IA32, LibraryClasses.X64] >>> BaseLib >>> + MemEncryptSevLib >>> Tpm12DeviceLib >>> >>> [Guids] >>> @@ -56,6 +60,9 @@ [Ppis] >>> [Pcd] >>> gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## >>> PRODUCES >>> >>> +[Pcd.IA32, Pcd.X64] >>> + gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## >>> SOMETIMES_CONSUMES >>> + >>> [Depex.IA32, Depex.X64] >>> TRUE >>> >> >> In the "MemEncrypt.h" file, declare a function called >> InternalTpmDecryptAddressRange(). The function definition in >> "MemEncryptNull.c" should do nothing, while the one in "MemEncryptSev.c" >> should check MemEncryptSevIsEnabled(), and then make the above-seen >> MemEncryptSevClearPageEncMask() call. >> >> The new InternalTpmDecryptAddressRange() function should be called from >> Tcg2ConfigPeimEntryPoint(), before the latter calls >> InternalTpm12Detect(). Regarding error checking... if >> InternalTpmDecryptAddressRange() fails, I think we can log an error >> message, and hang with CpuDeadLoop(). >> >> (An alternative approach would be to call MemEncryptSevIsEnabled() and >> MemEncryptSevClearPageEncMask() regardless of architecture, i.e., also >> on ARM / AARCH64. In addition to that, we'd have to implement a Null >> instance of MemEncryptSevLib, and resolve MemEncryptSevLib to the Null >> instance in the ArmVirtPkg DSC files. But I don't like that: the library >> *class* carries SEV in the name, which is inherently X64-specific, thus >> I wouldn't even like the lib *class* to leak into ArmVirtPkg.) >> >> >> (3) If the approach in (2) works, then please don't forget to update the >> patch subject (it currently refers to PlatformPei). >> >> >> (4) The argument of the EFI_SIZE_TO_PAGES() function-like macro should >> have type UINTN. The constant 0x5000 has type "int" (INT32); please cast >> it to UINTN. >> >> (In fact I would prefer a new macro for 0x5000, somewhere in the >> "MdePkg/Include/IndustryStandard/Tpm*.h" files; but I can see that >> SecurityPkg already open-codes the 0x5000 constant in >> "Tcg/Tcg2Acpi/Tpm.asl" and "Tcg/TcgSmm/Tpm.asl", so meh.) >> >> Thanks >> Laszlo >> -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#74376): https://edk2.groups.io/g/devel/message/74376 Mute This Topic: https://groups.io/mt/82248382/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-