diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c index 6d21a2e41d..1ce200c43c 100644 --- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c @@ -251,6 +251,16 @@ UpdateRegionMappingRecursive ( ASSERT (Level < 3); if (!IsTableEntry (*Entry, Level)) { + // + // If the region we are trying to map is already covered by a block + // entry with the right attributes, don't bother splitting it up. + // + if (IsBlockEntry (*Entry, Level) && + ((*Entry & TT_ATTRIBUTES_MASK & ~AttributeClearMask) == AttributeSetMask)) + { + continue; + } + // // No table entry exists yet, so we need to allocate a page table // for the next level. diff --git a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c index 247cf87bf3..299d38ad07 100644 --- a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c +++ b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c @@ -170,6 +170,17 @@ UpdatePageEntries ( // Does this descriptor need to be converted from section entry to 4K pages? if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (Descriptor)) { + // + // If the section mapping covers the requested region with the expected + // attributes, splitting it is unnecessary, and should be avoided as it + // may result in unbounded recursion when using a strict NX policy. + // + if ((EntryValue & ~TT_DESCRIPTOR_PAGE_TYPE_MASK & EntryMask) == + (ConvertSectionAttributesToPageAttributes (Descriptor) & EntryMask)) + { + continue; + } + Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT); if (EFI_ERROR (Status)) { // Exit for loop