arch-arm: Implement ARMv8.1 TTBR1_EL2 register
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Fri, 20 Apr 2018 08:50:29 +0000 (09:50 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 29 May 2018 10:07:53 +0000 (10:07 +0000)
This patch implements the ARMv8.1 TTBR1_EL2 register, which is used for
getting the translation table base address when a Host Operating System
is running at EL2. (HCR_EL2.E2H = 1)

Change-Id: Ic0ab351cae3fd64855eda7c18c8757da0d7b8663
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/10382
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/arch/arm/miscregs.cc
src/arch/arm/table_walker.cc

index 08eb255f3a00aec48cdf4921c1f501a4fe0f36ec..e1ddbf9d3cd3247254c15f763f07c521bc772593 100644 (file)
@@ -3535,7 +3535,7 @@ ISA::initializeMiscRegMetadata()
       .hyp().mon()
       .mapsTo(MISCREG_HTTBR);
     InitReg(MISCREG_TTBR1_EL2)
-      .unimplemented();
+      .hyp().mon();
     InitReg(MISCREG_TCR_EL2)
       .hyp().mon()
       .mapsTo(MISCREG_HTCR);
index 3c79e43ac423200115acc415e95451d8fbf59e2a..26a07d70e37d59e53f47bcc2654dbb80e05e6661 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012-2017 ARM Limited
+ * Copyright (c) 2010, 2012-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -739,9 +739,9 @@ TableWalker::processWalkAArch64()
     DPRINTF(TLB, "Beginning table walk for address %#llx, TCR: %#llx\n",
             currState->vaddr_tainted, currState->tcr);
 
-    static const GrainSize GrainMapDefault[] =
+    static const GrainSize GrainMap_tg0[] =
       { Grain4KB, Grain64KB, Grain16KB, ReservedGrain };
-    static const GrainSize GrainMap_EL1_tg1[] =
+    static const GrainSize GrainMap_tg1[] =
       { ReservedGrain, Grain16KB, Grain4KB, Grain64KB };
 
     statWalkWaitTime.sample(curTick() - currState->startTime);
@@ -761,7 +761,7 @@ TableWalker::processWalkAArch64()
             DPRINTF(TLB, " - Selecting VTTBR0 (AArch64 stage 2)\n");
             ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2);
             tsz = 64 - currState->vtcr.t0sz64;
-            tg = GrainMapDefault[currState->vtcr.tg0];
+            tg = GrainMap_tg0[currState->vtcr.tg0];
             // ARM DDI 0487A.f D7-2148
             // The starting level of stage 2 translation depends on
             // VTCR_EL2.SL0 and VTCR_EL2.TG0
@@ -781,7 +781,7 @@ TableWalker::processWalkAArch64()
             DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
             ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
             tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
-            tg = GrainMapDefault[currState->tcr.tg0];
+            tg = GrainMap_tg0[currState->tcr.tg0];
             if (bits(currState->vaddr, 63, tsz) != 0x0 ||
                 currState->tcr.epd0)
               fault = true;
@@ -790,7 +790,7 @@ TableWalker::processWalkAArch64()
             DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
             ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
             tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
-            tg = GrainMap_EL1_tg1[currState->tcr.tg1];
+            tg = GrainMap_tg1[currState->tcr.tg1];
             if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
                 currState->tcr.epd1)
               fault = true;
@@ -802,16 +802,37 @@ TableWalker::processWalkAArch64()
         ps = currState->tcr.ips;
         break;
       case EL2:
+        switch(bits(currState->vaddr, 63,48)) {
+          case 0:
+            DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
+            ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
+            tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
+            tg = GrainMap_tg0[currState->tcr.tg0];
+            break;
+
+          case 0xffff:
+            DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
+            ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL2);
+            tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
+            tg = GrainMap_tg1[currState->tcr.tg1];
+            if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
+                currState->tcr.epd1 || !currState->hcr.e2h)
+              fault = true;
+            break;
+
+           default:
+              // invalid addr if top two bytes are not all 0s
+              fault = true;
+        }
+        ps = currState->tcr.ips;
+        break;
       case EL3:
         switch(bits(currState->vaddr, 63,48)) {
             case 0:
                 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
-                if (currState->el == EL2)
-                    ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
-                else
-                    ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
+                ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
                 tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
-                tg = GrainMapDefault[currState->tcr.tg0];
+                tg = GrainMap_tg0[currState->tcr.tg0];
                 break;
             default:
                 // invalid addr if top two bytes are not all 0s