X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ArmPkg%2FDrivers%2FCpuDxe%2FAArch64%2FMmu.c;fp=ArmPkg%2FDrivers%2FCpuDxe%2FAArch64%2FMmu.c;h=8997b7f61f8bca11c2fc393f7dc99edb8fb8fa8d;hp=838803aa9b4432b9e36cc851f077cbb65255dd49;hb=429309e0c6b74792d679681a8edd0d5ae0ff850c;hpb=7c2a6033c149625482a18cd51b65513c8fb8fe15 diff --git a/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c b/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c index 838803aa9b..8997b7f61f 100644 --- a/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c +++ b/ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c @@ -13,7 +13,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include "CpuDxe.h" -#define INVALID_ENTRY ((UINT32)~0) +#define INVALID_ENTRY ((UINT32)~0) #define MIN_T0SZ 16 #define BITS_PER_LEVEL 9 @@ -21,49 +21,52 @@ SPDX-License-Identifier: BSD-2-Clause-Patent STATIC VOID GetRootTranslationTableInfo ( - IN UINTN T0SZ, - OUT UINTN *RootTableLevel, - OUT UINTN *RootTableEntryCount + IN UINTN T0SZ, + OUT UINTN *RootTableLevel, + OUT UINTN *RootTableEntryCount ) { - *RootTableLevel = (T0SZ - MIN_T0SZ) / BITS_PER_LEVEL; - *RootTableEntryCount = TT_ENTRY_COUNT >> (T0SZ - MIN_T0SZ) % BITS_PER_LEVEL; + *RootTableLevel = (T0SZ - MIN_T0SZ) / BITS_PER_LEVEL; + *RootTableEntryCount = TT_ENTRY_COUNT >> (T0SZ - MIN_T0SZ) % BITS_PER_LEVEL; } STATIC UINT64 PageAttributeToGcdAttribute ( - IN UINT64 PageAttributes + IN UINT64 PageAttributes ) { UINT64 GcdAttributes; switch (PageAttributes & TT_ATTR_INDX_MASK) { - case TT_ATTR_INDX_DEVICE_MEMORY: - GcdAttributes = EFI_MEMORY_UC; - break; - case TT_ATTR_INDX_MEMORY_NON_CACHEABLE: - GcdAttributes = EFI_MEMORY_WC; - break; - case TT_ATTR_INDX_MEMORY_WRITE_THROUGH: - GcdAttributes = EFI_MEMORY_WT; - break; - case TT_ATTR_INDX_MEMORY_WRITE_BACK: - GcdAttributes = EFI_MEMORY_WB; - break; - default: - DEBUG ((DEBUG_ERROR, - "PageAttributeToGcdAttribute: PageAttributes:0x%lX not supported.\n", - PageAttributes)); - ASSERT (0); - // The Global Coherency Domain (GCD) value is defined as a bit set. - // Returning 0 means no attribute has been set. - GcdAttributes = 0; + case TT_ATTR_INDX_DEVICE_MEMORY: + GcdAttributes = EFI_MEMORY_UC; + break; + case TT_ATTR_INDX_MEMORY_NON_CACHEABLE: + GcdAttributes = EFI_MEMORY_WC; + break; + case TT_ATTR_INDX_MEMORY_WRITE_THROUGH: + GcdAttributes = EFI_MEMORY_WT; + break; + case TT_ATTR_INDX_MEMORY_WRITE_BACK: + GcdAttributes = EFI_MEMORY_WB; + break; + default: + DEBUG (( + DEBUG_ERROR, + "PageAttributeToGcdAttribute: PageAttributes:0x%lX not supported.\n", + PageAttributes + )); + ASSERT (0); + // The Global Coherency Domain (GCD) value is defined as a bit set. + // Returning 0 means no attribute has been set. + GcdAttributes = 0; } // Determine protection attributes if (((PageAttributes & TT_AP_MASK) == TT_AP_NO_RO) || - ((PageAttributes & TT_AP_MASK) == TT_AP_RO_RO)) { + ((PageAttributes & TT_AP_MASK) == TT_AP_RO_RO)) + { // Read only cases map to write-protect GcdAttributes |= EFI_MEMORY_RO; } @@ -80,19 +83,19 @@ STATIC UINT64 GetFirstPageAttribute ( IN UINT64 *FirstLevelTableAddress, - IN UINTN TableLevel + IN UINTN TableLevel ) { - UINT64 FirstEntry; + UINT64 FirstEntry; // Get the first entry of the table FirstEntry = *FirstLevelTableAddress; - if ((TableLevel != 3) && (FirstEntry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY) { + if ((TableLevel != 3) && ((FirstEntry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY)) { // Only valid for Levels 0, 1 and 2 // Get the attribute of the subsequent table - return GetFirstPageAttribute ((UINT64*)(FirstEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE), TableLevel + 1); + return GetFirstPageAttribute ((UINT64 *)(FirstEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE), TableLevel + 1); } else if (((FirstEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) || ((TableLevel == 3) && ((FirstEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY_LEVEL3))) { @@ -105,25 +108,25 @@ GetFirstPageAttribute ( STATIC UINT64 GetNextEntryAttribute ( - IN UINT64 *TableAddress, + IN UINT64 *TableAddress, IN UINTN EntryCount, IN UINTN TableLevel, IN UINT64 BaseAddress, - IN OUT UINT32 *PrevEntryAttribute, - IN OUT UINT64 *StartGcdRegion + IN OUT UINT32 *PrevEntryAttribute, + IN OUT UINT64 *StartGcdRegion ) { - UINTN Index; - UINT64 Entry; - UINT32 EntryAttribute; - UINT32 EntryType; - EFI_STATUS Status; - UINTN NumberOfDescriptors; + UINTN Index; + UINT64 Entry; + UINT32 EntryAttribute; + UINT32 EntryType; + EFI_STATUS Status; + UINTN NumberOfDescriptors; EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; // Get the memory space map from GCD MemorySpaceMap = NULL; - Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); ASSERT_EFI_ERROR (Status); // We cannot get more than 3-level page table @@ -132,24 +135,28 @@ GetNextEntryAttribute ( // While the top level table might not contain TT_ENTRY_COUNT entries; // the subsequent ones should be filled up for (Index = 0; Index < EntryCount; Index++) { - Entry = TableAddress[Index]; - EntryType = Entry & TT_TYPE_MASK; + Entry = TableAddress[Index]; + EntryType = Entry & TT_TYPE_MASK; EntryAttribute = Entry & TT_ATTR_INDX_MASK; // If Entry is a Table Descriptor type entry then go through the sub-level table if ((EntryType == TT_TYPE_BLOCK_ENTRY) || - ((TableLevel == 3) && (EntryType == TT_TYPE_BLOCK_ENTRY_LEVEL3))) { + ((TableLevel == 3) && (EntryType == TT_TYPE_BLOCK_ENTRY_LEVEL3))) + { if ((*PrevEntryAttribute == INVALID_ENTRY) || (EntryAttribute != *PrevEntryAttribute)) { if (*PrevEntryAttribute != INVALID_ENTRY) { // Update GCD with the last region - SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, - *StartGcdRegion, - (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL(TableLevel))) - *StartGcdRegion, - PageAttributeToGcdAttribute (*PrevEntryAttribute)); + SetGcdMemorySpaceAttributes ( + MemorySpaceMap, + NumberOfDescriptors, + *StartGcdRegion, + (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))) - *StartGcdRegion, + PageAttributeToGcdAttribute (*PrevEntryAttribute) + ); } // Start of the new region - *StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL(TableLevel)); + *StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel)); *PrevEntryAttribute = EntryAttribute; } else { continue; @@ -159,20 +166,27 @@ GetNextEntryAttribute ( ASSERT (TableLevel < 3); // Increase the level number and scan the sub-level table - GetNextEntryAttribute ((UINT64*)(Entry & TT_ADDRESS_MASK_DESCRIPTION_TABLE), - TT_ENTRY_COUNT, TableLevel + 1, - (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL(TableLevel))), - PrevEntryAttribute, StartGcdRegion); + GetNextEntryAttribute ( + (UINT64 *)(Entry & TT_ADDRESS_MASK_DESCRIPTION_TABLE), + TT_ENTRY_COUNT, + TableLevel + 1, + (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))), + PrevEntryAttribute, + StartGcdRegion + ); } else { if (*PrevEntryAttribute != INVALID_ENTRY) { // Update GCD with the last region - SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, - *StartGcdRegion, - (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL(TableLevel))) - *StartGcdRegion, - PageAttributeToGcdAttribute (*PrevEntryAttribute)); + SetGcdMemorySpaceAttributes ( + MemorySpaceMap, + NumberOfDescriptors, + *StartGcdRegion, + (BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))) - *StartGcdRegion, + PageAttributeToGcdAttribute (*PrevEntryAttribute) + ); // Start of the new region - *StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL(TableLevel)); + *StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel)); *PrevEntryAttribute = INVALID_ENTRY; } } @@ -180,25 +194,25 @@ GetNextEntryAttribute ( FreePool (MemorySpaceMap); - return BaseAddress + (EntryCount * TT_ADDRESS_AT_LEVEL(TableLevel)); + return BaseAddress + (EntryCount * TT_ADDRESS_AT_LEVEL (TableLevel)); } EFI_STATUS SyncCacheConfig ( - IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol + IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol ) { - EFI_STATUS Status; - UINT32 PageAttribute; - UINT64 *FirstLevelTableAddress; - UINTN TableLevel; - UINTN TableCount; - UINTN NumberOfDescriptors; - EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; - UINTN Tcr; - UINTN T0SZ; - UINT64 BaseAddressGcdRegion; - UINT64 EndAddressGcdRegion; + EFI_STATUS Status; + UINT32 PageAttribute; + UINT64 *FirstLevelTableAddress; + UINTN TableLevel; + UINTN TableCount; + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; + UINTN Tcr; + UINTN T0SZ; + UINT64 BaseAddressGcdRegion; + UINT64 EndAddressGcdRegion; // This code assumes MMU is enabled and filed with section translations ASSERT (ArmMmuEnabled ()); @@ -207,7 +221,7 @@ SyncCacheConfig ( // Get the memory space map from GCD // MemorySpaceMap = NULL; - Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); ASSERT_EFI_ERROR (Status); // The GCD implementation maintains its own copy of the state of memory space attributes. GCD needs @@ -217,7 +231,7 @@ SyncCacheConfig ( // with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead. // Obtain page table base - FirstLevelTableAddress = (UINT64*)(ArmGetTTBR0BaseAddress ()); + FirstLevelTableAddress = (UINT64 *)(ArmGetTTBR0BaseAddress ()); // Get Translation Control Register value Tcr = ArmGetTCR (); @@ -232,17 +246,24 @@ SyncCacheConfig ( // We scan from the start of the memory map (ie: at the address 0x0) BaseAddressGcdRegion = 0x0; - EndAddressGcdRegion = GetNextEntryAttribute (FirstLevelTableAddress, - TableCount, TableLevel, - BaseAddressGcdRegion, - &PageAttribute, &BaseAddressGcdRegion); + EndAddressGcdRegion = GetNextEntryAttribute ( + FirstLevelTableAddress, + TableCount, + TableLevel, + BaseAddressGcdRegion, + &PageAttribute, + &BaseAddressGcdRegion + ); // Update GCD with the last region if valid if (PageAttribute != INVALID_ENTRY) { - SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, - BaseAddressGcdRegion, - EndAddressGcdRegion - BaseAddressGcdRegion, - PageAttributeToGcdAttribute (PageAttribute)); + SetGcdMemorySpaceAttributes ( + MemorySpaceMap, + NumberOfDescriptors, + BaseAddressGcdRegion, + EndAddressGcdRegion - BaseAddressGcdRegion, + PageAttributeToGcdAttribute (PageAttribute) + ); } FreePool (MemorySpaceMap); @@ -252,30 +273,31 @@ SyncCacheConfig ( UINT64 EfiAttributeToArmAttribute ( - IN UINT64 EfiAttributes + IN UINT64 EfiAttributes ) { - UINT64 ArmAttributes; + UINT64 ArmAttributes; switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) { - case EFI_MEMORY_UC: - if (ArmReadCurrentEL () == AARCH64_EL2) { - ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_XN_MASK; - } else { - ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_UXN_MASK | TT_PXN_MASK; - } - break; - case EFI_MEMORY_WC: - ArmAttributes = TT_ATTR_INDX_MEMORY_NON_CACHEABLE; - break; - case EFI_MEMORY_WT: - ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_THROUGH | TT_SH_INNER_SHAREABLE; - break; - case EFI_MEMORY_WB: - ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_BACK | TT_SH_INNER_SHAREABLE; - break; - default: - ArmAttributes = TT_ATTR_INDX_MASK; + case EFI_MEMORY_UC: + if (ArmReadCurrentEL () == AARCH64_EL2) { + ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_XN_MASK; + } else { + ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_UXN_MASK | TT_PXN_MASK; + } + + break; + case EFI_MEMORY_WC: + ArmAttributes = TT_ATTR_INDX_MEMORY_NON_CACHEABLE; + break; + case EFI_MEMORY_WT: + ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_THROUGH | TT_SH_INNER_SHAREABLE; + break; + case EFI_MEMORY_WB: + ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_BACK | TT_SH_INNER_SHAREABLE; + break; + default: + ArmAttributes = TT_ATTR_INDX_MASK; } // Set the access flag to match the block attributes @@ -298,19 +320,19 @@ EfiAttributeToArmAttribute ( // And then the function will identify the size of the region that has the same page table attribute. EFI_STATUS GetMemoryRegionRec ( - IN UINT64 *TranslationTable, - IN UINTN TableLevel, - IN UINT64 *LastBlockEntry, - IN OUT UINTN *BaseAddress, - OUT UINTN *RegionLength, - OUT UINTN *RegionAttributes + IN UINT64 *TranslationTable, + IN UINTN TableLevel, + IN UINT64 *LastBlockEntry, + IN OUT UINTN *BaseAddress, + OUT UINTN *RegionLength, + OUT UINTN *RegionAttributes ) { - EFI_STATUS Status; - UINT64 *NextTranslationTable; - UINT64 *BlockEntry; - UINT64 BlockEntryType; - UINT64 EntryType; + EFI_STATUS Status; + UINT64 *NextTranslationTable; + UINT64 *BlockEntry; + UINT64 BlockEntryType; + UINT64 EntryType; if (TableLevel != 3) { BlockEntryType = TT_TYPE_BLOCK_ENTRY; @@ -319,22 +341,25 @@ GetMemoryRegionRec ( } // Find the block entry linked to the Base Address - BlockEntry = (UINT64*)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, TableLevel, *BaseAddress); - EntryType = *BlockEntry & TT_TYPE_MASK; + BlockEntry = (UINT64 *)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, TableLevel, *BaseAddress); + EntryType = *BlockEntry & TT_TYPE_MASK; if ((TableLevel < 3) && (EntryType == TT_TYPE_TABLE_ENTRY)) { - NextTranslationTable = (UINT64*)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE); + NextTranslationTable = (UINT64 *)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE); // The entry is a page table, so we go to the next level Status = GetMemoryRegionRec ( - NextTranslationTable, // Address of the next level page table - TableLevel + 1, // Next Page Table level - (UINTN*)TT_LAST_BLOCK_ADDRESS(NextTranslationTable, TT_ENTRY_COUNT), - BaseAddress, RegionLength, RegionAttributes); + NextTranslationTable, // Address of the next level page table + TableLevel + 1, // Next Page Table level + (UINTN *)TT_LAST_BLOCK_ADDRESS (NextTranslationTable, TT_ENTRY_COUNT), + BaseAddress, + RegionLength, + RegionAttributes + ); // In case of 'Success', it means the end of the block region has been found into the upper // level translation table - if (!EFI_ERROR(Status)) { + if (!EFI_ERROR (Status)) { return EFI_SUCCESS; } @@ -343,7 +368,7 @@ GetMemoryRegionRec ( } else if (EntryType == BlockEntryType) { // We have found the BlockEntry attached to the address. We save its start address (the start // address might be before the 'BaseAddress') and attributes - *BaseAddress = *BaseAddress & ~(TT_ADDRESS_AT_LEVEL(TableLevel) - 1); + *BaseAddress = *BaseAddress & ~(TT_ADDRESS_AT_LEVEL (TableLevel) - 1); *RegionLength = 0; *RegionAttributes = *BlockEntry & TT_ATTRIBUTES_MASK; } else { @@ -353,11 +378,12 @@ GetMemoryRegionRec ( while (BlockEntry <= LastBlockEntry) { if ((*BlockEntry & TT_ATTRIBUTES_MASK) == *RegionAttributes) { - *RegionLength = *RegionLength + TT_BLOCK_ENTRY_SIZE_AT_LEVEL(TableLevel); + *RegionLength = *RegionLength + TT_BLOCK_ENTRY_SIZE_AT_LEVEL (TableLevel); } else { // In case we have found the end of the region we return success return EFI_SUCCESS; } + BlockEntry++; } @@ -369,13 +395,13 @@ GetMemoryRegionRec ( EFI_STATUS GetMemoryRegion ( - IN OUT UINTN *BaseAddress, - OUT UINTN *RegionLength, - OUT UINTN *RegionAttributes + IN OUT UINTN *BaseAddress, + OUT UINTN *RegionLength, + OUT UINTN *RegionAttributes ) { EFI_STATUS Status; - UINT64 *TranslationTable; + UINT64 *TranslationTable; UINTN TableLevel; UINTN EntryCount; UINTN T0SZ; @@ -388,9 +414,14 @@ GetMemoryRegion ( // Get the Table info from T0SZ GetRootTranslationTableInfo (T0SZ, &TableLevel, &EntryCount); - Status = GetMemoryRegionRec (TranslationTable, TableLevel, - (UINTN*)TT_LAST_BLOCK_ADDRESS(TranslationTable, EntryCount), - BaseAddress, RegionLength, RegionAttributes); + Status = GetMemoryRegionRec ( + TranslationTable, + TableLevel, + (UINTN *)TT_LAST_BLOCK_ADDRESS (TranslationTable, EntryCount), + BaseAddress, + RegionLength, + RegionAttributes + ); // If the region continues up to the end of the root table then GetMemoryRegionRec() // will return EFI_NOT_FOUND