summaryrefslogtreecommitdiffstats
path: root/ArmPkg
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2015-12-15 17:31:56 +0000
committerabiesheuvel <abiesheuvel@Edk2>2015-12-15 17:31:56 +0000
commit46ff196fde4882fca1a0210f7df9166d8832ad06 (patch)
tree8ebf9ac7cfe7ee2a91f11d070c4abd9452a5fe78 /ArmPkg
parentb9f7890c47691c7eb5c66c42c775744ee813260b (diff)
downloadedk2-46ff196fde4882fca1a0210f7df9166d8832ad06.tar.gz
edk2-46ff196fde4882fca1a0210f7df9166d8832ad06.tar.bz2
edk2-46ff196fde4882fca1a0210f7df9166d8832ad06.zip
ArmPkg/ArmV7Mmu: prefer non shareable memory on non-coherent hardware
Commit SVN r18778 made all mappings of normal memory (inner) shareable, even on hardware that implements shareability as uncached accesses. The original concerns that prompted the change, regarding coherent DMA and virt guests migrating between CPUs, do not apply to such hardware, so revert to the original behavior in that case. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19285 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg')
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h14
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c42
2 files changed, 53 insertions, 3 deletions
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
@@ -42,6 +42,42 @@ ConvertSectionAttributesToPageAttributes (
}
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 (
IN UINT32 *SectionEntry,
@@ -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 {
//