diff options
author | Dun Tan <dun.tan@intel.com> | 2023-03-16 10:34:40 +0800 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2023-03-27 08:21:58 +0000 |
commit | 4904a2b1ecb700fce6085f3e0ae18a73aed97a2e (patch) | |
tree | 74977ec86f1735e29647755752b3eb17e82ad3de /UefiCpuPkg/Library | |
parent | 563a2d2695891a709394ce39af8349a2dee64b4f (diff) | |
download | edk2-4904a2b1ecb700fce6085f3e0ae18a73aed97a2e.tar.gz edk2-4904a2b1ecb700fce6085f3e0ae18a73aed97a2e.tar.bz2 edk2-4904a2b1ecb700fce6085f3e0ae18a73aed97a2e.zip |
UefiCpuPkg/CpuPageTableLib: Fix the non-1:1 mapping issue
In previous code logic, when splitting a leaf parent entry to
smaller granularity child page table, if the parent entry
Attribute&Mask(without PageTableBaseAddress field) is equal to the
input attribute&mask(without PageTableBaseAddress field), the split
process won't happen. This may lead to failure in non-1:1 mapping.
For example, there is a page table in which [0, 1G] is mapped(Lv4[0]
,Lv3[0,0], a non-leaf level4 entry and a leaf level3 entry). And we
want to remap [0, 2M] linear address range to [1G, 1G + 2M] with the
same attibute. The expected behaviour should be: split Lv3[0,0]
entry into 512 level2 entries and remap the first level2 entry to
cover [0, 2M]. But the split won't happen in previous code since
PageTableBaseAddress of input Attribute is not checked.
So, when checking if a leaf parent entry needs to be splitted, we
should also check if PageTableBaseAddress calculated by parent entry
is equal to the value caculated by input attribute.
Signed-off-by: Dun Tan <dun.tan@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Tested-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'UefiCpuPkg/Library')
-rw-r--r-- | UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c index 127b65183f..b94ef07c56 100644 --- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c +++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c @@ -274,6 +274,8 @@ PageTableLibMapInLevel ( IA32_MAP_ATTRIBUTE ChildMask;
IA32_MAP_ATTRIBUTE CurrentMask;
IA32_MAP_ATTRIBUTE LocalParentAttribute;
+ UINT64 PhysicalAddrInEntry;
+ UINT64 PhysicalAddrInAttr;
ASSERT (Level != 0);
ASSERT ((Attribute != NULL) && (Mask != NULL));
@@ -341,7 +343,15 @@ PageTableLibMapInLevel ( // This function is called when the memory length is less than the region length of the parent level.
// No need to split the page when the attributes equal.
//
- return RETURN_SUCCESS;
+ if (Mask->Bits.PageTableBaseAddress == 0) {
+ return RETURN_SUCCESS;
+ }
+
+ PhysicalAddrInEntry = IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&PleBAttribute) + MultU64x32 (RegionLength, (UINT32)PagingEntryIndex);
+ PhysicalAddrInAttr = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) & (~RegionMask);
+ if (PhysicalAddrInEntry == PhysicalAddrInAttr) {
+ return RETURN_SUCCESS;
+ }
}
ASSERT (Buffer == NULL || *BufferSize >= SIZE_4KB);
|