From af1e8667e1527150cafc149e3cc658b8d5846a6a Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 6 Oct 2020 13:51:44 +0100 Subject: [PATCH] arch-arm: Remove stage2 TLBI flushes from stage1 flushes This is not needed anymore as stage2 flush is now handled by the MMU. With this patch we are progressively removing any link between stage1 and stage2 TLBs Change-Id: I3e9e339a78ac972bc536214152f6c68d6a50cb5c Signed-off-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/45781 Tested-by: kokoro --- src/arch/arm/mmu.hh | 25 +++++++++++++++++-- src/arch/arm/tlb.cc | 29 ---------------------- src/arch/arm/tlbi_op.cc | 13 +++++----- src/arch/arm/tlbi_op.hh | 53 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 82 insertions(+), 38 deletions(-) diff --git a/src/arch/arm/mmu.hh b/src/arch/arm/mmu.hh index 23fd5a253d..6d35b3f3c8 100644 --- a/src/arch/arm/mmu.hh +++ b/src/arch/arm/mmu.hh @@ -105,8 +105,29 @@ class MMU : public BaseMMU void flush(const OP &tlbi_op) { - getITBPtr()->flush(tlbi_op); - getDTBPtr()->flush(tlbi_op); + if (tlbi_op.stage1Flush()) { + flushStage1(tlbi_op); + } + + if (tlbi_op.stage2Flush()) { + flushStage2(tlbi_op.makeStage2()); + } + } + + template + void + flushStage1(const OP &tlbi_op) + { + iflush(tlbi_op); + dflush(tlbi_op); + } + + template + void + flushStage2(const OP &tlbi_op) + { + itbStage2->flush(tlbi_op); + dtbStage2->flush(tlbi_op); } template diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 0f8a8d6bf5..d759819bc7 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -283,11 +283,6 @@ TLB::flushAll() } stats.flushTlb++; - - // If there's a second stage TLB (and we're not it) then flush it as well - if (!isStage2) { - stage2Tlb->flushAll(); - } } void @@ -312,12 +307,6 @@ TLB::flush(const TLBIALL& tlbi_op) } 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 && isHyp) { - stage2Tlb->flush(tlbi_op.makeStage2()); - } } void @@ -341,13 +330,6 @@ TLB::flush(const TLBIALLEL &tlbi_op) } 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 @@ -372,12 +354,6 @@ TLB::flush(const TLBIVMALL &tlbi_op) } 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 @@ -403,11 +379,6 @@ TLB::flush(const TLBIALLN &tlbi_op) } stats.flushTlb++; - - // If there's a second stage TLB (and we're not it) then flush it as well - if (!isStage2 && !hyp) { - stage2Tlb->flush(tlbi_op.makeStage2()); - } } void diff --git a/src/arch/arm/tlbi_op.cc b/src/arch/arm/tlbi_op.cc index bd784ce100..5bcc009d82 100644 --- a/src/arch/arm/tlbi_op.cc +++ b/src/arch/arm/tlbi_op.cc @@ -48,6 +48,7 @@ TLBIALL::operator()(ThreadContext* tc) HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); inHost = (hcr.tge == 1 && hcr.e2h == 1); el2Enabled = EL2Enabled(tc); + currentEL = currEL(tc); getMMUPtr(tc)->flush(*this); @@ -108,10 +109,10 @@ TLBIASID::operator()(ThreadContext* tc) inHost = (hcr.tge == 1 && hcr.e2h == 1); el2Enabled = EL2Enabled(tc); - getMMUPtr(tc)->flush(*this); + getMMUPtr(tc)->flushStage1(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flush(*this); + getMMUPtr(checker)->flushStage1(*this); } } @@ -145,11 +146,11 @@ TLBIMVAA::operator()(ThreadContext* tc) { HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); inHost = (hcr.tge == 1 && hcr.e2h == 1); - getMMUPtr(tc)->flush(*this); + getMMUPtr(tc)->flushStage1(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flush(*this); + getMMUPtr(checker)->flushStage1(*this); } } @@ -158,11 +159,11 @@ TLBIMVA::operator()(ThreadContext* tc) { HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); inHost = (hcr.tge == 1 && hcr.e2h == 1); - getMMUPtr(tc)->flush(*this); + getMMUPtr(tc)->flushStage1(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flush(*this); + getMMUPtr(checker)->flushStage1(*this); } } diff --git a/src/arch/arm/tlbi_op.hh b/src/arch/arm/tlbi_op.hh index ce72dfbca3..924aabde38 100644 --- a/src/arch/arm/tlbi_op.hh +++ b/src/arch/arm/tlbi_op.hh @@ -72,6 +72,28 @@ class TLBIOp (*this)(oc); } + /** + * Return true if the TLBI op needs to flush stage1 + * entries, Defaulting to true in the TLBIOp abstract + * class + */ + virtual bool + stage1Flush() const + { + return true; + } + + /** + * Return true if the TLBI op needs to flush stage2 + * entries, Defaulting to false in the TLBIOp abstract + * class + */ + virtual bool + stage2Flush() const + { + return false; + } + bool secureLookup; ExceptionLevel targetEL; }; @@ -81,11 +103,20 @@ class TLBIALL : public TLBIOp { public: TLBIALL(ExceptionLevel _targetEL, bool _secure) - : TLBIOp(_targetEL, _secure), inHost(false), el2Enabled(false) + : TLBIOp(_targetEL, _secure), inHost(false), el2Enabled(false), + currentEL(EL0) {} void operator()(ThreadContext* tc) override; + bool + stage2Flush() const override + { + // TLBIALL (AArch32) flushing stage2 entries if we're currently + // in hyp mode + return currentEL == EL2; + } + TLBIALL makeStage2() const { @@ -94,6 +125,7 @@ class TLBIALL : public TLBIOp bool inHost; bool el2Enabled; + ExceptionLevel currentEL; }; /** Instruction TLB Invalidate All */ @@ -132,6 +164,13 @@ class TLBIALLEL : public TLBIOp void operator()(ThreadContext* tc) override; + bool + stage2Flush() const override + { + // If we're targeting EL1 then flush stage2 as well + return targetEL == EL1; + } + TLBIALLEL makeStage2() const { @@ -152,6 +191,12 @@ class TLBIVMALL : public TLBIOp void operator()(ThreadContext* tc) override; + bool + stage2Flush() const override + { + return stage2; + } + TLBIVMALL makeStage2() const { @@ -215,6 +260,12 @@ class TLBIALLN : public TLBIOp void operator()(ThreadContext* tc) override; + bool + stage2Flush() const override + { + return targetEL != EL2; + } + TLBIALLN makeStage2() const {