diff --git a/ArmPkg/Drivers/CpuDxe/Mmu.c b/ArmPkg/Drivers/CpuDxe/Mmu.c index 9ba5c83448..89bf88ed3b 100644 --- a/ArmPkg/Drivers/CpuDxe/Mmu.c +++ b/ArmPkg/Drivers/CpuDxe/Mmu.c @@ -88,6 +88,70 @@ SectionToGcdAttributes ( return EFI_SUCCESS; } +EFI_STATUS +PageToGcdAttributes ( + IN UINT32 PageAttributes, + OUT UINT64 *GcdAttributes + ) +{ + *GcdAttributes = 0; + + // determine cacheability attributes + switch(PageAttributes & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) { + case TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED: + *GcdAttributes |= EFI_MEMORY_UC; + break; + case TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE: + *GcdAttributes |= EFI_MEMORY_UC; + break; + case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC: + *GcdAttributes |= EFI_MEMORY_WT; + break; + case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC: + *GcdAttributes |= EFI_MEMORY_WB; + break; + case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE: + *GcdAttributes |= EFI_MEMORY_WC; + break; + case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC: + *GcdAttributes |= EFI_MEMORY_WB; + break; + case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE: + *GcdAttributes |= EFI_MEMORY_UC; + break; + default: + return EFI_UNSUPPORTED; + } + + // determine protection attributes + switch(PageAttributes & TT_DESCRIPTOR_PAGE_AP_MASK) { + case TT_DESCRIPTOR_PAGE_AP_NO_NO: // no read, no write + //*GcdAttributes |= EFI_MEMORY_WP | EFI_MEMORY_RP; + break; + + case TT_DESCRIPTOR_PAGE_AP_RW_NO: + case TT_DESCRIPTOR_PAGE_AP_RW_RW: + // normal read/write access, do not add additional attributes + break; + + // read only cases map to write-protect + case TT_DESCRIPTOR_PAGE_AP_RO_NO: + case TT_DESCRIPTOR_PAGE_AP_RO_RO: + *GcdAttributes |= EFI_MEMORY_WP; + break; + + default: + return EFI_UNSUPPORTED; + } + + // now process eXectue Never attribute + if ((PageAttributes & TT_DESCRIPTOR_PAGE_XN_MASK) != 0 ) { + *GcdAttributes |= EFI_MEMORY_XP; + } + + return EFI_SUCCESS; +} + /** Searches memory descriptors covered by given memory range. @@ -215,6 +279,81 @@ SetGcdMemorySpaceAttributes ( return EFI_SUCCESS; } +EFI_STATUS +SyncCacheConfigPage ( + IN UINT32 SectionIndex, + IN UINT32 FirstLevelDescriptor, + IN UINTN NumberOfDescriptors, + IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, + IN OUT EFI_PHYSICAL_ADDRESS *NextRegionBase, + IN OUT UINT64 *NextRegionLength, + IN OUT UINT32 *NextSectionAttributes + ) +{ + EFI_STATUS Status; + UINT32 i; + volatile ARM_PAGE_TABLE_ENTRY *SecondLevelTable; + UINT32 NextPageAttributes = 0; + UINT32 PageAttributes = 0; + UINT32 BaseAddress; + UINT64 GcdAttributes; + + // Get the Base Address from FirstLevelDescriptor; + BaseAddress = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(SectionIndex << TT_DESCRIPTOR_SECTION_BASE_SHIFT); + + // Convert SectionAttributes into PageAttributes + NextPageAttributes = + TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(*NextSectionAttributes,0) | + TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(*NextSectionAttributes); + + // obtain page table base + SecondLevelTable = (ARM_PAGE_TABLE_ENTRY *)(FirstLevelDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK); + + for (i=0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) { + if ((SecondLevelTable[i] & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) { + // extract attributes (cacheability and permissions) + PageAttributes = SecondLevelTable[i] & (TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK | TT_DESCRIPTOR_PAGE_AP_MASK); + + if (NextPageAttributes == 0) { + // start on a new region + *NextRegionLength = 0; + *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT); + NextPageAttributes = PageAttributes; + } else if (PageAttributes != NextPageAttributes) { + // Convert Section Attributes into GCD Attributes + Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes); + ASSERT_EFI_ERROR (Status); + + // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK) + SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes); + + // start on a new region + *NextRegionLength = 0; + *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT); + NextPageAttributes = PageAttributes; + } + } else if (NextPageAttributes != 0) { + // Convert Page Attributes into GCD Attributes + Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes); + ASSERT_EFI_ERROR (Status); + + // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK) + SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes); + + *NextRegionLength = 0; + *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT); + NextPageAttributes = 0; + } + *NextRegionLength += TT_DESCRIPTOR_PAGE_SIZE; + } + + // Convert back PageAttributes into SectionAttributes + *NextSectionAttributes = + TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY(NextPageAttributes,0) | + TT_DESCRIPTOR_CONVERT_TO_SECTION_AP(NextPageAttributes); + + return EFI_SUCCESS; +} EFI_STATUS SyncCacheConfig ( @@ -223,12 +362,11 @@ SyncCacheConfig ( { EFI_STATUS Status; UINT32 i; - UINT32 Descriptor; - UINT32 SectionAttributes; EFI_PHYSICAL_ADDRESS NextRegionBase; UINT64 NextRegionLength; + UINT32 NextSectionAttributes = 0; + UINT32 SectionAttributes = 0; UINT64 GcdAttributes; - UINT32 NextRegionAttributes = 0; volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; UINTN NumberOfDescriptors; EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; @@ -256,46 +394,71 @@ SyncCacheConfig ( // obtain page table base FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ()); + // Get the first region + NextSectionAttributes = FirstLevelTable[0] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK); // iterate through each 1MB descriptor NextRegionBase = NextRegionLength = 0; - for (i=0; i< TRANSLATION_TABLE_SECTION_COUNT; i++) { + for (i=0; i < TRANSLATION_TABLE_SECTION_COUNT; i++) { + if ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) { + // extract attributes (cacheability and permissions) + SectionAttributes = FirstLevelTable[i] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK); - // obtain existing descriptor and make sure it contains a valid Base Address even if it is a fault section - Descriptor = FirstLevelTable[i] | TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT); - - // extract attributes (cacheability and permissions) - SectionAttributes = Descriptor & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK); - - // do we already have an existing region (or are we about to finish)? - // Skip the first entry, and make sure we close on the last entry - if ( (NextRegionLength > 0) || (i == (TRANSLATION_TABLE_SECTION_COUNT-1)) ) { - // attributes are changing, update attributes in GCD - if (SectionAttributes != NextRegionAttributes) { - - // convert section entry attributes to GCD bitmask - Status = SectionToGcdAttributes (NextRegionAttributes, &GcdAttributes); + if (NextSectionAttributes == 0) { + // start on a new region + NextRegionLength = 0; + NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT); + NextSectionAttributes = SectionAttributes; + } else if (SectionAttributes != NextSectionAttributes) { + // Convert Section Attributes into GCD Attributes + Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes); ASSERT_EFI_ERROR (Status); // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK) SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes); - // start on a new region NextRegionLength = 0; - NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(Descriptor); + NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT); + NextSectionAttributes = SectionAttributes; } + NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE; + } else if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(FirstLevelTable[i])) { + Status = SyncCacheConfigPage ( + i,FirstLevelTable[i], + &NumberOfDescriptors, &MemorySpaceMap, + &NextRegionBase,&NextRegionLength,&NextSectionAttributes); + ASSERT_EFI_ERROR (Status); + } else { + // We do not support yet 16MB sections + ASSERT ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) != TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION); + + // start on a new region + if (NextSectionAttributes != 0) { + // Convert Section Attributes into GCD Attributes + Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes); + ASSERT_EFI_ERROR (Status); + + // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK) + SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes); + + NextRegionLength = 0; + NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT); + NextSectionAttributes = 0; + } + NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE; } - - // starting a new region? - if (NextRegionLength == 0) { - NextRegionAttributes = SectionAttributes; - } - - NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE; - } // section entry loop + if (NextSectionAttributes != 0) { + // Convert Section Attributes into GCD Attributes + Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes); + ASSERT_EFI_ERROR (Status); + + // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK) + SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes); + } + return EFI_SUCCESS; } @@ -591,7 +754,7 @@ ConvertSectionToPages ( UINT32 SectionDescriptor; UINT32 PageTableDescriptor; UINT32 PageDescriptor; - UINT32 i; + UINT32 Index; volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; volatile ARM_PAGE_TABLE_ENTRY *PageTable; @@ -623,8 +786,8 @@ ConvertSectionToPages ( PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)(UINTN)PageTableAddr; // write the page table entries out - for (i=0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) { - PageTable[i] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (i << 12)) | PageDescriptor; + for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) { + PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (Index << 12)) | PageDescriptor; } // flush d-cache so descriptors make it back to uncached memory for subsequent table walks diff --git a/ArmPkg/Include/Chipset/ArmV7.h b/ArmPkg/Include/Chipset/ArmV7.h index b9d7430580..6a63cceabb 100644 --- a/ArmPkg/Include/Chipset/ArmV7.h +++ b/ArmPkg/Include/Chipset/ArmV7.h @@ -122,6 +122,8 @@ #define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 12) | (1UL << 3) | (1UL << 2)) #define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 12) | (0UL << 3) | (0UL << 2)) +#define TT_DESCRIPTOR_PAGE_SIZE (0x00001000) + #define TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK ((3UL << 6) | (1UL << 3) | (1UL << 2)) #define TT_DESCRIPTOR_PAGE_CACHEABLE_MASK (1UL << 3) #define TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 6) | (0UL << 3) | (0UL << 2)) @@ -151,6 +153,13 @@ (((Desc) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) & TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_MASK): \ (((((Desc) & (0x3 << 12)) >> 6) | (Desc & (0x3 << 2))))) +#define TT_DESCRIPTOR_CONVERT_TO_SECTION_AP(Desc) ((((Desc) & TT_DESCRIPTOR_PAGE_AP_MASK) << 6) & TT_DESCRIPTOR_SECTION_AP_MASK) + +#define TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY(Desc,IsLargePage) (IsLargePage? \ + (((Desc) & TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_MASK) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK): \ + (((((Desc) & (0x3 << 6)) << 6) | (Desc & (0x3 << 2))))) + + #define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5) #define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0x0FUL) << 5) @@ -193,6 +202,27 @@ TT_DESCRIPTOR_SECTION_AP_RW_RW | \ TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE) +#define TT_DESCRIPTOR_PAGE_WRITE_BACK (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ + TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ + TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ + TT_DESCRIPTOR_PAGE_AP_RW_RW | \ + TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC) +#define TT_DESCRIPTOR_PAGE_WRITE_THROUGH (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ + TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ + TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ + TT_DESCRIPTOR_PAGE_AP_RW_RW | \ + TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC) +#define TT_DESCRIPTOR_PAGE_DEVICE (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ + TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ + TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ + TT_DESCRIPTOR_PAGE_AP_RW_RW | \ + TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE) +#define TT_DESCRIPTOR_PAGE_UNCACHED (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ + TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ + TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ + TT_DESCRIPTOR_PAGE_AP_RW_RW | \ + TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE) + // Cortex A9 feature bit definitions #define A9_FEATURE_PARITY (1<<9) #define A9_FEATURE_AOW (1<<8) diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c index 9bb3c2690f..3ba66d62bf 100644 --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c @@ -19,21 +19,119 @@ #include #include #include +#include #include "ArmV7Lib.h" #include "ArmLibPrivate.h" +VOID +PopulateLevel2PageTable ( + IN UINT32 *SectionEntry, + IN UINT32 PhysicalBase, + IN UINT32 RemainLength, + IN ARM_MEMORY_REGION_ATTRIBUTES Attributes + ) { + UINT32* PageEntry; + UINT32 Pages; + UINT32 Index; + UINT32 PageAttributes; + UINT32 SectionDescriptor; + UINT32 TranslationTable; + UINT32 BaseSectionAddress; + + switch (Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: + case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK: + PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_BACK; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: + case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH: + PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_THROUGH; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE: + case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_DEVICE: + PageAttributes = TT_DESCRIPTOR_PAGE_DEVICE; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED: + case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED: + PageAttributes = TT_DESCRIPTOR_PAGE_UNCACHED; + break; + default: + PageAttributes = TT_DESCRIPTOR_PAGE_UNCACHED; + break; + } + + // Check if the Section Entry has already been populated. Otherwise attach a + // Level 2 Translation Table to it + if (*SectionEntry != 0) { + // The entry must be a page table. Otherwise it exists an overlapping in the memory map + if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(*SectionEntry)) { + TranslationTable = *SectionEntry & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK; + } else if ((*SectionEntry & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) { + // Case where a virtual memory map descriptor overlapped a section entry + + // Allocate a Level2 Page Table for this Section + TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT)); + TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK; + + // Translate the Section Descriptor into Page Descriptor + SectionDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE; + SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(*SectionEntry,0); + SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(*SectionEntry); + SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(*SectionEntry,0); + SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(*SectionEntry); + SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S(*SectionEntry); + + BaseSectionAddress = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(*SectionEntry); + + // Populate the new Level2 Page Table for the section + PageEntry = (UINT32*)TranslationTable; + for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) { + PageEntry[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseSectionAddress + (Index << 12)) | SectionDescriptor; + } + + // Overwrite the section entry to point to the new Level2 Translation Table + *SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | + (IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE(Attributes) ? (1 << 3) : 0) | + TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE; + } else { + // We do not support the other section type (16MB Section) + ASSERT(0); + return; + } + } else { + TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT)); + TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK; + + ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_PAGE_SIZE); + + *SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | + (IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE(Attributes) ? (1 << 3) : 0) | + TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE; + } + + PageEntry = ((UINT32 *)(TranslationTable) + ((PhysicalBase & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT)); + Pages = RemainLength / TT_DESCRIPTOR_PAGE_SIZE; + + for (Index = 0; Index < Pages; Index++) { + *PageEntry++ = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(PhysicalBase) | PageAttributes; + PhysicalBase += TT_DESCRIPTOR_PAGE_SIZE; + } + +} + VOID FillTranslationTable ( IN UINT32 *TranslationTable, IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion ) { - UINT32 *Entry; - UINTN Sections; - UINTN Index; + UINT32 *SectionEntry; UINT32 Attributes; UINT32 PhysicalBase = MemoryRegion->PhysicalBase; + UINT32 RemainLength = MemoryRegion->Length; + ASSERT(MemoryRegion->Length > 0); + switch (MemoryRegion->Attributes) { case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(0); @@ -64,12 +162,34 @@ FillTranslationTable ( break; } - Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); - Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE; - - for (Index = 0; Index < Sections; Index++) { - *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; - PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + // Get the first section entry for this mapping + SectionEntry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); + + while (RemainLength != 0) { + if (PhysicalBase % TT_DESCRIPTOR_SECTION_SIZE == 0) { + if (RemainLength >= TT_DESCRIPTOR_SECTION_SIZE) { + // Case: Physical address aligned on the Section Size (1MB) && the length is greater than the Section Size + *SectionEntry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; + PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + } else { + // Case: Physical address aligned on the Section Size (1MB) && the length does not fill a section + PopulateLevel2PageTable(SectionEntry++,PhysicalBase,RemainLength,MemoryRegion->Attributes); + + // It must be the last entry + break; + } + } else { + // Case: Physical address NOT aligned on the Section Size (1MB) + PopulateLevel2PageTable(SectionEntry++,PhysicalBase,RemainLength,MemoryRegion->Attributes); + // Aligned the address + PhysicalBase = (PhysicalBase + TT_DESCRIPTOR_SECTION_SIZE) & ~(TT_DESCRIPTOR_SECTION_SIZE-1); + + // If it is the last entry + if (RemainLength < TT_DESCRIPTOR_SECTION_SIZE) { + break; + } + } + RemainLength -= TT_DESCRIPTOR_SECTION_SIZE; } } @@ -111,7 +231,7 @@ ArmConfigureMmu ( ArmCleanInvalidateDataCache(); ArmInvalidateInstructionCache(); - TranslationTableAttribute = 0; + TranslationTableAttribute = (ARM_MEMORY_REGION_ATTRIBUTES)0; while (MemoryTable->Length != 0) { // Find the memory attribute for the Translation Table if ((TranslationTable >= MemoryTable->PhysicalBase) && (TranslationTable < MemoryTable->PhysicalBase + MemoryTable->Length)) { diff --git a/ArmPlatformPkg/Library/EblCmdLib/EblCmdMmu.c b/ArmPlatformPkg/Library/EblCmdLib/EblCmdMmu.c index fdbdd906db..fba4741699 100644 --- a/ArmPlatformPkg/Library/EblCmdLib/EblCmdMmu.c +++ b/ArmPlatformPkg/Library/EblCmdLib/EblCmdMmu.c @@ -35,27 +35,6 @@ TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED) // Small Page -#define TT_DESCRIPTOR_PAGE_WRITE_BACK (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ - TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ - TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ - TT_DESCRIPTOR_PAGE_AP_RW_RW | \ - TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC) -#define TT_DESCRIPTOR_PAGE_WRITE_THROUGH (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ - TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ - TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ - TT_DESCRIPTOR_PAGE_AP_RW_RW | \ - TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC) -#define TT_DESCRIPTOR_PAGE_DEVICE (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ - TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ - TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ - TT_DESCRIPTOR_PAGE_AP_RW_RW | \ - TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE) -#define TT_DESCRIPTOR_PAGE_UNCACHED (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ - TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ - TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \ - TT_DESCRIPTOR_PAGE_AP_RW_RW | \ - TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE) - #define TT_DESCRIPTOR_PAGE_STRONGLY_ORDER (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \ TT_DESCRIPTOR_PAGE_NG_GLOBAL | \ TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \