diff --git a/src/arch/arm/mmu.cc b/src/arch/arm/mmu.cc index c3e487f025..0895cee2fb 100644 --- a/src/arch/arm/mmu.cc +++ b/src/arch/arm/mmu.cc @@ -36,6 +36,7 @@ */ #include "arch/arm/mmu.hh" +#include "arch/arm/tlbi_op.hh" using namespace ArmISA; @@ -66,84 +67,6 @@ MMU::invalidateMiscReg(TLBType type) } } -void -MMU::flushAllSecurity(bool secure_lookup, ExceptionLevel target_el, - TLBType type, bool ignore_el, bool in_host) -{ - if (type & TLBType::I_TLBS) { - getITBPtr()->flushAllSecurity( - secure_lookup, target_el, ignore_el, in_host); - } - if (type & TLBType::D_TLBS) { - getDTBPtr()->flushAllSecurity( - secure_lookup, target_el, ignore_el, in_host); - } -} - -void -MMU::flushAllNs(ExceptionLevel target_el, bool ignore_el, - TLBType type) -{ - if (type & TLBType::I_TLBS) { - getITBPtr()->flushAllNs(target_el, ignore_el); - } - if (type & TLBType::D_TLBS) { - getDTBPtr()->flushAllNs(target_el, ignore_el); - } -} - -void -MMU::flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup, - ExceptionLevel target_el, TLBType type, - bool in_host) -{ - if (type & TLBType::I_TLBS) { - getITBPtr()->flushMvaAsid( - mva, asn, secure_lookup, target_el, in_host); - } - if (type & TLBType::D_TLBS) { - getDTBPtr()->flushMvaAsid( - mva, asn, secure_lookup, target_el, in_host); - } -} - -void -MMU::flushAsid(uint64_t asn, bool secure_lookup, - ExceptionLevel target_el, TLBType type, - bool in_host) -{ - if (type & TLBType::I_TLBS) { - getITBPtr()->flushAsid(asn, secure_lookup, target_el, in_host); - } - if (type & TLBType::D_TLBS) { - getDTBPtr()->flushAsid(asn, secure_lookup, target_el, in_host); - } -} - -void -MMU::flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el, - TLBType type, bool in_host) -{ - if (type & TLBType::I_TLBS) { - getITBPtr()->flushMva(mva, secure_lookup, target_el, in_host); - } - if (type & TLBType::D_TLBS) { - getDTBPtr()->flushMva(mva, secure_lookup, target_el, in_host); - } -} - -void -MMU::flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el, - TLBType type) -{ - if (type & TLBType::I_TLBS) { - getITBPtr()->flushIpaVmid(ipa, secure_lookup, target_el); - } - if (type & TLBType::D_TLBS) { - getDTBPtr()->flushIpaVmid(ipa, secure_lookup, target_el); - } -} - ArmISA::MMU * ArmMMUParams::create() const { diff --git a/src/arch/arm/mmu.hh b/src/arch/arm/mmu.hh index cc4684f51b..e5adb9508f 100644 --- a/src/arch/arm/mmu.hh +++ b/src/arch/arm/mmu.hh @@ -79,58 +79,33 @@ class MMU : public BaseMMU void invalidateMiscReg(TLBType type = ALL_TLBS); - /** Reset the entire TLB - * @param secure_lookup if the operation affects the secure world - */ - void flushAllSecurity(bool secure_lookup, ExceptionLevel target_el, - TLBType type = ALL_TLBS, - bool ignore_el = false, bool in_host = false); + template + void + flush(const OP &tlbi_op) + { + getITBPtr()->flush(tlbi_op); + getDTBPtr()->flush(tlbi_op); + } - /** Remove all entries in the non secure world, depending on whether they - * were allocated in hyp mode or not - */ - void flushAllNs(ExceptionLevel target_el, bool ignore_el = false, - TLBType type = ALL_TLBS); + template + void + iflush(const OP &tlbi_op) + { + getITBPtr()->flush(tlbi_op); + } - /** Remove any entries that match both a va and asn - * @param mva virtual address to flush - * @param asn contextid/asn to flush on match - * @param secure_lookup if the operation affects the secure world - */ - void flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup, - ExceptionLevel target_el, TLBType type = ALL_TLBS, - bool in_host = false); - - /** Remove any entries that match the asn - * @param asn contextid/asn to flush on match - * @param secure_lookup if the operation affects the secure world - */ - void flushAsid(uint64_t asn, bool secure_lookup, - ExceptionLevel target_el, TLBType type = ALL_TLBS, - bool in_host = false); - - /** Remove all entries that match the va regardless of asn - * @param mva address to flush from cache - * @param secure_lookup if the operation affects the secure world - */ - void flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el, - TLBType type = ALL_TLBS, bool in_host = false); - - /** - * Invalidate all entries in the stage 2 TLB that match the given ipa - * and the current VMID - * @param ipa the address to invalidate - * @param secure_lookup if the operation affects the secure world - */ - void flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el, - TLBType type = ALL_TLBS); + template + void + dflush(const OP &tlbi_op) + { + getDTBPtr()->flush(tlbi_op); + } uint64_t getAttr() const { return getDTBPtr()->getAttr(); } - }; template diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 6f8b46f9ea..a8e0cb30a7 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -52,6 +52,7 @@ #include "arch/arm/stage2_mmu.hh" #include "arch/arm/system.hh" #include "arch/arm/table_walker.hh" +#include "arch/arm/tlbi_op.hh" #include "arch/arm/utility.hh" #include "base/inifile.hh" #include "base/str.hh" @@ -269,19 +270,18 @@ TLB::flushAll() } void -TLB::flushAllSecurity(bool secure_lookup, ExceptionLevel target_el, - bool ignore_el, bool in_host) +TLB::flush(const TLBIALL& tlbi_op) { DPRINTF(TLB, "Flushing all TLB entries (%s lookup)\n", - (secure_lookup ? "secure" : "non-secure")); + (tlbi_op.secureLookup ? "secure" : "non-secure")); int x = 0; TlbEntry *te; while (x < size) { te = &table[x]; - const bool el_match = ignore_el ? - true : te->checkELMatch(target_el, in_host); - if (te->valid && secure_lookup == !te->nstid && - (te->vmid == vmid || secure_lookup) && el_match) { + 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.secureLookup) && el_match) { DPRINTF(TLB, " - %s\n", te->print()); te->valid = false; @@ -295,14 +295,14 @@ TLB::flushAllSecurity(bool secure_lookup, ExceptionLevel target_el, // 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->flushAllSecurity(secure_lookup, EL1, true, false); + stage2Tlb->flush(tlbi_op.makeStage2()); } } void -TLB::flushAllNs(ExceptionLevel target_el, bool ignore_el) +TLB::flush(const TLBIALLN &tlbi_op) { - bool hyp = target_el == EL2; + bool hyp = tlbi_op.targetEL == EL2; DPRINTF(TLB, "Flushing all NS TLB entries (%s lookup)\n", (hyp ? "hyp" : "non-hyp")); @@ -310,8 +310,7 @@ TLB::flushAllNs(ExceptionLevel target_el, bool ignore_el) TlbEntry *te; while (x < size) { te = &table[x]; - const bool el_match = ignore_el ? - true : te->checkELMatch(target_el, false); + const bool el_match = te->checkELMatch(tlbi_op.targetEL, false); if (te->valid && te->nstid && te->isHyp == hyp && el_match) { @@ -326,36 +325,36 @@ TLB::flushAllNs(ExceptionLevel target_el, bool ignore_el) // If there's a second stage TLB (and we're not it) then flush it as well if (!isStage2 && !hyp) { - stage2Tlb->flushAllNs(EL1, true); + stage2Tlb->flush(tlbi_op.makeStage2()); } } void -TLB::flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup, - ExceptionLevel target_el, bool in_host) +TLB::flush(const TLBIMVA &tlbi_op) { DPRINTF(TLB, "Flushing TLB entries with mva: %#x, asid: %#x " - "(%s lookup)\n", mva, asn, (secure_lookup ? - "secure" : "non-secure")); - _flushMva(mva, asn, secure_lookup, false, target_el, in_host); + "(%s lookup)\n", tlbi_op.addr, tlbi_op.asid, + (tlbi_op.secureLookup ? "secure" : "non-secure")); + _flushMva(tlbi_op.addr, tlbi_op.asid, tlbi_op.secureLookup, false, + tlbi_op.targetEL, tlbi_op.inHost); stats.flushTlbMvaAsid++; } void -TLB::flushAsid(uint64_t asn, bool secure_lookup, ExceptionLevel target_el, - bool in_host) +TLB::flush(const TLBIASID &tlbi_op) { - DPRINTF(TLB, "Flushing TLB entries with asid: %#x (%s lookup)\n", asn, - (secure_lookup ? "secure" : "non-secure")); + DPRINTF(TLB, "Flushing TLB entries with asid: %#x (%s lookup)\n", + tlbi_op.asid, (tlbi_op.secureLookup ? "secure" : "non-secure")); int x = 0 ; TlbEntry *te; while (x < size) { te = &table[x]; - if (te->valid && te->asid == asn && secure_lookup == !te->nstid && - (te->vmid == vmid || secure_lookup) && - te->checkELMatch(target_el, in_host)) { + if (te->valid && te->asid == tlbi_op.asid && + tlbi_op.secureLookup == !te->nstid && + (te->vmid == vmid || tlbi_op.secureLookup) && + te->checkELMatch(tlbi_op.targetEL, tlbi_op.inHost)) { te->valid = false; DPRINTF(TLB, " - %s\n", te->print()); @@ -367,12 +366,13 @@ TLB::flushAsid(uint64_t asn, bool secure_lookup, ExceptionLevel target_el, } void -TLB::flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el, - bool in_host) { +TLB::flush(const TLBIMVAA &tlbi_op) { - DPRINTF(TLB, "Flushing TLB entries with mva: %#x (%s lookup)\n", mva, - (secure_lookup ? "secure" : "non-secure")); - _flushMva(mva, 0xbeef, secure_lookup, true, target_el, in_host); + DPRINTF(TLB, "Flushing TLB entries with mva: %#x (%s lookup)\n", + tlbi_op.addr, + (tlbi_op.secureLookup ? "secure" : "non-secure")); + _flushMva(tlbi_op.addr, 0xbeef, tlbi_op.secureLookup, true, + tlbi_op.targetEL, tlbi_op.inHost); stats.flushTlbMva++; } @@ -400,10 +400,11 @@ TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup, } void -TLB::flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el) +TLB::flush(const TLBIIPA &tlbi_op) { assert(!isStage2); - stage2Tlb->_flushMva(ipa, 0xbeef, secure_lookup, true, target_el, false); + stage2Tlb->_flushMva(tlbi_op.addr, 0xbeef, tlbi_op.secureLookup, + true, tlbi_op.targetEL, false); } void diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index 6363b7c009..5007b3ce39 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -61,6 +61,13 @@ class Stage2LookUp; class Stage2MMU; class TLB; +class TLBIALL; +class TLBIALLN; +class TLBIMVA; +class TLBIASID; +class TLBIMVAA; +class TLBIIPA; + class TlbTestInterface { public: @@ -253,46 +260,31 @@ class TLB : public BaseTLB /** Reset the entire TLB - * @param secure_lookup if the operation affects the secure world */ - void flushAllSecurity(bool secure_lookup, ExceptionLevel target_el, - bool ignore_el = false, bool in_host = false); + void flush(const TLBIALL& tlbi_op); /** Remove all entries in the non secure world, depending on whether they * were allocated in hyp mode or not */ - void flushAllNs(ExceptionLevel target_el, bool ignore_el = false); - + void flush(const TLBIALLN &tlbi_op); /** Remove any entries that match both a va and asn - * @param mva virtual address to flush - * @param asn contextid/asn to flush on match - * @param secure_lookup if the operation affects the secure world */ - void flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup, - ExceptionLevel target_el, bool in_host = false); + void flush(const TLBIMVA &tlbi_op); /** Remove any entries that match the asn - * @param asn contextid/asn to flush on match - * @param secure_lookup if the operation affects the secure world */ - void flushAsid(uint64_t asn, bool secure_lookup, - ExceptionLevel target_el, bool in_host = false); + void flush(const TLBIASID &tlbi_op); /** Remove all entries that match the va regardless of asn - * @param mva address to flush from cache - * @param secure_lookup if the operation affects the secure world */ - void flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el, - bool in_host = false); + void flush(const TLBIMVAA &tlbi_op); /** * Invalidate all entries in the stage 2 TLB that match the given ipa * and the current VMID - * @param ipa the address to invalidate - * @param secure_lookup if the operation affects the secure world */ - void flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el); + void flush(const TLBIIPA &tlbi_op); Fault trickBoxCheck(const RequestPtr &req, Mode mode, TlbEntry::DomainType domain); diff --git a/src/arch/arm/tlbi_op.cc b/src/arch/arm/tlbi_op.cc index dd14a90dc3..76a3096574 100644 --- a/src/arch/arm/tlbi_op.cc +++ b/src/arch/arm/tlbi_op.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 ARM Limited + * Copyright (c) 2018-2020 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -46,64 +46,60 @@ void TLBIALL::operator()(ThreadContext* tc) { HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); - bool in_host = (hcr.tge == 1 && hcr.e2h == 1); - getMMUPtr(tc)->flushAllSecurity(secureLookup, targetEL, - MMU::ALL_TLBS, in_host); + 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)->flushAllSecurity( - secureLookup, targetEL, MMU::ALL_TLBS, in_host); + getMMUPtr(checker)->flush(*this); } } void ITLBIALL::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushAllSecurity(secureLookup, targetEL, MMU::I_TLBS); + getMMUPtr(tc)->iflush(*this); } void DTLBIALL::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushAllSecurity(secureLookup, targetEL, MMU::D_TLBS); + getMMUPtr(tc)->dflush(*this); } void TLBIASID::operator()(ThreadContext* tc) { HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); - bool in_host = (hcr.tge == 1 && hcr.e2h == 1); - getMMUPtr(tc)->flushAsid(asid, secureLookup, targetEL, - MMU::ALL_TLBS, in_host); + inHost = (hcr.tge == 1 && hcr.e2h == 1); + getMMUPtr(tc)->flush(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flushAsid(asid, secureLookup, targetEL, - MMU::ALL_TLBS, in_host); + getMMUPtr(checker)->flush(*this); } } void ITLBIASID::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushAsid(asid, secureLookup, targetEL, MMU::I_TLBS); + getMMUPtr(tc)->iflush(*this); } void DTLBIASID::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushAsid(asid, secureLookup, targetEL, MMU::D_TLBS); + getMMUPtr(tc)->dflush(*this); } void TLBIALLN::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushAllNs(targetEL); + getMMUPtr(tc)->flush(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flushAllNs(targetEL); + getMMUPtr(checker)->flush(*this); } } @@ -111,14 +107,12 @@ void TLBIMVAA::operator()(ThreadContext* tc) { HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); - bool in_host = (hcr.tge == 1 && hcr.e2h == 1); - getMMUPtr(tc)->flushMva(addr, secureLookup, targetEL, - MMU::ALL_TLBS, in_host); + inHost = (hcr.tge == 1 && hcr.e2h == 1); + getMMUPtr(tc)->flush(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flushMva(addr, secureLookup, targetEL, - MMU::ALL_TLBS, in_host); + getMMUPtr(checker)->flush(*this); } } @@ -126,41 +120,35 @@ void TLBIMVA::operator()(ThreadContext* tc) { HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); - bool in_host = (hcr.tge == 1 && hcr.e2h == 1); - getMMUPtr(tc)->flushMvaAsid(addr, asid, - secureLookup, targetEL, MMU::ALL_TLBS, in_host); + inHost = (hcr.tge == 1 && hcr.e2h == 1); + getMMUPtr(tc)->flush(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flushMvaAsid( - addr, asid, secureLookup, targetEL, MMU::ALL_TLBS, in_host); + getMMUPtr(checker)->flush(*this); } } void ITLBIMVA::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushMvaAsid( - addr, asid, secureLookup, targetEL, MMU::I_TLBS); + getMMUPtr(tc)->iflush(*this); } void DTLBIMVA::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushMvaAsid( - addr, asid, secureLookup, targetEL, MMU::D_TLBS); + getMMUPtr(tc)->dflush(*this); } void TLBIIPA::operator()(ThreadContext* tc) { - getMMUPtr(tc)->flushIpaVmid(addr, - secureLookup, targetEL); + getMMUPtr(tc)->flush(*this); CheckerCPU *checker = tc->getCheckerCpuPtr(); if (checker) { - getMMUPtr(checker)->flushIpaVmid(addr, - secureLookup, targetEL); + getMMUPtr(checker)->flush(*this); } } diff --git a/src/arch/arm/tlbi_op.hh b/src/arch/arm/tlbi_op.hh index 511d70ed39..5371da04d0 100644 --- a/src/arch/arm/tlbi_op.hh +++ b/src/arch/arm/tlbi_op.hh @@ -72,7 +72,6 @@ class TLBIOp (*this)(oc); } - protected: bool secureLookup; ExceptionLevel targetEL; }; @@ -82,10 +81,18 @@ class TLBIALL : public TLBIOp { public: TLBIALL(ExceptionLevel _targetEL, bool _secure) - : TLBIOp(_targetEL, _secure) + : TLBIOp(_targetEL, _secure), inHost(false) {} void operator()(ThreadContext* tc) override; + + TLBIALL + makeStage2() const + { + return TLBIALL(EL1, secureLookup); + } + + bool inHost; }; /** Instruction TLB Invalidate All */ @@ -119,13 +126,13 @@ class TLBIASID : public TLBIOp { public: TLBIASID(ExceptionLevel _targetEL, bool _secure, uint16_t _asid) - : TLBIOp(_targetEL, _secure), asid(_asid) + : TLBIOp(_targetEL, _secure), asid(_asid), inHost(false) {} void operator()(ThreadContext* tc) override; - protected: uint16_t asid; + bool inHost; }; /** Instruction TLB Invalidate by ASID match */ @@ -163,6 +170,12 @@ class TLBIALLN : public TLBIOp {} void operator()(ThreadContext* tc) override; + + TLBIALLN + makeStage2() const + { + return TLBIALLN(EL1); + } }; /** TLB Invalidate by VA, All ASID */ @@ -171,13 +184,13 @@ class TLBIMVAA : public TLBIOp public: TLBIMVAA(ExceptionLevel _targetEL, bool _secure, Addr _addr) - : TLBIOp(_targetEL, _secure), addr(_addr) + : TLBIOp(_targetEL, _secure), addr(_addr), inHost(false) {} void operator()(ThreadContext* tc) override; - protected: Addr addr; + bool inHost; }; /** TLB Invalidate by VA */ @@ -186,14 +199,15 @@ class TLBIMVA : public TLBIOp public: TLBIMVA(ExceptionLevel _targetEL, bool _secure, Addr _addr, uint16_t _asid) - : TLBIOp(_targetEL, _secure), addr(_addr), asid(_asid) + : TLBIOp(_targetEL, _secure), addr(_addr), asid(_asid), + inHost(false) {} void operator()(ThreadContext* tc) override; - protected: Addr addr; uint16_t asid; + bool inHost; }; /** Instruction TLB Invalidate by VA */ @@ -234,7 +248,6 @@ class TLBIIPA : public TLBIOp void operator()(ThreadContext* tc) override; - protected: Addr addr; };