\r
@param[in] Pnle Pointer to IA32_PML5, IA32_PML4, IA32_PDPTE or IA32_PDE. All share the same structure definition.\r
@param[in] Attribute The attribute of the page directory referenced by the non-leaf.\r
+ @param[in] Mask The mask of the page directory referenced by the non-leaf.\r
**/\r
VOID\r
PageTableLibSetPnle (\r
IN IA32_PAGE_NON_LEAF_ENTRY *Pnle,\r
- IN IA32_MAP_ATTRIBUTE *Attribute\r
+ IN IA32_MAP_ATTRIBUTE *Attribute,\r
+ IN IA32_MAP_ATTRIBUTE *Mask\r
)\r
{\r
- Pnle->Bits.Present = Attribute->Bits.Present;\r
- Pnle->Bits.ReadWrite = Attribute->Bits.ReadWrite;\r
- Pnle->Bits.UserSupervisor = Attribute->Bits.UserSupervisor;\r
- Pnle->Bits.Nx = Attribute->Bits.Nx;\r
- Pnle->Bits.Accessed = 0;\r
+ if (Mask->Bits.Present) {\r
+ Pnle->Bits.Present = Attribute->Bits.Present;\r
+ }\r
+\r
+ if (Mask->Bits.ReadWrite) {\r
+ Pnle->Bits.ReadWrite = Attribute->Bits.ReadWrite;\r
+ }\r
+\r
+ if (Mask->Bits.UserSupervisor) {\r
+ Pnle->Bits.UserSupervisor = Attribute->Bits.UserSupervisor;\r
+ }\r
+\r
+ if (Mask->Bits.Nx) {\r
+ Pnle->Bits.Nx = Attribute->Bits.Nx;\r
+ }\r
+\r
+ Pnle->Bits.Accessed = 0;\r
\r
//\r
// Set the attributes (WT, CD, A) to 0.\r
Update page table to map [LinearAddress, LinearAddress + Length) with specified attribute in the specified level.\r
\r
@param[in] ParentPagingEntry The pointer to the page table entry to update.\r
+ @param[in] ParentAttribute The accumulated attribute of all parents' attribute.\r
@param[in] Modify FALSE to indicate Buffer is not used and BufferSize is increased by the required buffer size.\r
@param[in] Buffer The free buffer to be used for page table creation/updating.\r
When Modify is TRUE, it's used from the end.\r
RETURN_STATUS\r
PageTableLibMapInLevel (\r
IN IA32_PAGING_ENTRY *ParentPagingEntry,\r
+ IN IA32_MAP_ATTRIBUTE *ParentAttribute,\r
IN BOOLEAN Modify,\r
IN VOID *Buffer,\r
IN OUT INTN *BufferSize,\r
IA32_MAP_ATTRIBUTE NopAttribute;\r
BOOLEAN CreateNew;\r
IA32_PAGING_ENTRY OneOfPagingEntry;\r
+ IA32_MAP_ATTRIBUTE ChildAttribute;\r
+ IA32_MAP_ATTRIBUTE ChildMask;\r
\r
ASSERT (Level != 0);\r
ASSERT ((Attribute != NULL) && (Mask != NULL));\r
//\r
// Set default attribute bits for PML5E/PML4E/PDPTE/PDE.\r
//\r
- PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute);\r
+ PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute, &AllOneMask);\r
} else {\r
//\r
// Just make sure Present and MustBeZero (PageSize) bits are accurate.\r
// Use NOP attributes as the attribute of grand-parents because CPU will consider\r
// the actual attributes of grand-parents when determing the memory type.\r
//\r
- PleBAttribute.Uint64 = PageTableLibGetPleBMapAttribute (&ParentPagingEntry->PleB, &NopAttribute);\r
+ PleBAttribute.Uint64 = PageTableLibGetPleBMapAttribute (&ParentPagingEntry->PleB, ParentAttribute);\r
if ((IA32_MAP_ATTRIBUTE_ATTRIBUTES (&PleBAttribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask))\r
== (IA32_MAP_ATTRIBUTE_ATTRIBUTES (Attribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask)))\r
{\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
- PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute);\r
+ PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute, &AllOneMask);\r
\r
RegionLength = REGION_LENGTH (Level);\r
PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry->Pnle);\r
SubOffset += RegionLength;\r
}\r
}\r
+ } else {\r
+ //\r
+ // It's a non-leaf entry\r
+ //\r
+ ChildAttribute.Uint64 = 0;\r
+ ChildMask.Uint64 = 0;\r
+\r
+ //\r
+ // If the inheritable attributes in the parent entry conflicts with the requested attributes,\r
+ // let the child entries take the parent attributes and\r
+ // loosen the attribute in the parent entry\r
+ // E.g.: when PDPTE[0].ReadWrite = 0 but caller wants to map [0-2MB] as ReadWrite = 1 (PDE[0].ReadWrite = 1)\r
+ // we need to change PDPTE[0].ReadWrite = 1 and let all PDE[0-255].ReadWrite = 0 in this step.\r
+ // when PDPTE[0].Nx = 1 but caller wants to map [0-2MB] as Nx = 0 (PDT[0].Nx = 0)\r
+ // we need to change PDPTE[0].Nx = 0 and let all PDE[0-255].Nx = 1 in this step.\r
+ if ((ParentPagingEntry->Pnle.Bits.Present == 0) && (Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) {\r
+ if (Modify) {\r
+ ParentPagingEntry->Pnle.Bits.Present = 1;\r
+ }\r
+\r
+ ChildAttribute.Bits.Present = 0;\r
+ ChildMask.Bits.Present = 1;\r
+ }\r
+\r
+ if ((ParentPagingEntry->Pnle.Bits.ReadWrite == 0) && (Mask->Bits.ReadWrite == 1) && (Attribute->Bits.ReadWrite == 1)) {\r
+ if (Modify) {\r
+ ParentPagingEntry->Pnle.Bits.ReadWrite = 1;\r
+ }\r
+\r
+ ChildAttribute.Bits.ReadWrite = 0;\r
+ ChildMask.Bits.ReadWrite = 1;\r
+ }\r
+\r
+ if ((ParentPagingEntry->Pnle.Bits.UserSupervisor == 0) && (Mask->Bits.UserSupervisor == 1) && (Attribute->Bits.UserSupervisor == 1)) {\r
+ if (Modify) {\r
+ ParentPagingEntry->Pnle.Bits.UserSupervisor = 1;\r
+ }\r
+\r
+ ChildAttribute.Bits.UserSupervisor = 0;\r
+ ChildMask.Bits.UserSupervisor = 1;\r
+ }\r
+\r
+ if ((ParentPagingEntry->Pnle.Bits.Nx == 1) && (Mask->Bits.Nx == 1) && (Attribute->Bits.Nx == 0)) {\r
+ if (Modify) {\r
+ ParentPagingEntry->Pnle.Bits.Nx = 0;\r
+ }\r
+\r
+ ChildAttribute.Bits.Nx = 1;\r
+ ChildMask.Bits.Nx = 1;\r
+ }\r
+\r
+ if (ChildMask.Uint64 != 0) {\r
+ if (Modify) {\r
+ //\r
+ // Update child entries to use restrictive attribute inherited from parent.\r
+ // e.g.: Set PDE[0-255].ReadWrite = 0\r
+ //\r
+ PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&ParentPagingEntry->Pnle);\r
+ for (Index = 0; Index < 512; Index++) {\r
+ if (PagingEntry[Index].Pce.Present == 0) {\r
+ continue;\r
+ }\r
+\r
+ if (IsPle (&PagingEntry[Index], Level)) {\r
+ PageTableLibSetPle (Level - 1, &PagingEntry[Index], 0, &ChildAttribute, &ChildMask);\r
+ } else {\r
+ PageTableLibSetPnle (&PagingEntry[Index].Pnle, &ChildAttribute, &ChildMask);\r
+ }\r
+ }\r
+ }\r
+ }\r
}\r
\r
//\r
RegionMask = RegionLength - 1;\r
RegionStart = (LinearAddress + Offset) & ~RegionMask;\r
\r
+ ParentAttribute->Uint64 = PageTableLibGetPnleMapAttribute (&ParentPagingEntry->Pnle, ParentAttribute);\r
+\r
//\r
// Apply the attribute.\r
//\r
//\r
Status = PageTableLibMapInLevel (\r
CurrentPagingEntry,\r
+ ParentAttribute,\r
Modify,\r
Buffer,\r
BufferSize,\r
IN IA32_MAP_ATTRIBUTE *Mask\r
)\r
{\r
- RETURN_STATUS Status;\r
- IA32_PAGING_ENTRY TopPagingEntry;\r
- INTN RequiredSize;\r
- UINT64 MaxLinearAddress;\r
- UINTN MaxLevel;\r
- UINTN MaxLeafLevel;\r
+ RETURN_STATUS Status;\r
+ IA32_PAGING_ENTRY TopPagingEntry;\r
+ INTN RequiredSize;\r
+ UINT64 MaxLinearAddress;\r
+ UINTN MaxLevel;\r
+ UINTN MaxLeafLevel;\r
+ IA32_MAP_ATTRIBUTE ParentAttribute;\r
\r
if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) {\r
//\r
\r
TopPagingEntry.Uintn = *PageTable;\r
if (TopPagingEntry.Uintn != 0) {\r
- TopPagingEntry.Pce.Present = 1;\r
+ TopPagingEntry.Pce.Present = 1;\r
+ TopPagingEntry.Pce.ReadWrite = 1;\r
+ TopPagingEntry.Pce.UserSupervisor = 1;\r
+ TopPagingEntry.Pce.Nx = 0;\r
}\r
\r
+ ParentAttribute.Uint64 = 0;\r
+ ParentAttribute.Bits.PageTableBaseAddress = 1;\r
+ ParentAttribute.Bits.Present = 1;\r
+ ParentAttribute.Bits.ReadWrite = 1;\r
+ ParentAttribute.Bits.UserSupervisor = 1;\r
+ ParentAttribute.Bits.Nx = 0;\r
+\r
//\r
// Query the required buffer size without modifying the page table.\r
//\r
RequiredSize = 0;\r
Status = PageTableLibMapInLevel (\r
&TopPagingEntry,\r
+ &ParentAttribute,\r
FALSE,\r
NULL,\r
&RequiredSize,\r
//\r
// Update the page table when the supplied buffer is sufficient.\r
//\r
+ ParentAttribute.Uint64 = 0;\r
+ ParentAttribute.Bits.PageTableBaseAddress = 1;\r
+ ParentAttribute.Bits.Present = 1;\r
+ ParentAttribute.Bits.ReadWrite = 1;\r
+ ParentAttribute.Bits.UserSupervisor = 1;\r
+ ParentAttribute.Bits.Nx = 0;\r
+\r
Status = PageTableLibMapInLevel (\r
&TopPagingEntry,\r
+ &ParentAttribute,\r
TRUE,\r
Buffer,\r
(INTN *)BufferSize,\r