arch-arm: Fix implementation of TLBI_VMALL instructions
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Fri, 18 Sep 2020 09:33:24 +0000 (10:33 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 3 Nov 2020 09:55:11 +0000 (09:55 +0000)
Same as 73dfc5f89b81e622a2330b1b52e055cafcc9178b: there's a difference
on how AArch64 and AArch32 treat stage2 invalidation.

Change-Id: I6fede4d9cb82e4bae9163326d38db9351d2a3880
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/35243
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/arm/isa.cc
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh
src/arch/arm/tlbi_op.cc
src/arch/arm/tlbi_op.hh

index 1866319ed864d2c9f4b8bd69eaf805f83c49f226..217f432ac7cd5319814b4f80e957a3e78b158c33 100644 (file)
@@ -1755,17 +1755,15 @@ ISA::setMiscReg(int misc_reg, RegVal val)
                 return;
             }
           case MISCREG_TLBI_VMALLS12E1:
-            // @todo: handle VMID and stage 2 to enable Virtualization
             {
                 assert64();
                 scr = readMiscReg(MISCREG_SCR);
 
-                TLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
+                TLBIVMALL tlbiOp(EL1, haveSecurity && !scr.ns, true);
                 tlbiOp(tc);
                 return;
             }
           case MISCREG_TLBI_VMALLE1:
-            // @todo: handle VMID and stage 2 to enable Virtualization
             {
                 assert64();
                 scr = readMiscReg(MISCREG_SCR);
@@ -1773,22 +1771,20 @@ ISA::setMiscReg(int misc_reg, RegVal val)
                 HCR hcr = readMiscReg(MISCREG_HCR_EL2);
                 bool is_host = (hcr.tge && hcr.e2h);
                 ExceptionLevel target_el = is_host ?  EL2 : EL1;
-                TLBIALL tlbiOp(target_el, haveSecurity && !scr.ns);
+                TLBIVMALL tlbiOp(target_el, haveSecurity && !scr.ns, false);
                 tlbiOp(tc);
                 return;
             }
           case MISCREG_TLBI_VMALLS12E1IS:
-            // @todo: handle VMID and stage 2 to enable Virtualization
             {
                 assert64();
                 scr = readMiscReg(MISCREG_SCR);
 
-                TLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
+                TLBIVMALL tlbiOp(EL1, haveSecurity && !scr.ns, true);
                 tlbiOp.broadcast(tc);
                 return;
             }
           case MISCREG_TLBI_VMALLE1IS:
-            // @todo: handle VMID and stage 2 to enable Virtualization
             {
                 assert64();
                 scr = readMiscReg(MISCREG_SCR);
@@ -1796,7 +1792,7 @@ ISA::setMiscReg(int misc_reg, RegVal val)
                 HCR hcr = readMiscReg(MISCREG_HCR_EL2);
                 bool is_host = (hcr.tge && hcr.e2h);
                 ExceptionLevel target_el = is_host ?  EL2 : EL1;
-                TLBIALL tlbiOp(target_el, haveSecurity && !scr.ns);
+                TLBIVMALL tlbiOp(target_el, haveSecurity && !scr.ns, false);
                 tlbiOp.broadcast(tc);
                 return;
             }
index 38aa38ed01f2b259e6d2aabbf3a7430b8a4d974b..bad16d83b2cb5a67022de1ceb50a4f7a9a4fb6df 100644 (file)
@@ -329,6 +329,36 @@ TLB::flush(const TLBIALLEL &tlbi_op)
     }
 }
 
+void
+TLB::flush(const TLBIVMALL &tlbi_op)
+{
+    DPRINTF(TLB, "Flushing all TLB entries (%s lookup)\n",
+            (tlbi_op.secureLookup ? "secure" : "non-secure"));
+    int x = 0;
+    TlbEntry *te;
+    while (x < size) {
+        te = &table[x];
+        const bool el_match = te->checkELMatch(
+            tlbi_op.targetEL, tlbi_op.inHost);
+        if (te->valid && tlbi_op.secureLookup == !te->nstid &&
+            (te->vmid == vmid || !tlbi_op.el2Enabled) && el_match) {
+
+            DPRINTF(TLB, " -  %s\n", te->print());
+            te->valid = false;
+            stats.flushedEntries++;
+        }
+        ++x;
+    }
+
+    stats.flushTlb++;
+
+    // If there's a second stage TLB (and we're not it) then flush it as well
+    // if we're currently in hyp mode
+    if (!isStage2 && tlbi_op.stage2) {
+        stage2Tlb->flush(tlbi_op.makeStage2());
+    }
+}
+
 void
 TLB::flush(const TLBIALLN &tlbi_op)
 {
index b05c9ba30d8890c4a494ea7c8d5d8bdeb5f01e32..c157a261216558a58c499ff5db608081964b3833 100644 (file)
@@ -63,6 +63,7 @@ class TLB;
 
 class TLBIALL;
 class TLBIALLEL;
+class TLBIVMALL;
 class TLBIALLN;
 class TLBIMVA;
 class TLBIASID;
@@ -269,6 +270,11 @@ class TLB : public BaseTLB
      */
     void flush(const TLBIALLEL &tlbi_op);
 
+    /** Implementaton of AArch64 TLBI VMALLE1(IS)/VMALLS112E1(IS)
+     * instructions
+     */
+    void flush(const TLBIVMALL &tlbi_op);
+
     /** Remove all entries in the non secure world, depending on whether they
      *  were allocated in hyp mode or not
      */
index bb5153dd81248d2ead8a3c87b3ec62f2b36320a9..bd784ce1005e0933593c236cf8d04ba8b112d88b 100644 (file)
@@ -86,6 +86,21 @@ TLBIALLEL::operator()(ThreadContext* tc)
     }
 }
 
+void
+TLBIVMALL::operator()(ThreadContext* tc)
+{
+    HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    inHost = (hcr.tge == 1 && hcr.e2h == 1);
+
+    getMMUPtr(tc)->flush(*this);
+
+    // If CheckerCPU is connected, need to notify it of a flush
+    CheckerCPU *checker = tc->getCheckerCpuPtr();
+    if (checker) {
+        getMMUPtr(checker)->flush(*this);
+    }
+}
+
 void
 TLBIASID::operator()(ThreadContext* tc)
 {
index 888cd99d1767213ed762a4ab98905358bf1d550a..cab0e52ae5e6e8ad486420c85e81023fc3f651f1 100644 (file)
@@ -141,6 +141,28 @@ class TLBIALLEL : public TLBIOp
     bool inHost;
 };
 
+/** Implementaton of AArch64 TLBI VMALLE1(IS)/VMALLS112E1(IS) instructions */
+class TLBIVMALL : public TLBIOp
+{
+  public:
+    TLBIVMALL(ExceptionLevel _targetEL, bool _secure, bool _stage2)
+      : TLBIOp(_targetEL, _secure), inHost(false), el2Enabled(false),
+        stage2(_stage2)
+    {}
+
+    void operator()(ThreadContext* tc) override;
+
+    TLBIVMALL
+    makeStage2() const
+    {
+        return TLBIVMALL(EL1, secureLookup, false);
+    }
+
+    bool inHost;
+    bool el2Enabled;
+    bool stage2;
+};
+
 /** TLB Invalidate by ASID match */
 class TLBIASID : public TLBIOp
 {