arm: Fix stage 2 memory attribute checking in AArch64
authorDylan Johnson <Dylan.Johnson@ARM.com>
Tue, 2 Aug 2016 09:38:03 +0000 (10:38 +0100)
committerDylan Johnson <Dylan.Johnson@ARM.com>
Tue, 2 Aug 2016 09:38:03 +0000 (10:38 +0100)
Change-Id: I14c93a5460550051a12129e792a9a9bd522a145c

src/arch/arm/table_walker.cc
src/arch/arm/table_walker.hh

index 1c1f705998e978c1786763bb98d2df6baf13c36e..1f06d009a24e9f9808e32c707e812d6eb0c49edc 100644 (file)
@@ -1337,52 +1337,82 @@ TableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
 }
 
 void
-TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
-                             uint8_t sh)
+TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
+                             LongDescriptor &lDescriptor)
 {
-    DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
+    uint8_t attr;
+    uint8_t attr_hi;
+    uint8_t attr_lo;
+    uint8_t sh = lDescriptor.sh();
 
-    // Select MAIR
-    uint64_t mair;
-    switch (currState->el) {
-      case EL0:
-      case EL1:
-        mair = tc->readMiscReg(MISCREG_MAIR_EL1);
-        break;
-      case EL2:
-        mair = tc->readMiscReg(MISCREG_MAIR_EL2);
-        break;
-      case EL3:
-        mair = tc->readMiscReg(MISCREG_MAIR_EL3);
-        break;
-      default:
-        panic("Invalid exception level");
-        break;
-    }
+    if (isStage2) {
+        attr = lDescriptor.memAttr();
+        uint8_t attr_hi = (attr >> 2) & 0x3;
+        uint8_t attr_lo =  attr       & 0x3;
+
+        DPRINTF(TLBVerbose, "memAttrsAArch64 MemAttr:%#x sh:%#x\n", attr, sh);
+
+        if (attr_hi == 0) {
+            te.mtype        = attr_lo == 0 ? TlbEntry::MemoryType::StronglyOrdered
+                                            : TlbEntry::MemoryType::Device;
+            te.outerAttrs   = 0;
+            te.innerAttrs   = attr_lo == 0 ? 1 : 3;
+            te.nonCacheable = true;
+        } else {
+            te.mtype        = TlbEntry::MemoryType::Normal;
+            te.outerAttrs   = attr_hi == 1 ? 0 :
+                              attr_hi == 2 ? 2 : 1;
+            te.innerAttrs   = attr_lo == 1 ? 0 :
+                              attr_lo == 2 ? 6 : 5;
+            te.nonCacheable = (attr_hi == 1) || (attr_lo == 1);
+        }
+    } else {
+        uint8_t attrIndx = lDescriptor.attrIndx();
+
+        DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
+
+        // Select MAIR
+        uint64_t mair;
+        switch (currState->el) {
+          case EL0:
+          case EL1:
+            mair = tc->readMiscReg(MISCREG_MAIR_EL1);
+            break;
+          case EL2:
+            mair = tc->readMiscReg(MISCREG_MAIR_EL2);
+            break;
+          case EL3:
+            mair = tc->readMiscReg(MISCREG_MAIR_EL3);
+            break;
+          default:
+            panic("Invalid exception level");
+            break;
+        }
 
-    // Select attributes
-    uint8_t attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
-    uint8_t attr_lo = bits(attr, 3, 0);
-    uint8_t attr_hi = bits(attr, 7, 4);
+        // Select attributes
+        attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
+        attr_lo = bits(attr, 3, 0);
+        attr_hi = bits(attr, 7, 4);
 
-    // Memory type
-    te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal;
+        // Memory type
+        te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal;
 
-    // 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
-        te.nonCacheable = true;
-    }
+        // 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
+            te.nonCacheable = true;
+        }
 
-    te.shareable       = sh == 2;
-    te.outerShareable = (sh & 0x2) ? true : false;
-    // Attributes formatted according to the 64-bit PAR
-    te.attributes = ((uint64_t) attr << 56) |
-        (1 << 11) |     // LPAE bit
-        (te.ns << 9) |  // NS bit
-        (sh << 7);
+        te.shareable       = sh == 2;
+        te.outerShareable = (sh & 0x2) ? true : false;
+        // Attributes formatted according to the 64-bit PAR
+        te.attributes = ((uint64_t) attr << 56) |
+            (1 << 11) |     // LPAE bit
+            (te.ns << 9) |  // NS bit
+            (sh << 7);
+    }
 }
 
 void
@@ -2038,8 +2068,7 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
                (currState->userTable && (descriptor.ap() & 0x1));
         }
         if (currState->aarch64)
-            memAttrsAArch64(currState->tc, te, currState->longDesc.attrIndx(),
-                            currState->longDesc.sh());
+            memAttrsAArch64(currState->tc, te, lDescriptor);
         else
             memAttrsLPAE(currState->tc, te, lDescriptor);
     } else {
index e3c7d33d72fd3b6e8a5e54e4fbac5ef5f075acb0..fc628f714ab78adeb2b95c018c2e9fc5cd82f8cc 100644 (file)
@@ -911,8 +911,8 @@ class TableWalker : public MemObject
                   uint8_t texcb, bool s);
     void memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
                       LongDescriptor &lDescriptor);
-    void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
-                         uint8_t sh);
+    void memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
+                         LongDescriptor &lDescriptor);
 
     static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);