summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorRay Ni <ray.ni@intel.com>2022-06-23 14:20:32 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2022-06-23 06:36:56 +0000
commit4bfd668e5edb59092a8e16414b3f6632efdac4f2 (patch)
treeb9de6a03a6c341304a69a199b2b387d0cdb7d65c /UefiCpuPkg
parentf304308e1cb21846a79fc8e4aa9ffa2cb1db3e4c (diff)
downloadedk2-4bfd668e5edb59092a8e16414b3f6632efdac4f2.tar.gz
edk2-4bfd668e5edb59092a8e16414b3f6632efdac4f2.tar.bz2
edk2-4bfd668e5edb59092a8e16414b3f6632efdac4f2.zip
UefiCpuPkg: CpuDxe: Set RW and P Attributes on Split Pages
A memory range can be submitted for attribute changes which is large enough to not require a page split during the attribute update. Consider the following scenario: 1. An attribute update removed the RW attribute on a range large enough to not require a page split. 2. Later, an attributes update is called to re-add the RW attribute for a subsection of that larger page which requires a split 3. The attribute update logic performs a page split, so now the parent and child pages have matching attributes 4. Then, the attribute update logic changes the child page to have the RW attribute. 5. The child page would then correctly have the RW attribute added but the parent page would still have the RW attribute removed which will cause an improper access violation. The page being split should have loose attributes to accommodate the above case. The split page should always have the attributes set so the lowest level page frame determines the access rights as detailed in 4.10.2.2 of the Intel 64 and IA-32 Architectures Software Developer Manual. Setting the User/Supervisor attribute shouldn't be necessary. Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Signed-off-by: Taylor Beebe <t@taylorbeebe.com>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/CpuDxe/CpuPageTable.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/CpuPageTable.c
index f7a4d92e92..5b1dec2d67 100644
--- a/UefiCpuPkg/CpuDxe/CpuPageTable.c
+++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c
@@ -37,7 +37,9 @@
#define IA32_PG_PMNT BIT62
#define IA32_PG_NX BIT63
-#define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
+#define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
+#define PAGE_ATTRIBUTE_BITS_POST_SPLIT (IA32_PG_RW | IA32_PG_P)
+
//
// Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
// X64 PAE PDPTE does not have such restriction
@@ -583,7 +585,7 @@ SplitPage (
NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) | AddressEncMask | ((*PageEntry) & PAGE_PROGATE_BITS);
}
- (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | ((*PageEntry) & PAGE_ATTRIBUTE_BITS);
+ (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | PAGE_ATTRIBUTE_BITS_POST_SPLIT;
return RETURN_SUCCESS;
} else {
return RETURN_UNSUPPORTED;
@@ -606,7 +608,7 @@ SplitPage (
NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) | AddressEncMask | IA32_PG_PS | ((*PageEntry) & PAGE_PROGATE_BITS);
}
- (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | ((*PageEntry) & PAGE_ATTRIBUTE_BITS);
+ (*PageEntry) = (UINT64)(UINTN)NewPageEntry | AddressEncMask | PAGE_ATTRIBUTE_BITS_POST_SPLIT;
return RETURN_SUCCESS;
} else {
return RETURN_UNSUPPORTED;