X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ArmPkg%2FLibrary%2FArmMmuLib%2FArm%2FArmMmuLibCore.c;h=889b22867dc79081a6a8bb79736533ccd8a27126;hp=351b6c03a42c7593017a81727c38a304f0cb80a7;hb=aa1097921d7581a8a9c527d5beb3d9d97c731f7e;hpb=d9c0d991f769c50e69d14a006bdbaaf31986143a diff --git a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c index 351b6c03a4..889b22867d 100644 --- a/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibCore.c @@ -37,6 +37,8 @@ #define ID_MMFR0_SHR_IMP_HW_COHERENT 1 #define ID_MMFR0_SHR_IGNORED 0xf +#define __EFI_MEMORY_RWX 0 // no restrictions + #define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | \ EFI_MEMORY_WC | \ EFI_MEMORY_WT | \ @@ -126,6 +128,7 @@ PopulateLevel2PageTable ( UINT32 SectionDescriptor; UINT32 TranslationTable; UINT32 BaseSectionAddress; + UINT32 FirstPageOffset; switch (Attributes) { case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: @@ -197,9 +200,12 @@ PopulateLevel2PageTable ( TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE; } - PageEntry = ((UINT32 *)(TranslationTable) + ((PhysicalBase & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT)); + FirstPageOffset = (PhysicalBase & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT; + PageEntry = (UINT32 *)TranslationTable + FirstPageOffset; Pages = RemainLength / TT_DESCRIPTOR_PAGE_SIZE; + ASSERT (FirstPageOffset + Pages <= TRANSLATION_TABLE_PAGE_COUNT); + for (Index = 0; Index < Pages; Index++) { *PageEntry++ = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(PhysicalBase) | PageAttributes; PhysicalBase += TT_DESCRIPTOR_PAGE_SIZE; @@ -218,6 +224,7 @@ FillTranslationTable ( UINT32 Attributes; UINT32 PhysicalBase; UINT64 RemainLength; + UINT32 PageMapLength; ASSERT(MemoryRegion->Length > 0); @@ -266,30 +273,31 @@ FillTranslationTable ( 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; - } + if (PhysicalBase % TT_DESCRIPTOR_SECTION_SIZE == 0 && + 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; + RemainLength -= TT_DESCRIPTOR_SECTION_SIZE; } else { + PageMapLength = MIN (RemainLength, TT_DESCRIPTOR_SECTION_SIZE) - + (PhysicalBase % TT_DESCRIPTOR_SECTION_SIZE); + + // Case: Physical address aligned on the Section Size (1MB) && the length + // does not fill a section // 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); + PopulateLevel2PageTable (SectionEntry++, PhysicalBase, PageMapLength, + MemoryRegion->Attributes); // If it is the last entry if (RemainLength < TT_DESCRIPTOR_SECTION_SIZE) { break; } + + PhysicalBase += PageMapLength; + RemainLength -= PageMapLength; } - RemainLength -= TT_DESCRIPTOR_SECTION_SIZE; } } @@ -335,17 +343,12 @@ ArmConfigureMmu ( } // Translate the Memory Attributes into Translation Table Register Attributes - if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED) || - (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED)) { - TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_NON_CACHEABLE : TTBR_NON_CACHEABLE; - } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) || + if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) || (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK)) { TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_BACK_ALLOC : TTBR_WRITE_BACK_ALLOC; - } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH) || - (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH)) { - TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_THROUGH : TTBR_WRITE_THROUGH; } else { - ASSERT (0); // No support has been found for the attributes of the memory region that the translation table belongs to. + // Page tables must reside in memory mapped as write-back cacheable + ASSERT (0); return RETURN_UNSUPPORTED; } @@ -453,9 +456,6 @@ ConvertSectionToPages ( 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 - WriteBackInvalidateDataCacheRange ((VOID *)PageTable, TT_DESCRIPTOR_PAGE_SIZE); - // Formulate page table entry, Domain=0, NS=0 PageTableDescriptor = (((UINTN)PageTable) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE; @@ -589,12 +589,6 @@ UpdatePageEntries ( if (CurrentPageTableEntry != PageTableEntry) { Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT)); - // Clean/invalidate the cache for this page, but only - // if we are modifying the memory type attributes - if (((CurrentPageTableEntry ^ PageTableEntry) & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) != 0) { - WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE); - } - // Only need to update if we are changing the entry PageTable[PageTableIndex] = PageTableEntry; ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva); @@ -701,20 +695,18 @@ UpdateSectionEntries ( } else { // still a section entry - // mask off appropriate fields - Descriptor = CurrentDescriptor & ~EntryMask; + if (CurrentDescriptor != 0) { + // mask off appropriate fields + Descriptor = CurrentDescriptor & ~EntryMask; + } else { + Descriptor = ((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT; + } // mask in new attributes and/or permissions Descriptor |= EntryValue; if (CurrentDescriptor != Descriptor) { - Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << TT_DESCRIPTOR_SECTION_BASE_SHIFT); - - // Clean/invalidate the cache for this section, but only - // if we are modifying the memory type attributes - if (((CurrentDescriptor ^ Descriptor) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) != 0) { - WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB); - } + Mva = (VOID *)(UINTN)(((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT); // Only need to update if we are changing the descriptor FirstLevelTable[FirstLevelIdx + i] = Descriptor; @@ -797,7 +789,7 @@ ArmSetMemoryRegionNoExec ( IN UINT64 Length ) { - return EFI_UNSUPPORTED; + return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP); } EFI_STATUS @@ -806,7 +798,7 @@ ArmClearMemoryRegionNoExec ( IN UINT64 Length ) { - return EFI_UNSUPPORTED; + return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX); } EFI_STATUS @@ -815,7 +807,7 @@ ArmSetMemoryRegionReadOnly ( IN UINT64 Length ) { - return EFI_UNSUPPORTED; + return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO); } EFI_STATUS @@ -824,7 +816,7 @@ ArmClearMemoryRegionReadOnly ( IN UINT64 Length ) { - return EFI_UNSUPPORTED; + return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX); } RETURN_STATUS