3 Virtual Memory Management Services to test an address range encryption state
5 Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/CpuLib.h>
12 #include <Library/MemEncryptSevLib.h>
14 #include "VirtualMemory.h"
17 Returns the (updated) address range state based upon the page table
20 @param[in] CurrentState The current address range state
21 @param[in] PageDirectoryEntry The page table entry to check
22 @param[in] AddressEncMask The encryption mask
24 @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
26 @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
28 @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
31 MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
33 IN MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE CurrentState
,
34 IN UINT64 PageDirectoryEntry
,
35 IN UINT64 AddressEncMask
38 if (CurrentState
== MemEncryptSevAddressRangeEncrypted
) {
39 if ((PageDirectoryEntry
& AddressEncMask
) == 0) {
40 CurrentState
= MemEncryptSevAddressRangeMixed
;
42 } else if (CurrentState
== MemEncryptSevAddressRangeUnencrypted
) {
43 if ((PageDirectoryEntry
& AddressEncMask
) != 0) {
44 CurrentState
= MemEncryptSevAddressRangeMixed
;
46 } else if (CurrentState
== MemEncryptSevAddressRangeError
) {
48 // First address check, set initial state
50 if ((PageDirectoryEntry
& AddressEncMask
) == 0) {
51 CurrentState
= MemEncryptSevAddressRangeUnencrypted
;
53 CurrentState
= MemEncryptSevAddressRangeEncrypted
;
61 Returns the encryption state of the specified virtual address range.
63 @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
65 @param[in] BaseAddress Base address to check
66 @param[in] Length Length of virtual address range
68 @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
70 @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
72 @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
73 @retval MemEncryptSevAddressRangeError Address range is not mapped
75 MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
77 InternalMemEncryptSevGetAddressRangeState (
78 IN PHYSICAL_ADDRESS Cr3BaseAddress
,
79 IN PHYSICAL_ADDRESS BaseAddress
,
83 PAGE_MAP_AND_DIRECTORY_POINTER
*PageMapLevel4Entry
;
84 PAGE_MAP_AND_DIRECTORY_POINTER
*PageUpperDirectoryPointerEntry
;
85 PAGE_MAP_AND_DIRECTORY_POINTER
*PageDirectoryPointerEntry
;
86 PAGE_TABLE_1G_ENTRY
*PageDirectory1GEntry
;
87 PAGE_TABLE_ENTRY
*PageDirectory2MEntry
;
88 PAGE_TABLE_4K_ENTRY
*PageTableEntry
;
89 UINT64 AddressEncMask
;
91 PHYSICAL_ADDRESS Address
;
92 PHYSICAL_ADDRESS AddressEnd
;
93 MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State
;
96 // If Cr3BaseAddress is not specified then read the current CR3
98 if (Cr3BaseAddress
== 0) {
99 Cr3BaseAddress
= AsmReadCr3 ();
102 AddressEncMask
= MemEncryptSevGetEncryptionMask ();
103 AddressEncMask
&= PAGING_1G_ADDRESS_MASK_64
;
105 PgTableMask
= AddressEncMask
| EFI_PAGE_MASK
;
107 State
= MemEncryptSevAddressRangeError
;
110 // Encryption is on a page basis, so start at the beginning of the
111 // virtual address page boundary and walk page-by-page.
113 Address
= (PHYSICAL_ADDRESS
)(UINTN
)BaseAddress
& ~EFI_PAGE_MASK
;
114 AddressEnd
= (PHYSICAL_ADDRESS
)
115 (UINTN
)(BaseAddress
+ Length
);
117 while (Address
< AddressEnd
) {
118 PageMapLevel4Entry
= (VOID
*)(Cr3BaseAddress
& ~PgTableMask
);
119 PageMapLevel4Entry
+= PML4_OFFSET (Address
);
120 if (!PageMapLevel4Entry
->Bits
.Present
) {
121 return MemEncryptSevAddressRangeError
;
124 PageDirectory1GEntry
= (VOID
*)(
125 (PageMapLevel4Entry
->Bits
.PageTableBaseAddress
<<
128 PageDirectory1GEntry
+= PDP_OFFSET (Address
);
129 if (!PageDirectory1GEntry
->Bits
.Present
) {
130 return MemEncryptSevAddressRangeError
;
134 // If the MustBe1 bit is not 1, it's not actually a 1GB entry
136 if (PageDirectory1GEntry
->Bits
.MustBe1
) {
140 State
= UpdateAddressState (
142 PageDirectory1GEntry
->Uint64
,
153 PageUpperDirectoryPointerEntry
=
154 (PAGE_MAP_AND_DIRECTORY_POINTER
*)PageDirectory1GEntry
;
155 PageDirectory2MEntry
=
157 (PageUpperDirectoryPointerEntry
->Bits
.PageTableBaseAddress
<<
160 PageDirectory2MEntry
+= PDE_OFFSET (Address
);
161 if (!PageDirectory2MEntry
->Bits
.Present
) {
162 return MemEncryptSevAddressRangeError
;
166 // If the MustBe1 bit is not a 1, it's not a 2MB entry
168 if (PageDirectory2MEntry
->Bits
.MustBe1
) {
172 State
= UpdateAddressState (
174 PageDirectory2MEntry
->Uint64
,
185 PageDirectoryPointerEntry
=
186 (PAGE_MAP_AND_DIRECTORY_POINTER
*)PageDirectory2MEntry
;
189 (PageDirectoryPointerEntry
->Bits
.PageTableBaseAddress
<<
192 PageTableEntry
+= PTE_OFFSET (Address
);
193 if (!PageTableEntry
->Bits
.Present
) {
194 return MemEncryptSevAddressRangeError
;
197 State
= UpdateAddressState (
199 PageTableEntry
->Uint64
,
203 Address
+= EFI_PAGE_SIZE
;