From e9ee6b1c690e9c321c2e9b90b1ec1b43dfd3325e Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 18 Sep 2020 10:33:24 +0100 Subject: [PATCH] arch-arm: Fix implementation of TLBI_VMALL instructions Same as 73dfc5f89b81e622a2330b1b52e055cafcc9178b: there's a difference on how AArch64 and AArch32 treat stage2 invalidation. Change-Id: I6fede4d9cb82e4bae9163326d38db9351d2a3880 Signed-off-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/35243 Reviewed-by: Nikos Nikoleris Tested-by: kokoro --- src/arch/arm/isa.cc | 12 ++++-------- src/arch/arm/tlb.cc | 30 ++++++++++++++++++++++++++++++ src/arch/arm/tlb.hh | 6 ++++++ src/arch/arm/tlbi_op.cc | 15 +++++++++++++++ src/arch/arm/tlbi_op.hh | 22 ++++++++++++++++++++++ 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 1866319ed..217f432ac 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -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; } diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 38aa38ed0..bad16d83b 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -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) { diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index b05c9ba30..c157a2612 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -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 */ diff --git a/src/arch/arm/tlbi_op.cc b/src/arch/arm/tlbi_op.cc index bb5153dd8..bd784ce10 100644 --- a/src/arch/arm/tlbi_op.cc +++ b/src/arch/arm/tlbi_op.cc @@ -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) { diff --git a/src/arch/arm/tlbi_op.hh b/src/arch/arm/tlbi_op.hh index 888cd99d1..cab0e52ae 100644 --- a/src/arch/arm/tlbi_op.hh +++ b/src/arch/arm/tlbi_op.hh @@ -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 { -- 2.30.2