]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c
ArmPkg/ArmMmuLib ARM: cache-invalidate initial page table entries
[mirror_edk2.git] / ArmPkg / Library / ArmMmuLib / Arm / ArmMmuLibCore.c
index e882e6e2009c85ab53261a783190c01bb600c793..11a1e704beabec023077a859da6703db8849f00b 100644 (file)
@@ -147,6 +147,13 @@ PopulateLevel2PageTable (
 \r
       BaseSectionAddress = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(*SectionEntry);\r
 \r
+      //\r
+      // Make sure we are not inadvertently hitting in the caches\r
+      // when populating the page tables\r
+      //\r
+      InvalidateDataCacheRange ((VOID *)TranslationTable,\r
+        TRANSLATION_TABLE_PAGE_SIZE);\r
+\r
       // Populate the new Level2 Page Table for the section\r
       PageEntry = (UINT32*)TranslationTable;\r
       for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {\r
@@ -166,6 +173,12 @@ PopulateLevel2PageTable (
     TranslationTable = (UINTN)AllocateAlignedPages (\r
                                 EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_PAGE_SIZE),\r
                                 TRANSLATION_TABLE_PAGE_ALIGNMENT);\r
+    //\r
+    // Make sure we are not inadvertently hitting in the caches\r
+    // when populating the page tables\r
+    //\r
+    InvalidateDataCacheRange ((VOID *)TranslationTable,\r
+      TRANSLATION_TABLE_PAGE_SIZE);\r
     ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_PAGE_SIZE);\r
 \r
     *SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) |\r
@@ -184,6 +197,13 @@ PopulateLevel2PageTable (
     PhysicalBase += TT_DESCRIPTOR_PAGE_SIZE;\r
   }\r
 \r
+  //\r
+  // Invalidate again to ensure that any line fetches that may have occurred\r
+  // [speculatively] since the previous invalidate are evicted again.\r
+  //\r
+  ArmDataMemoryBarrier ();\r
+  InvalidateDataCacheRange ((UINT32 *)TranslationTable + FirstPageOffset,\r
+    RemainLength / TT_DESCRIPTOR_PAGE_SIZE * sizeof (*PageEntry));\r
 }\r
 \r
 STATIC\r
@@ -258,7 +278,16 @@ FillTranslationTable (
         RemainLength >= TT_DESCRIPTOR_SECTION_SIZE) {\r
       // Case: Physical address aligned on the Section Size (1MB) && the length\r
       // is greater than the Section Size\r
-      *SectionEntry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;\r
+      *SectionEntry = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;\r
+\r
+      //\r
+      // Issue a DMB to ensure that the page table entry update made it to\r
+      // memory before we issue the invalidate, otherwise, a subsequent\r
+      // speculative fetch could observe the old value.\r
+      //\r
+      ArmDataMemoryBarrier ();\r
+      ArmInvalidateDataCacheEntryByMVA ((UINTN)SectionEntry++);\r
+\r
       PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;\r
       RemainLength -= TT_DESCRIPTOR_SECTION_SIZE;\r
     } else {\r
@@ -268,9 +297,17 @@ FillTranslationTable (
       // Case: Physical address aligned on the Section Size (1MB) && the length\r
       //       does not fill a section\r
       // Case: Physical address NOT aligned on the Section Size (1MB)\r
-      PopulateLevel2PageTable (SectionEntry++, PhysicalBase, PageMapLength,\r
+      PopulateLevel2PageTable (SectionEntry, PhysicalBase, PageMapLength,\r
         MemoryRegion->Attributes);\r
 \r
+      //\r
+      // Issue a DMB to ensure that the page table entry update made it to\r
+      // memory before we issue the invalidate, otherwise, a subsequent\r
+      // speculative fetch could observe the old value.\r
+      //\r
+      ArmDataMemoryBarrier ();\r
+      ArmInvalidateDataCacheEntryByMVA ((UINTN)SectionEntry++);\r
+\r
       // If it is the last entry\r
       if (RemainLength < TT_DESCRIPTOR_SECTION_SIZE) {\r
         break;\r
@@ -309,6 +346,11 @@ ArmConfigureMmu (
     *TranslationTableSize = TRANSLATION_TABLE_SECTION_SIZE;\r
   }\r
 \r
+  //\r
+  // Make sure we are not inadvertently hitting in the caches\r
+  // when populating the page tables\r
+  //\r
+  InvalidateDataCacheRange (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);\r
   ZeroMem (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);\r
 \r
   // By default, mark the translation table as belonging to a uncached region\r
@@ -350,18 +392,6 @@ ArmConfigureMmu (
     }\r
   }\r
 \r
-  ArmCleanInvalidateDataCache ();\r
-  ArmInvalidateInstructionCache ();\r
-\r
-  ArmDisableDataCache ();\r
-  ArmDisableInstructionCache();\r
-  // TLBs are also invalidated when calling ArmDisableMmu()\r
-  ArmDisableMmu ();\r
-\r
-  // Make sure nothing sneaked into the cache\r
-  ArmCleanInvalidateDataCache ();\r
-  ArmInvalidateInstructionCache ();\r
-\r
   ArmSetTTBR0 ((VOID *)(UINTN)(((UINTN)TranslationTable & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) | (TTBRAttributes & 0x7F)));\r
 \r
   //\r