]> xenbits.xensource.com Git - ovmf.git/commitdiff
UefiCpuPkg/CpuPageTableLib: Fix the non-1:1 mapping issue
authorDun Tan <dun.tan@intel.com>
Thu, 16 Mar 2023 02:34:40 +0000 (10:34 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 27 Mar 2023 08:21:58 +0000 (08:21 +0000)
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>
UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c

index 127b65183f549f916784394c1479897bf489ad13..b94ef07c56be870e9ae0c0bc825c0dfa1fd90971 100644 (file)
@@ -274,6 +274,8 @@ PageTableLibMapInLevel (
   IA32_MAP_ATTRIBUTE  ChildMask;\r
   IA32_MAP_ATTRIBUTE  CurrentMask;\r
   IA32_MAP_ATTRIBUTE  LocalParentAttribute;\r
+  UINT64              PhysicalAddrInEntry;\r
+  UINT64              PhysicalAddrInAttr;\r
 \r
   ASSERT (Level != 0);\r
   ASSERT ((Attribute != NULL) && (Mask != NULL));\r
@@ -341,7 +343,15 @@ PageTableLibMapInLevel (
       // This function is called when the memory length is less than the region length of the parent level.\r
       // No need to split the page when the attributes equal.\r
       //\r
-      return RETURN_SUCCESS;\r
+      if (Mask->Bits.PageTableBaseAddress == 0) {\r
+        return RETURN_SUCCESS;\r
+      }\r
+\r
+      PhysicalAddrInEntry = IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&PleBAttribute) + MultU64x32 (RegionLength, (UINT32)PagingEntryIndex);\r
+      PhysicalAddrInAttr  = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) & (~RegionMask);\r
+      if (PhysicalAddrInEntry == PhysicalAddrInAttr) {\r
+        return RETURN_SUCCESS;\r
+      }\r
     }\r
 \r
     ASSERT (Buffer == NULL || *BufferSize >= SIZE_4KB);\r