]> xenbits.xensource.com Git - ovmf.git/commitdiff
UefiCpuPkg/CpuPageTableLib: Fix issue when splitting leaf entry
authorDun Tan <dun.tan@intel.com>
Fri, 9 Dec 2022 02:34:43 +0000 (10:34 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 27 Mar 2023 08:21:58 +0000 (08:21 +0000)
When splitting leaf parent entry to smaller granularity, create
child page table before modifing parent entry. In previous code
logic, when splitting a leaf parent entry, parent entry will
point to a null 4k memory before child page table is created in
this 4k memory. When the page table to be modified is the page
table in CR3, if the executed CpuPageTableLib code is in the
range mapped by the modified leaf parent entry, then issue will
happen.

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 57f1db203b9adf058092ade29bdf307d7dddf298..f09bb63ad1351b39106ffd4daa9afdfebaff6a23 100644 (file)
@@ -363,21 +363,24 @@ PageTableLibMapInLevel (
       //\r
       // Create 512 child-level entries that map to 2M/4K.\r
       //\r
-      ParentPagingEntry->Uintn = (UINTN)Buffer + *BufferSize;\r
-      ZeroMem ((VOID *)ParentPagingEntry->Uintn, SIZE_4KB);\r
+      PagingEntry = (IA32_PAGING_ENTRY *)((UINTN)Buffer + *BufferSize);\r
+      ZeroMem (PagingEntry, SIZE_4KB);\r
+\r
+      for (SubOffset = 0, Index = 0; Index < 512; Index++) {\r
+        PagingEntry[Index].Uint64 = OneOfPagingEntry.Uint64 + SubOffset;\r
+        SubOffset                += RegionLength;\r
+      }\r
 \r
       //\r
       // Set NOP attributes\r
       // Note: Should NOT inherit the attributes from the original entry because a zero RW bit\r
       //       will make the entire region read-only even the child entries set the RW bit.\r
       //\r
+      // Non-leaf entry doesn't have PAT bit. So use ~IA32_PE_BASE_ADDRESS_MASK_40 is to make sure PAT bit\r
+      // (bit12) in original big-leaf entry is not assigned to PageTableBaseAddress field of non-leaf entry.\r
+      //\r
       PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute, &AllOneMask);\r
-\r
-      PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry->Pnle);\r
-      for (SubOffset = 0, Index = 0; Index < 512; Index++) {\r
-        PagingEntry[Index].Uint64 = OneOfPagingEntry.Uint64 + SubOffset;\r
-        SubOffset                += RegionLength;\r
-      }\r
+      ParentPagingEntry->Uint64 = ((UINTN)(VOID *)PagingEntry) | (ParentPagingEntry->Uint64 & (~IA32_PE_BASE_ADDRESS_MASK_40));\r
     }\r
   } else {\r
     //\r