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 <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/35241
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
{
assert64();
- TLBIALL tlbiOp(EL3, true);
+ TLBIALLEL tlbiOp(EL3, true);
tlbiOp(tc);
return;
}
{
assert64();
- TLBIALL tlbiOp(EL3, true);
+ TLBIALLEL tlbiOp(EL3, true);
tlbiOp.broadcast(tc);
return;
}
assert64();
scr = readMiscReg(MISCREG_SCR);
- TLBIALL tlbiOp(EL2, haveSecurity && !scr.ns);
+ TLBIALLEL tlbiOp(EL2, haveSecurity && !scr.ns);
tlbiOp(tc);
return;
}
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
{
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
{
}
}
+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)
{
class TLB;
class TLBIALL;
+class TLBIALLEL;
class TLBIALLN;
class TLBIMVA;
class TLBIASID;
/** 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
getMMUPtr(tc)->dflush(*this);
}
+void
+TLBIALLEL::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)
{
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
{