Giacomo Travaglini has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/35241 )

Change subject: arch-arm: Fix implementation of TLBI ALLEx instructions
......................................................................

arch-arm: Fix implementation of TLBI ALLEx instructions

The TLBIALL op in gem5 was designed after the AArch32 TLBIALL instruction.
and was reused by the TLBI ALLEL1, ALLE2, ALLE3 logic.

This is not correct for the following reasons:

- TLBI ALLEx invalidates regardless of the VMID
- TLBI ALLEx (AArch64) is "target regime" oriented, whereas TLBIALL
  (AArch32) is "current regime" oriented

TLBIALL has a different behaviour depending on the current exception
level: if issued at EL1 it will invalidate stage1 translations only; if
at EL2, it will invalidate stage2 translations as well.

TLBI ALLEx is more standard; every TLBI ALLE1 will invalidate stage1 and
stage2 translations. This is because the instruction is not executable
from the guest (EL1)

So for TLBIALL the condition for stage2 forwarding will be:

if (!isStage2 && isHyp) {

Whereas for TLBI ALLEx will be:

if (!isStage2 && target_el == EL1) {

Change-Id: I282f2cfaecbfc883e173770e5d2578b41055bb7a
Signed-off-by: Giacomo Travaglini <[email protected]>
---
M src/arch/arm/isa.cc
M src/arch/arm/tlb.cc
M src/arch/arm/tlb.hh
M src/arch/arm/tlbi_op.cc
M src/arch/arm/tlbi_op.hh
5 files changed, 94 insertions(+), 7 deletions(-)



diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index cfef0ab..ba96722 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -1698,7 +1698,7 @@
             {
                 assert64();

-                TLBIALL tlbiOp(EL3, true);
+                TLBIALLEL tlbiOp(EL3, true);
                 tlbiOp(tc);
                 return;
             }
@@ -1707,7 +1707,7 @@
             {
                 assert64();

-                TLBIALL tlbiOp(EL3, true);
+                TLBIALLEL tlbiOp(EL3, true);
                 tlbiOp.broadcast(tc);
                 return;
             }
@@ -1717,7 +1717,7 @@
                 assert64();
                 scr = readMiscReg(MISCREG_SCR);

-                TLBIALL tlbiOp(EL2, haveSecurity && !scr.ns);
+                TLBIALLEL tlbiOp(EL2, haveSecurity && !scr.ns);
                 tlbiOp(tc);
                 return;
             }
@@ -1727,12 +1727,30 @@
                 assert64();
                 scr = readMiscReg(MISCREG_SCR);

-                TLBIALL tlbiOp(EL2, haveSecurity && !scr.ns);
+                TLBIALLEL tlbiOp(EL2, haveSecurity && !scr.ns);
                 tlbiOp.broadcast(tc);
                 return;
             }
           // AArch64 TLB Invalidate All, EL1
           case MISCREG_TLBI_ALLE1:
+            {
+                assert64();
+                scr = readMiscReg(MISCREG_SCR);
+
+                TLBIALLEL tlbiOp(EL1, haveSecurity && !scr.ns);
+                tlbiOp(tc);
+                return;
+            }
+          // AArch64 TLB Invalidate All, EL1, Inner Shareable
+          case MISCREG_TLBI_ALLE1IS:
+            {
+                assert64();
+                scr = readMiscReg(MISCREG_SCR);
+
+                TLBIALLEL tlbiOp(EL1, haveSecurity && !scr.ns);
+                tlbiOp.broadcast(tc);
+                return;
+            }
           case MISCREG_TLBI_VMALLS12E1:
             // @todo: handle VMID and stage 2 to enable Virtualization
             {
@@ -1756,8 +1774,6 @@
                 tlbiOp(tc);
                 return;
             }
-          // AArch64 TLB Invalidate All, EL1, Inner Shareable
-          case MISCREG_TLBI_ALLE1IS:
           case MISCREG_TLBI_VMALLS12E1IS:
             // @todo: handle VMID and stage 2 to enable Virtualization
             {
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 3ab0e6e..861c270 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -299,6 +299,36 @@
 }

 void
+TLB::flush(const TLBIALLEL &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 && 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)
+    // and if we're targeting EL1
+    // then flush it as well
+    if (!isStage2 && tlbi_op.targetEL == EL1) {
+        stage2Tlb->flush(tlbi_op.makeStage2());
+    }
+}
+
+void
 TLB::flush(const TLBIALLN &tlbi_op)
 {
     bool hyp = tlbi_op.targetEL == EL2;
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index 753b8b5..e550cf6 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -62,6 +62,7 @@
 class TLB;

 class TLBIALL;
+class TLBIALLEL;
 class TLBIALLN;
 class TLBIMVA;
 class TLBIASID;
@@ -261,7 +262,12 @@

     /** Reset the entire TLB
      */
-    void flush(const TLBIALL& tlbi_op);
+    void flush(const TLBIALL &tlbi_op);
+
+    /** Implementaton of AArch64 TLBI ALLE1(IS), ALLE2(IS), ALLE3(IS)
+     * instructions
+     */
+    void flush(const TLBIALLEL &tlbi_op);

/** Remove all entries in the non secure world, depending on whether they
      *  were allocated in hyp mode or not
diff --git a/src/arch/arm/tlbi_op.cc b/src/arch/arm/tlbi_op.cc
index f1ba30b..a5e03ce 100644
--- a/src/arch/arm/tlbi_op.cc
+++ b/src/arch/arm/tlbi_op.cc
@@ -71,6 +71,22 @@
 }

 void
+TLBIALLEL::operator()(ThreadContext* tc)
+{
+    HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    inHost = (hcr.tge == 1 && hcr.e2h == 1);
+    getITBPtr(tc)->flush(*this);
+    getDTBPtr(tc)->flush(*this);
+
+    // If CheckerCPU is connected, need to notify it of a flush
+    CheckerCPU *checker = tc->getCheckerCpuPtr();
+    if (checker) {
+        getITBPtr(checker)->flush(*this);
+        getDTBPtr(checker)->flush(*this);
+    }
+}
+
+void
 TLBIASID::operator()(ThreadContext* tc)
 {
     HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
diff --git a/src/arch/arm/tlbi_op.hh b/src/arch/arm/tlbi_op.hh
index 5371da0..8b40587 100644
--- a/src/arch/arm/tlbi_op.hh
+++ b/src/arch/arm/tlbi_op.hh
@@ -121,6 +121,25 @@
     void operator()(ThreadContext* tc) override;
 };

+/** Implementaton of AArch64 TLBI ALLE(1,2,3)(IS) instructions */
+class TLBIALLEL : public TLBIOp
+{
+  public:
+    TLBIALLEL(ExceptionLevel _targetEL, bool _secure)
+      : TLBIOp(_targetEL, _secure), inHost(false)
+    {}
+
+    void operator()(ThreadContext* tc) override;
+
+    TLBIALLEL
+    makeStage2() const
+    {
+        return TLBIALLEL(EL1, secureLookup);
+    }
+
+    bool inHost;
+};
+
 /** TLB Invalidate by ASID match */
 class TLBIASID : public TLBIOp
 {

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/35241
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I282f2cfaecbfc883e173770e5d2578b41055bb7a
Gerrit-Change-Number: 35241
Gerrit-PatchSet: 1
Gerrit-Owner: Giacomo Travaglini <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to