diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h index e138613ca5..cbd3d6f654 100644 --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h @@ -15,6 +15,20 @@ #ifndef __ARM_V7_LIB_H__ #define __ARM_V7_LIB_H__ +#define ID_MMFR0_SHARELVL_SHIFT 12 +#define ID_MMFR0_SHARELVL_MASK 0xf +#define ID_MMFR0_SHARELVL_ONE 0 +#define ID_MMFR0_SHARELVL_TWO 1 + +#define ID_MMFR0_INNERSHR_SHIFT 28 +#define ID_MMFR0_INNERSHR_MASK 0xf +#define ID_MMFR0_OUTERSHR_SHIFT 8 +#define ID_MMFR0_OUTERSHR_MASK 0xf + +#define ID_MMFR0_SHR_IMP_UNCACHED 0 +#define ID_MMFR0_SHR_IMP_HW_COHERENT 1 +#define ID_MMFR0_SHR_IGNORED 0xf + typedef VOID (*ARM_V7_CACHE_OPERATION)(UINT32); VOID diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c index 23d2e43beb..fc8ea42843 100644 --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c @@ -41,6 +41,42 @@ ConvertSectionAttributesToPageAttributes ( return PageAttributes; } +STATIC +BOOLEAN +PreferNonshareableMemory ( + VOID + ) +{ + UINTN Mmfr; + UINTN Val; + + if (FeaturePcdGet (PcdNormalMemoryNonshareableOverride)) { + return TRUE; + } + + // + // Check whether the innermost level of shareability (the level we will use + // by default to map normal memory) is implemented with hardware coherency + // support. Otherwise, revert to mapping as non-shareable. + // + Mmfr = ArmReadIdMmfr0 (); + switch ((Mmfr >> ID_MMFR0_SHARELVL_SHIFT) & ID_MMFR0_SHARELVL_MASK) { + case ID_MMFR0_SHARELVL_ONE: + // one level of shareability + Val = (Mmfr >> ID_MMFR0_OUTERSHR_SHIFT) & ID_MMFR0_OUTERSHR_MASK; + break; + case ID_MMFR0_SHARELVL_TWO: + // two levels of shareability + Val = (Mmfr >> ID_MMFR0_INNERSHR_SHIFT) & ID_MMFR0_INNERSHR_MASK; + break; + default: + // unexpected value -> shareable is the safe option + ASSERT (FALSE); + return FALSE; + } + return Val != ID_MMFR0_SHR_IMP_HW_COHERENT; +} + STATIC VOID PopulateLevel2PageTable ( @@ -80,7 +116,7 @@ PopulateLevel2PageTable ( break; } - if (FeaturePcdGet(PcdNormalMemoryNonshareableOverride)) { + if (PreferNonshareableMemory ()) { PageAttributes &= ~TT_DESCRIPTOR_PAGE_S_SHARED; } @@ -189,7 +225,7 @@ FillTranslationTable ( break; } - if (FeaturePcdGet(PcdNormalMemoryNonshareableOverride)) { + if (PreferNonshareableMemory ()) { Attributes &= ~TT_DESCRIPTOR_SECTION_S_SHARED; } @@ -281,7 +317,7 @@ ArmConfigureMmu ( } if (TTBRAttributes & TTBR_SHAREABLE) { - if (FeaturePcdGet(PcdNormalMemoryNonshareableOverride)) { + if (PreferNonshareableMemory ()) { TTBRAttributes ^= TTBR_SHAREABLE; } else { //