From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.groups.io with SMTP id smtpd.web12.3190.1609840132653267096 for ; Tue, 05 Jan 2021 01:48:52 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=FTttNrlb; spf=pass (domain: redhat.com, ip: 216.205.24.124, mailfrom: lersek@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1609840131; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=delAHURb+ktwX/xbqmkPTdE3LgizETO2fviQUFsf4WU=; b=FTttNrlbK1wc9vtaTaoiY/vaGnKrmEz3MR6flAQJWqrYxpC8+Af069fwwtkKFwpvcq9FGZ f8srLPRoxCoVD645LGxfYf9SRlCGBHfmnh6wpjHsRbFmpjo+hpUZCt3aX7SblL/8hjCLpb tRMrcreE7MeaVdVPiBCYrT7UwCMbKkA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-149-VtLSNAKTOUuQOChL9T9bKA-1; Tue, 05 Jan 2021 04:48:48 -0500 X-MC-Unique: VtLSNAKTOUuQOChL9T9bKA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7D8A81005504; Tue, 5 Jan 2021 09:48:46 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-112-233.ams2.redhat.com [10.36.112.233]) by smtp.corp.redhat.com (Postfix) with ESMTP id B185771D5F; Tue, 5 Jan 2021 09:48:44 +0000 (UTC) Subject: Re: [edk2-devel] [PATCH 09/12] OvmfPkg/MemEncryptSevLib: Address range encryption state interface To: devel@edk2.groups.io, thomas.lendacky@amd.com Cc: Brijesh Singh , James Bottomley , Jordan Justen , Ard Biesheuvel References: <6877ca800856e85692d7ab99357895fa318f36c7.1608065471.git.thomas.lendacky@amd.com> From: "Laszlo Ersek" Message-ID: Date: Tue, 5 Jan 2021 10:48:43 +0100 MIME-Version: 1.0 In-Reply-To: <6877ca800856e85692d7ab99357895fa318f36c7.1608065471.git.thomas.lendacky@amd.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lersek@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit On 12/15/20 21:51, Lendacky, Thomas wrote: > From: Tom Lendacky > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3108 > > Update the MemEncryptSevLib library to include an interface that can > report the encryption state on a range of memory. The values will > represent the range as being unencrypted, encrypted, a mix of unencrypted > and encrypted, and error (e.g. ranges that aren't mapped). > > Cc: Jordan Justen > Cc: Laszlo Ersek > Cc: Ard Biesheuvel > Cc: Brijesh Singh > Signed-off-by: Tom Lendacky > --- > .../DxeBaseMemEncryptSevLib.inf | 1 + > .../PeiBaseMemEncryptSevLib.inf | 1 + > .../SecBaseMemEncryptSevLib.inf | 1 + > OvmfPkg/Include/Library/MemEncryptSevLib.h | 33 +++ > .../BaseMemEncryptSevLib/X64/VirtualMemory.h | 35 ++- > .../Ia32/MemEncryptSevLib.c | 31 ++- > .../X64/MemEncryptSevLib.c | 32 ++- > .../X64/PeiDxeVirtualMemory.c | 19 +- > .../X64/SecVirtualMemory.c | 20 ++ > .../BaseMemEncryptSevLib/X64/VirtualMemory.c | 207 ++++++++++++++++++ > 10 files changed, 368 insertions(+), 12 deletions(-) > create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c Acked-by: Laszlo Ersek Thanks, Laszlo > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeBaseMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeBaseMemEncryptSevLib.inf > index 390f2d60677f..04728a5dd256 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeBaseMemEncryptSevLib.inf > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeBaseMemEncryptSevLib.inf > @@ -34,6 +34,7 @@ [Sources.X64] > MemEncryptSevLibInternal.c > X64/MemEncryptSevLib.c > X64/PeiDxeVirtualMemory.c > + X64/VirtualMemory.c > X64/VirtualMemory.h > > [Sources.IA32] > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiBaseMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiBaseMemEncryptSevLib.inf > index cb973fdeb868..4e4f59c0b0b6 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiBaseMemEncryptSevLib.inf > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiBaseMemEncryptSevLib.inf > @@ -34,6 +34,7 @@ [Sources.X64] > MemEncryptSevLibInternal.c > X64/MemEncryptSevLib.c > X64/PeiDxeVirtualMemory.c > + X64/VirtualMemory.c > X64/VirtualMemory.h > > [Sources.IA32] > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecBaseMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/SecBaseMemEncryptSevLib.inf > index b26f739d69fd..79389298a3b3 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecBaseMemEncryptSevLib.inf > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecBaseMemEncryptSevLib.inf > @@ -34,6 +34,7 @@ [Sources.X64] > MemEncryptSevLibInternal.c > X64/MemEncryptSevLib.c > X64/SecVirtualMemory.c > + X64/VirtualMemory.c > X64/VirtualMemory.h > > [Sources.IA32] > diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h > index 394065f15bc1..421b2e2c2c1e 100644 > --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h > +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h > @@ -33,6 +33,16 @@ typedef struct _SEC_SEV_ES_WORK_AREA { > UINT64 EncryptionMask; > } SEC_SEV_ES_WORK_AREA; > > +// > +// Memory encryption address range states. > +// > +typedef enum { > + MemEncryptSevAddressRangeUnencrypted, > + MemEncryptSevAddressRangeEncrypted, > + MemEncryptSevAddressRangeMixed, > + MemEncryptSevAddressRangeError, > +} MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE; > + > /** > Returns a boolean to indicate whether SEV-ES is enabled. > > @@ -147,4 +157,27 @@ MemEncryptSevGetEncryptionMask ( > VOID > ); > > +/** > + Returns the encryption state of the specified virtual address range. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use > + current CR3) > + @param[in] BaseAddress Base address to check > + @param[in] Length Length of virtual address range > + > + @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped > + unencrypted > + @retval MemEncryptSevAddressRangeEncrypted Address range is mapped > + encrypted > + @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed > + @retval MemEncryptSevAddressRangeError Address range is not mapped > +**/ > +MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE > +EFIAPI > +MemEncryptSevGetAddressRangeState ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN Length > + ); > + > #endif // _MEM_ENCRYPT_SEV_LIB_H_ > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h > index 26d26cd922a4..996f94f07ebb 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h > @@ -3,7 +3,7 @@ > Virtual Memory Management Services to set or clear the memory encryption bit > > Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
> - Copyright (c) 2017, AMD Incorporated. All rights reserved.
> + Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.
> > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -178,7 +178,17 @@ typedef struct { > UINTN FreePages; > } PAGE_TABLE_POOL; > > +/** > + Return the pagetable memory encryption mask. > > + @return The pagetable memory encryption mask. > + > +**/ > +UINT64 > +EFIAPI > +InternalGetMemEncryptionAddressMask ( > + VOID > + ); > > /** > This function clears memory encryption bit for the memory region specified by > @@ -234,4 +244,27 @@ InternalMemEncryptSevSetMemoryEncrypted ( > IN BOOLEAN Flush > ); > > +/** > + Returns the encryption state of the specified virtual address range. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use > + current CR3) > + @param[in] BaseAddress Base address to check > + @param[in] Length Length of virtual address range > + > + @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped > + unencrypted > + @retval MemEncryptSevAddressRangeEncrypted Address range is mapped > + encrypted > + @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed > + @retval MemEncryptSevAddressRangeError Address range is not mapped > +**/ > +MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE > +EFIAPI > +InternalMemEncryptSevGetAddressRangeState ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN Length > + ); > + > #endif > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c > index b4f6e5738e6e..12a5bf495bd7 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c > @@ -2,7 +2,7 @@ > > Secure Encrypted Virtualization (SEV) library helper function > > - Copyright (c) 2017, AMD Incorporated. All rights reserved.
> + Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.
> > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -82,3 +82,32 @@ MemEncryptSevSetPageEncMask ( > // > return RETURN_UNSUPPORTED; > } > + > +/** > + Returns the encryption state of the specified virtual address range. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use > + current CR3) > + @param[in] BaseAddress Base address to check > + @param[in] Length Length of virtual address range > + > + @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped > + unencrypted > + @retval MemEncryptSevAddressRangeEncrypted Address range is mapped > + encrypted > + @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed > + @retval MemEncryptSevAddressRangeError Address range is not mapped > +**/ > +MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE > +EFIAPI > +MemEncryptSevGetAddressRangeState ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN Length > + ) > +{ > + // > + // Memory is always encrypted in 32-bit mode > + // > + return MemEncryptSevAddressRangeEncrypted; > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c > index cf0921e21464..4fea6a6be0ac 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c > @@ -2,7 +2,7 @@ > > Secure Encrypted Virtualization (SEV) library helper function > > - Copyright (c) 2017, AMD Incorporated. All rights reserved.
> + Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.
> > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -88,3 +88,33 @@ MemEncryptSevSetPageEncMask ( > Flush > ); > } > + > +/** > + Returns the encryption state of the specified virtual address range. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use > + current CR3) > + @param[in] BaseAddress Base address to check > + @param[in] Length Length of virtual address range > + > + @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped > + unencrypted > + @retval MemEncryptSevAddressRangeEncrypted Address range is mapped > + encrypted > + @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed > + @retval MemEncryptSevAddressRangeError Address range is not mapped > +**/ > +MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE > +EFIAPI > +MemEncryptSevGetAddressRangeState ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN Length > + ) > +{ > + return InternalMemEncryptSevGetAddressRangeState ( > + Cr3BaseAddress, > + BaseAddress, > + Length > + ); > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c > index 3a5bab657bd7..d3455e812bd1 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c > @@ -28,14 +28,14 @@ typedef enum { > } MAP_RANGE_MODE; > > /** > - Get the memory encryption mask > + Return the pagetable memory encryption mask. > > - @param[out] EncryptionMask contains the pte mask. > + @return The pagetable memory encryption mask. > > **/ > -STATIC > UINT64 > -GetMemEncryptionAddressMask ( > +EFIAPI > +InternalGetMemEncryptionAddressMask ( > VOID > ) > { > @@ -200,7 +200,7 @@ Split2MPageTo4K ( > > PageTableEntry1 = PageTableEntry; > > - AddressEncMask = GetMemEncryptionAddressMask (); > + AddressEncMask = InternalGetMemEncryptionAddressMask (); > > ASSERT (PageTableEntry != NULL); > ASSERT (*PageEntry2M & AddressEncMask); > @@ -286,7 +286,7 @@ SetPageTablePoolReadOnly ( > LevelSize[3] = SIZE_1GB; > LevelSize[4] = SIZE_512GB; > > - AddressEncMask = GetMemEncryptionAddressMask(); > + AddressEncMask = InternalGetMemEncryptionAddressMask(); > PageTable = (UINT64 *)(UINTN)PageTableBase; > PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE; > > @@ -431,7 +431,7 @@ Split1GPageTo2M ( > > PageDirectoryEntry = AllocatePageTableMemory(1); > > - AddressEncMask = GetMemEncryptionAddressMask (); > + AddressEncMask = InternalGetMemEncryptionAddressMask (); > ASSERT (PageDirectoryEntry != NULL); > ASSERT (*PageEntry1G & AddressEncMask); > // > @@ -485,7 +485,7 @@ SetOrClearCBit( > { > UINT64 AddressEncMask; > > - AddressEncMask = GetMemEncryptionAddressMask (); > + AddressEncMask = InternalGetMemEncryptionAddressMask (); > > if (Mode == SetCBit) { > *PageTablePointer |= AddressEncMask; > @@ -527,6 +527,7 @@ DisableReadOnlyPageWriteProtect ( > /** > Enable Write Protect on pages marked as read-only. > **/ > +STATIC > VOID > EnableReadOnlyPageWriteProtect ( > VOID > @@ -605,7 +606,7 @@ SetMemoryEncDec ( > // > // Check if we have a valid memory encryption mask > // > - AddressEncMask = GetMemEncryptionAddressMask (); > + AddressEncMask = InternalGetMemEncryptionAddressMask (); > if (!AddressEncMask) { > return RETURN_ACCESS_DENIED; > } > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c > index 5c337ea0b820..bca5e3febb1b 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c > @@ -13,6 +13,26 @@ > > #include "VirtualMemory.h" > > +/** > + Return the pagetable memory encryption mask. > + > + @return The pagetable memory encryption mask. > + > +**/ > +UINT64 > +EFIAPI > +InternalGetMemEncryptionAddressMask ( > + VOID > + ) > +{ > + UINT64 EncryptionMask; > + > + EncryptionMask = MemEncryptSevGetEncryptionMask (); > + EncryptionMask &= PAGING_1G_ADDRESS_MASK_64; > + > + return EncryptionMask; > +} > + > /** > This function clears memory encryption bit for the memory region specified by > PhysicalAddress and Length from the current page table context. > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c > new file mode 100644 > index 000000000000..36aabcf556a7 > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c > @@ -0,0 +1,207 @@ > +/** @file > + > + Virtual Memory Management Services to test an address range encryption state > + > + Copyright (c) 2020, AMD Incorporated. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > + > +#include "VirtualMemory.h" > + > +/** > + Returns the (updated) address range state based upon the page table > + entry. > + > + @param[in] CurrentState The current address range state > + @param[in] PageDirectoryEntry The page table entry to check > + @param[in] AddressEncMask The encryption mask > + > + @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped > + unencrypted > + @retval MemEncryptSevAddressRangeEncrypted Address range is mapped > + encrypted > + @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed > +**/ > +STATIC > +MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE > +UpdateAddressState ( > + IN MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE CurrentState, > + IN UINT64 PageDirectoryEntry, > + IN UINT64 AddressEncMask > + ) > +{ > + if (CurrentState == MemEncryptSevAddressRangeEncrypted) { > + if ((PageDirectoryEntry & AddressEncMask) == 0) { > + CurrentState = MemEncryptSevAddressRangeMixed; > + } > + } else if (CurrentState == MemEncryptSevAddressRangeUnencrypted) { > + if ((PageDirectoryEntry & AddressEncMask) != 0) { > + CurrentState = MemEncryptSevAddressRangeMixed; > + } > + } else if (CurrentState == MemEncryptSevAddressRangeError) { > + // > + // First address check, set initial state > + // > + if ((PageDirectoryEntry & AddressEncMask) == 0) { > + CurrentState = MemEncryptSevAddressRangeUnencrypted; > + } else { > + CurrentState = MemEncryptSevAddressRangeEncrypted; > + } > + } > + > + return CurrentState; > +} > + > +/** > + Returns the encryption state of the specified virtual address range. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use > + current CR3) > + @param[in] BaseAddress Base address to check > + @param[in] Length Length of virtual address range > + > + @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped > + unencrypted > + @retval MemEncryptSevAddressRangeEncrypted Address range is mapped > + encrypted > + @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed > + @retval MemEncryptSevAddressRangeError Address range is not mapped > +**/ > +MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE > +EFIAPI > +InternalMemEncryptSevGetAddressRangeState ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN Length > + ) > +{ > + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; > + PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry; > + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; > + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; > + PAGE_TABLE_ENTRY *PageDirectory2MEntry; > + PAGE_TABLE_4K_ENTRY *PageTableEntry; > + UINT64 AddressEncMask; > + UINT64 PgTableMask; > + PHYSICAL_ADDRESS Address; > + PHYSICAL_ADDRESS AddressEnd; > + MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State; > + > + // > + // If Cr3BaseAddress is not specified then read the current CR3 > + // > + if (Cr3BaseAddress == 0) { > + Cr3BaseAddress = AsmReadCr3(); > + } > + > + AddressEncMask = MemEncryptSevGetEncryptionMask (); > + AddressEncMask &= PAGING_1G_ADDRESS_MASK_64; > + > + PgTableMask = AddressEncMask | EFI_PAGE_MASK; > + > + State = MemEncryptSevAddressRangeError; > + > + // > + // Encryption is on a page basis, so start at the beginning of the > + // virtual address page boundary and walk page-by-page. > + // > + Address = (PHYSICAL_ADDRESS) (UINTN) BaseAddress & ~EFI_PAGE_MASK; > + AddressEnd = (PHYSICAL_ADDRESS) > + (UINTN) (BaseAddress + Length); > + > + while (Address < AddressEnd) { > + PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask); > + PageMapLevel4Entry += PML4_OFFSET (Address); > + if (!PageMapLevel4Entry->Bits.Present) { > + return MemEncryptSevAddressRangeError; > + } > + > + PageDirectory1GEntry = (VOID *) ( > + (PageMapLevel4Entry->Bits.PageTableBaseAddress << > + 12) & ~PgTableMask > + ); > + PageDirectory1GEntry += PDP_OFFSET (Address); > + if (!PageDirectory1GEntry->Bits.Present) { > + return MemEncryptSevAddressRangeError; > + } > + > + // > + // If the MustBe1 bit is not 1, it's not actually a 1GB entry > + // > + if (PageDirectory1GEntry->Bits.MustBe1) { > + // > + // Valid 1GB page > + // > + State = UpdateAddressState ( > + State, > + PageDirectory1GEntry->Uint64, > + AddressEncMask > + ); > + > + Address += BIT30; > + continue; > + } > + > + // > + // Actually a PDP > + // > + PageUpperDirectoryPointerEntry = > + (PAGE_MAP_AND_DIRECTORY_POINTER *) PageDirectory1GEntry; > + PageDirectory2MEntry = > + (VOID *) ( > + (PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress << > + 12) & ~PgTableMask > + ); > + PageDirectory2MEntry += PDE_OFFSET (Address); > + if (!PageDirectory2MEntry->Bits.Present) { > + return MemEncryptSevAddressRangeError; > + } > + > + // > + // If the MustBe1 bit is not a 1, it's not a 2MB entry > + // > + if (PageDirectory2MEntry->Bits.MustBe1) { > + // > + // Valid 2MB page > + // > + State = UpdateAddressState ( > + State, > + PageDirectory2MEntry->Uint64, > + AddressEncMask > + ); > + > + Address += BIT21; > + continue; > + } > + > + // > + // Actually a PMD > + // > + PageDirectoryPointerEntry = > + (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory2MEntry; > + PageTableEntry = > + (VOID *)( > + (PageDirectoryPointerEntry->Bits.PageTableBaseAddress << > + 12) & ~PgTableMask > + ); > + PageTableEntry += PTE_OFFSET (Address); > + if (!PageTableEntry->Bits.Present) { > + return MemEncryptSevAddressRangeError; > + } > + > + State = UpdateAddressState ( > + State, > + PageTableEntry->Uint64, > + AddressEncMask > + ); > + > + Address += EFI_PAGE_SIZE; > + } > + > + return State; > +} >