diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec index 46e9894d3f..ff4531e441 100644 --- a/ArmPkg/ArmPkg.dec +++ b/ArmPkg/ArmPkg.dec @@ -73,6 +73,12 @@ # Define if the GICv3 controller should use the GICv2 legacy gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy|FALSE|BOOLEAN|0x00000042 +[PcdsFeatureFlag.ARM] + # Whether to map normal memory as non-shareable. FALSE is the safe choice, but + # TRUE may be appropriate to fix performance problems if you don't care about + # hardware coherency (i.e., no virtualization or cache coherent DMA) + gArmTokenSpaceGuid.PcdNormalMemoryNonshareableOverride|FALSE|BOOLEAN|0x00000043 + [PcdsFixedAtBuild.common] gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE|BOOLEAN|0x00000006 diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf index 01bdfb6996..d56851a140 100644 --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf @@ -48,3 +48,6 @@ [Protocols] gEfiCpuArchProtocolGuid + +[FeaturePcd.ARM] + gArmTokenSpaceGuid.PcdNormalMemoryNonshareableOverride diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf index ac081068db..6eaf350c7b 100644 --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf @@ -48,3 +48,6 @@ [Protocols] gEfiCpuArchProtocolGuid + +[FeaturePcd.ARM] + gArmTokenSpaceGuid.PcdNormalMemoryNonshareableOverride diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c index f03f609d21..a9cb06d78e 100644 --- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c +++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c @@ -80,6 +80,10 @@ PopulateLevel2PageTable ( break; } + if (FeaturePcdGet(PcdNormalMemoryNonshareableOverride)) { + PageAttributes &= ~TT_DESCRIPTOR_PAGE_S_SHARED; + } + // Check if the Section Entry has already been populated. Otherwise attach a // Level 2 Translation Table to it if (*SectionEntry != 0) { @@ -178,6 +182,10 @@ FillTranslationTable ( break; } + if (FeaturePcdGet(PcdNormalMemoryNonshareableOverride)) { + Attributes &= ~TT_DESCRIPTOR_SECTION_S_SHARED; + } + // Get the first section entry for this mapping SectionEntry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); @@ -266,15 +274,19 @@ ArmConfigureMmu ( } if (TTBRAttributes & TTBR_SHAREABLE) { - // - // Unlike the S bit in the short descriptors, which implies inner shareable - // on an implementation that supports two levels, the meaning of the S bit - // in the TTBR depends on the NOS bit, which defaults to Outer Shareable. - // However, we should only set this bit after we have confirmed that the - // implementation supports multiple levels, or else the NOS bit is UNK/SBZP - // - if (((ArmReadIdMmfr0 () >> 12) & 0xf) != 0) { - TTBRAttributes |= TTBR_NOT_OUTER_SHAREABLE; + if (FeaturePcdGet(PcdNormalMemoryNonshareableOverride)) { + TTBRAttributes ^= TTBR_SHAREABLE; + } else { + // + // Unlike the S bit in the short descriptors, which implies inner shareable + // on an implementation that supports two levels, the meaning of the S bit + // in the TTBR depends on the NOS bit, which defaults to Outer Shareable. + // However, we should only set this bit after we have confirmed that the + // implementation supports multiple levels, or else the NOS bit is UNK/SBZP + // + if (((ArmReadIdMmfr0 () >> 12) & 0xf) != 0) { + TTBRAttributes |= TTBR_NOT_OUTER_SHAREABLE; + } } }