/** @file\r
* File managing the MMU for ARMv7 architecture\r
*\r
-* Copyright (c) 2011, ARM Limited. All rights reserved.\r
-* \r
-* This program and the accompanying materials \r
-* are licensed and made available under the terms and conditions of the BSD License \r
-* which accompanies this distribution. The full text of the license may be found at \r
-* http://opensource.org/licenses/bsd-license.php \r
+* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution. The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
*\r
**/\r
\r
-#include <Uefi.h> \r
+#include <Uefi.h>\r
#include <Chipset/ArmV7.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include "ArmV7Lib.h"\r
#include "ArmLibPrivate.h"\r
\r
+UINT32\r
+ConvertSectionAttributesToPageAttributes (\r
+ IN UINT32 SectionAttributes,\r
+ IN BOOLEAN IsLargePage\r
+ )\r
+{\r
+ UINT32 PageAttributes;\r
+\r
+ PageAttributes = 0;\r
+ PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (SectionAttributes, IsLargePage);\r
+ PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (SectionAttributes);\r
+ PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN (SectionAttributes, IsLargePage);\r
+ PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG (SectionAttributes);\r
+ PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S (SectionAttributes);\r
+\r
+ return PageAttributes;\r
+}\r
+\r
+STATIC\r
VOID\r
PopulateLevel2PageTable (\r
IN UINT32 *SectionEntry,\r
IN UINT32 PhysicalBase,\r
IN UINT32 RemainLength,\r
IN ARM_MEMORY_REGION_ATTRIBUTES Attributes\r
- ) {\r
+ )\r
+{\r
UINT32* PageEntry;\r
UINT32 Pages;\r
UINT32 Index;\r
\r
switch (Attributes) {\r
case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK:\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK:\r
PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_BACK;\r
break;\r
case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH:\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH:\r
PageAttributes = TT_DESCRIPTOR_PAGE_WRITE_THROUGH;\r
break;\r
case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE:\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_DEVICE:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE:\r
PageAttributes = TT_DESCRIPTOR_PAGE_DEVICE;\r
break;\r
case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED:\r
PageAttributes = TT_DESCRIPTOR_PAGE_UNCACHED;\r
break;\r
default:\r
TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK;\r
\r
// Translate the Section Descriptor into Page Descriptor\r
- SectionDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE;\r
- SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(*SectionEntry,0);\r
- SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(*SectionEntry);\r
- SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(*SectionEntry,0);\r
- SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(*SectionEntry);\r
- SectionDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S(*SectionEntry);\r
+ SectionDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (*SectionEntry, FALSE);\r
\r
BaseSectionAddress = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(*SectionEntry);\r
\r
\r
}\r
\r
+STATIC\r
VOID\r
FillTranslationTable (\r
IN UINT32 *TranslationTable,\r
UINT32 Attributes;\r
UINT32 PhysicalBase = MemoryRegion->PhysicalBase;\r
UINT32 RemainLength = MemoryRegion->Length;\r
- \r
+\r
ASSERT(MemoryRegion->Length > 0);\r
\r
switch (MemoryRegion->Attributes) {\r
case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:\r
Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);\r
break;\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK:\r
Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(1);\r
break;\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH:\r
Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH(1);\r
break;\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_DEVICE:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE:\r
Attributes = TT_DESCRIPTOR_SECTION_DEVICE(1);\r
break;\r
- case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED:\r
+ case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED:\r
Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(1);\r
break;\r
default:\r
Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);\r
break;\r
}\r
- \r
+\r
// Get the first section entry for this mapping\r
SectionEntry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase);\r
\r
PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;\r
} else {\r
// Case: Physical address aligned on the Section Size (1MB) && the length does not fill a section\r
- PopulateLevel2PageTable(SectionEntry++,PhysicalBase,RemainLength,MemoryRegion->Attributes);\r
+ PopulateLevel2PageTable (SectionEntry++, PhysicalBase, RemainLength, MemoryRegion->Attributes);\r
\r
// It must be the last entry\r
break;\r
}\r
} else {\r
// Case: Physical address NOT aligned on the Section Size (1MB)\r
- PopulateLevel2PageTable(SectionEntry++,PhysicalBase,RemainLength,MemoryRegion->Attributes);\r
+ PopulateLevel2PageTable (SectionEntry++, PhysicalBase, RemainLength, MemoryRegion->Attributes);\r
// Aligned the address\r
PhysicalBase = (PhysicalBase + TT_DESCRIPTOR_SECTION_SIZE) & ~(TT_DESCRIPTOR_SECTION_SIZE-1);\r
\r
}\r
}\r
\r
-VOID\r
+RETURN_STATUS\r
EFIAPI\r
ArmConfigureMmu (\r
IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable,\r
- OUT VOID **TranslationTableBase OPTIONAL,\r
- OUT UINTN *TranslationTableSize OPTIONAL\r
+ OUT VOID **TranslationTableBase OPTIONAL,\r
+ OUT UINTN *TranslationTableSize OPTIONAL\r
)\r
{\r
- UINTN TranslationTable;\r
+ VOID* TranslationTable;\r
ARM_MEMORY_REGION_ATTRIBUTES TranslationTableAttribute;\r
UINT32 TTBRAttributes;\r
\r
// Allocate pages for translation table.\r
- TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SECTION_SIZE + TRANSLATION_TABLE_SECTION_ALIGNMENT));\r
- TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK;\r
+ TranslationTable = AllocatePages (EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_SECTION_SIZE + TRANSLATION_TABLE_SECTION_ALIGNMENT));\r
+ if (TranslationTable == NULL) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
+ }\r
+ TranslationTable = (VOID*)(((UINTN)TranslationTable + TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK);\r
\r
if (TranslationTableBase != NULL) {\r
- *TranslationTableBase = (VOID *)TranslationTable;\r
+ *TranslationTableBase = TranslationTable;\r
}\r
- \r
- if (TranslationTableBase != NULL) {\r
+\r
+ if (TranslationTableSize != NULL) {\r
*TranslationTableSize = TRANSLATION_TABLE_SECTION_SIZE;\r
}\r
\r
- ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);\r
-\r
- ArmCleanInvalidateDataCache();\r
- ArmInvalidateInstructionCache();\r
- ArmInvalidateTlb();\r
-\r
- ArmDisableDataCache();\r
- ArmDisableInstructionCache();\r
- ArmDisableMmu();\r
+ ZeroMem (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);\r
\r
- // Make sure nothing sneaked into the cache\r
- ArmCleanInvalidateDataCache();\r
- ArmInvalidateInstructionCache();\r
-\r
- TranslationTableAttribute = (ARM_MEMORY_REGION_ATTRIBUTES)0;\r
+ // By default, mark the translation table as belonging to a uncached region\r
+ TranslationTableAttribute = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;\r
while (MemoryTable->Length != 0) {\r
// Find the memory attribute for the Translation Table\r
- if ((TranslationTable >= MemoryTable->PhysicalBase) && (TranslationTable < MemoryTable->PhysicalBase + MemoryTable->Length)) {\r
+ if (((UINTN)TranslationTable >= MemoryTable->PhysicalBase) && ((UINTN)TranslationTable <= MemoryTable->PhysicalBase - 1 + MemoryTable->Length)) {\r
TranslationTableAttribute = MemoryTable->Attributes;\r
}\r
\r
- FillTranslationTable ((VOID *)TranslationTable, MemoryTable);\r
+ FillTranslationTable (TranslationTable, MemoryTable);\r
MemoryTable++;\r
}\r
\r
// Translate the Memory Attributes into Translation Table Register Attributes\r
- if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED) || \r
- (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED)) {\r
+ if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED) ||\r
+ (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED)) {\r
TTBRAttributes = TTBR_NON_CACHEABLE;\r
- } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) || \r
- (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK)) {\r
+ } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) ||\r
+ (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK)) {\r
TTBRAttributes = TTBR_WRITE_BACK_ALLOC;\r
- } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH) || \r
- (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH)) {\r
+ } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH) ||\r
+ (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH)) {\r
TTBRAttributes = TTBR_WRITE_THROUGH_NO_ALLOC;\r
} else {\r
- //TODO: We should raise an error here\r
- TTBRAttributes = TTBR_NON_CACHEABLE;\r
+ ASSERT (0); // No support has been found for the attributes of the memory region that the translation table belongs to.\r
+ return RETURN_UNSUPPORTED;\r
}\r
\r
- ArmSetTTBR0 ((VOID *)(UINTN)((TranslationTable & 0xFFFFC000) | (TTBRAttributes & 0x7F)));\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
ArmSetDomainAccessControl (DOMAIN_ACCESS_CONTROL_NONE(15) |\r
DOMAIN_ACCESS_CONTROL_NONE(14) |\r
DOMAIN_ACCESS_CONTROL_NONE(13) |\r
DOMAIN_ACCESS_CONTROL_NONE( 2) |\r
DOMAIN_ACCESS_CONTROL_NONE( 1) |\r
DOMAIN_ACCESS_CONTROL_MANAGER(0));\r
- \r
+\r
ArmEnableInstructionCache();\r
ArmEnableDataCache();\r
ArmEnableMmu();\r
+ return RETURN_SUCCESS;\r
}\r