arm: Treat Write-Through Normal memory as Non-Cacheable
authorNikos Nikoleris <nikos.nikoleris@arm.com>
Mon, 27 Feb 2017 15:57:31 +0000 (15:57 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 3 Apr 2017 16:39:00 +0000 (16:39 +0000)
A completed write to a memory location that is Write-Through Cacheable
has to be visible to an external observer without the need of explicit
cache maintenance. This change adds support for Write-Through
Cacheable Normal memory and treats it as Non-cacheable. This incurs a
small penalty as accesses to the memory do not fill in the cache but
does not violate the properties of the memory type.

Change-Id: Iee17ef9d952a550be9ad660b1e60e9f6c4ef2c2d
Reviewed-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2280
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
src/arch/arm/table_walker.cc

index 82462ab3343481ac3d3a9a0f78bfebf18563b1a9..8783d0a00bb914b3a3a626895d3a9ab5c510d12f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012-2016 ARM Limited
+ * Copyright (c) 2010, 2012-2017 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -1342,7 +1342,10 @@ TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
                               attr_hi == 2 ? 2 : 1;
             te.innerAttrs   = attr_lo == 1 ? 0 :
                               attr_lo == 2 ? 6 : 5;
-            te.nonCacheable = (attr_hi == 1) || (attr_lo == 1);
+            // Treat write-through memory as uncacheable, this is safe
+            // but for performance reasons not optimal.
+            te.nonCacheable = (attr_hi == 1) || (attr_hi == 2) ||
+                (attr_lo == 1) || (attr_lo == 2);
         }
     } else {
         uint8_t attrIndx = lDescriptor.attrIndx();
@@ -1377,9 +1380,25 @@ TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
 
         // Cacheability
         te.nonCacheable = false;
-        if (te.mtype == TlbEntry::MemoryType::Device ||  // Device memory
-            attr_hi == 0x8 ||  // Normal memory, Outer Non-cacheable
-            attr_lo == 0x8) {  // Normal memory, Inner Non-cacheable
+        if (te.mtype == TlbEntry::MemoryType::Device) {  // Device memory
+            te.nonCacheable = true;
+        }
+        // Treat write-through memory as uncacheable, this is safe
+        // but for performance reasons not optimal.
+        switch (attr_hi) {
+          case 0x1 ... 0x3: // Normal Memory, Outer Write-through transient
+          case 0x4:         // Normal memory, Outer Non-cacheable
+          case 0x8 ... 0xb: // Normal Memory, Outer Write-through non-transient
+            te.nonCacheable = true;
+        }
+        switch (attr_lo) {
+          case 0x1 ... 0x3: // Normal Memory, Inner Write-through transient
+          case 0x9 ... 0xb: // Normal Memory, Inner Write-through non-transient
+            warn_if(!attr_hi, "Unpredictable behavior");
+          case 0x4:         // Device-nGnRE memory or
+                            // Normal memory, Inner Non-cacheable
+          case 0x8:         // Device-nGRE memory or
+                            // Normal memory, Inner Write-through non-transient
             te.nonCacheable = true;
         }