CpuPageTableLib: Fix parent attributes are not inherited properly

With the following paging structure that maps [0, 2G] with ReadWrite
bit set.
PML4[0] --> PDPTE[0] --> PDE[0-255]
              \-> PDPTE[1] --> PDE[0-255]

If ReadWrite bit is cleared in PML4[0] and PageTableMap() is called
to change [0, 2M] as writable, today's logic doesn't inherit the
parent entry's attributes when determining the child entry's
attributes. It just sets the PDPTE[0].PDE[0].ReadWrite bit.
But since the PML4[0].ReadWrite is 0, [0, 2M] is still read-only.

The change fixes the bug.
If the inheritable attributes in ParentPagingEntry conflicts with the
requested attributes, let the child entries take the parent attributes
and loosen the attribute in the parent entry.

E.g.: when PDPTE[0].ReadWrite = 0 but caller wants to map [0-2MB as
ReadWrite = 1 (PDE[0].ReadWrite = 1), we need to change
PDPTE[0].ReadWrite = 1 and let all PDE[0-255].ReadWrite = 0 first.
Then change PDE[0].ReadWrite = 1.

Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
This commit is contained in:
Ray Ni
2022-07-15 20:10:08 +08:00
committed by mergify[bot]
parent c16f02f776
commit f4c845e46b
2 changed files with 147 additions and 17 deletions

View File

@@ -21,7 +21,11 @@
#define REGION_LENGTH(l) LShiftU64 (1, (l) * 9 + 3)
typedef struct {
UINT64 Present : 1; // 0 = Not present in memory, 1 = Present in memory
UINT64 Present : 1; // 0 = Not present in memory, 1 = Present in memory
UINT64 ReadWrite : 1; // 0 = Read-Only, 1= Read/Write
UINT64 UserSupervisor : 1; // 0 = Supervisor, 1=User
UINT64 Reserved : 58;
UINT64 Nx : 1; // No Execute bit
} IA32_PAGE_COMMON_ENTRY;
///
@@ -201,4 +205,18 @@ PageTableLibGetPleBMapAttribute (
IN IA32_MAP_ATTRIBUTE *ParentMapAttribute
);
/**
Return the attribute of a non-leaf page table entry.
@param[in] Pnle Pointer to a non-leaf page table entry.
@param[in] ParentMapAttribute Pointer to the parent attribute.
@return Attribute of the non-leaf page table entry.
**/
UINT64
PageTableLibGetPnleMapAttribute (
IN IA32_PAGE_NON_LEAF_ENTRY *Pnle,
IN IA32_MAP_ATTRIBUTE *ParentMapAttribute
);
#endif