arm: refactor page table format determination
authorCurtis Dunham <Curtis.Dunham@arm.com>
Thu, 2 Jun 2016 15:44:57 +0000 (16:44 +0100)
committerCurtis Dunham <Curtis.Dunham@arm.com>
Thu, 2 Jun 2016 15:44:57 +0000 (16:44 +0100)
In particular, when EL0 is in AArch32 but EL1 is AArch64, AArch64
memory translation must be used.  This is essential for typical
AArch64/32 interworking use cases.

src/arch/arm/table_walker.cc
src/arch/arm/tlb.cc

index e1e00442d6949f4d4e0a8d7967ee3b8c9085693e..82bec2547c05d159812ec614b3cfe8d52865450f 100644 (file)
@@ -220,7 +220,11 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid,
 
     currState->startTime = curTick();
     currState->tc = _tc;
-    currState->aarch64 = opModeIs64(currOpMode(_tc));
+    // ARM DDI 0487A.f (ARMv8 ARM) pg J8-5672
+    // aarch32/translation/translation/AArch32.TranslateAddress dictates
+    // even AArch32 EL0 will use AArch64 translation if EL1 is in AArch64.
+    currState->aarch64 = opModeIs64(currOpMode(_tc)) ||
+                         ((currEL(_tc) == EL0) && ELIs64(_tc, EL1));
     currState->el = currEL(_tc);
     currState->transState = _trans;
     currState->req = _req;
@@ -290,9 +294,8 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid,
     currState->stage2Req = !currState->aarch64 && currState->hcr.vm &&
                            !isStage2 && !currState->isSecure && !currState->isHyp;
 
-    bool long_desc_format = currState->aarch64 ||
-                            (_haveLPAE && currState->ttbcr.eae) ||
-                            _isHyp || isStage2;
+    bool long_desc_format = currState->aarch64 || _isHyp || isStage2 ||
+                            longDescFormatInUse(currState->tc);
 
     if (long_desc_format) {
         // Helper variables used for hierarchical permissions
@@ -377,7 +380,8 @@ TableWalker::processWalkWrapper()
         Fault f;
         if (currState->aarch64)
             f = processWalkAArch64();
-        else if ((_haveLPAE && currState->ttbcr.eae) || currState->isHyp || isStage2)
+        else if (longDescFormatInUse(currState->tc) ||
+                 currState->isHyp || isStage2)
             f = processWalkLPAE();
         else
             f = processWalk();
@@ -565,7 +569,7 @@ TableWalker::processWalkLPAE()
         ttbr = currState->tc->readMiscReg(MISCREG_HTTBR);
         tsz  = currState->htcr.t0sz;
     } else {
-        assert(_haveLPAE && currState->ttbcr.eae);
+        assert(longDescFormatInUse(currState->tc));
 
         // Determine boundaries of TTBR0/1 regions
         if (currState->ttbcr.t0sz)
index 1f6910262cc567faa69d82f0ad2230f4c14c083c..db132e2d686456fb56c55f3ed367a3b4545fb887 100644 (file)
@@ -951,7 +951,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
 
     bool is_fetch  = (mode == Execute);
     bool is_write  = (mode == Write);
-    bool long_desc_format = aarch64 || (haveLPAE && ttbcr.eae);
+    bool long_desc_format = aarch64 || longDescFormatInUse(tc);
     ArmFault::TranMethod tranMethod = long_desc_format ? ArmFault::LpaeTran
                                                        : ArmFault::VmsaTran;
 
@@ -1247,15 +1247,13 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
                                  !isSecure));
         scr    = tc->readMiscReg(MISCREG_SCR);
         isPriv = cpsr.mode != MODE_USER;
-        if (haveLPAE && ttbcr.eae) {
-            // Long-descriptor translation table format in use
+        if (longDescFormatInUse(tc)) {
             uint64_t ttbr_asid = tc->readMiscReg(
                 flattenMiscRegNsBanked(ttbcr.a1 ? MISCREG_TTBR1
                                                 : MISCREG_TTBR0,
                                        tc, !isSecure));
             asid = bits(ttbr_asid, 55, 48);
-        } else {
-            // Short-descriptor translation table format in use
+        } else { // Short-descriptor translation table format in use
             CONTEXTIDR context_id = tc->readMiscReg(flattenMiscRegNsBanked(
                 MISCREG_CONTEXTIDR, tc,!isSecure));
             asid = context_id.asid;