\r
EFI_STATUS\r
UpdatePageEntries (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes,\r
- IN EFI_PHYSICAL_ADDRESS VirtualMask\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes,\r
+ IN EFI_PHYSICAL_ADDRESS VirtualMask,\r
+ OUT BOOLEAN *FlushTlbs OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
\r
// Re-read descriptor\r
Descriptor = FirstLevelTable[FirstLevelIdx];\r
+ if (FlushTlbs != NULL) {\r
+ *FlushTlbs = TRUE;\r
+ }\r
}\r
\r
// Obtain page table base address\r
\r
if (CurrentPageTableEntry != PageTableEntry) {\r
Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));\r
- if ((CurrentPageTableEntry & TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) == TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) {\r
- // The current section mapping is cacheable so Clean/Invalidate the MVA of the page\r
- // Note assumes switch(Attributes), not ARMv7 possibilities\r
- WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE);\r
- }\r
\r
// Only need to update if we are changing the entry\r
PageTable[PageTableIndex] = PageTableEntry;\r
ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);\r
+\r
+ // Clean/invalidate the cache for this page, but only\r
+ // if we are modifying the memory type attributes\r
+ if (((CurrentPageTableEntry ^ PageTableEntry) & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) != 0) {\r
+ WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE);\r
+ }\r
}\r
\r
Status = EFI_SUCCESS;\r
// has this descriptor already been coverted to pages?\r
if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {\r
// forward this 1MB range to page table function instead\r
- Status = UpdatePageEntries ((FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT, TT_DESCRIPTOR_SECTION_SIZE, Attributes, VirtualMask);\r
+ Status = UpdatePageEntries (\r
+ (FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT,\r
+ TT_DESCRIPTOR_SECTION_SIZE,\r
+ Attributes,\r
+ VirtualMask,\r
+ NULL);\r
} else {\r
// still a section entry\r
\r
\r
if (CurrentDescriptor != Descriptor) {\r
Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
- if ((CurrentDescriptor & TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) == TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) {\r
- // The current section mapping is cacheable so Clean/Invalidate the MVA of the section\r
- // Note assumes switch(Attributes), not ARMv7 possabilities\r
- WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);\r
- }\r
\r
// Only need to update if we are changing the descriptor\r
FirstLevelTable[FirstLevelIdx + i] = Descriptor;\r
ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);\r
+\r
+ // Clean/invalidate the cache for this section, but only\r
+ // if we are modifying the memory type attributes\r
+ if (((CurrentDescriptor ^ Descriptor) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) != 0) {\r
+ WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);\r
+ }\r
}\r
\r
Status = EFI_SUCCESS;\r
{\r
EFI_STATUS Status;\r
UINT64 ChunkLength;\r
+ BOOLEAN FlushTlbs;\r
\r
if (Length == 0) {\r
return EFI_SUCCESS;\r
return EFI_SUCCESS;\r
}\r
\r
+ FlushTlbs = FALSE;\r
while (Length > 0) {\r
if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) &&\r
Length >= TT_DESCRIPTOR_SECTION_SIZE) {\r
\r
Status = UpdateSectionEntries (BaseAddress, ChunkLength, Attributes,\r
VirtualMask);\r
+\r
+ FlushTlbs = TRUE;\r
} else {\r
\r
//\r
BaseAddress, ChunkLength, Attributes));\r
\r
Status = UpdatePageEntries (BaseAddress, ChunkLength, Attributes,\r
- VirtualMask);\r
+ VirtualMask, &FlushTlbs);\r
}\r
\r
if (EFI_ERROR (Status)) {\r
Length -= ChunkLength;\r
}\r
\r
- // Flush d-cache so descriptors make it back to uncached memory for subsequent table walks\r
- // flush and invalidate pages\r
- //TODO: Do we really need to invalidate the caches everytime we change the memory attributes ?\r
- ArmCleanInvalidateDataCache ();\r
-\r
- ArmInvalidateInstructionCache ();\r
-\r
- // Invalidate all TLB entries so changes are synced\r
- ArmInvalidateTlb ();\r
-\r
+ if (FlushTlbs) {\r
+ ArmInvalidateTlb ();\r
+ }\r
return Status;\r
}\r
\r