diff --git a/src/arch/arm/ArmMMU.py b/src/arch/arm/ArmMMU.py index 8cafc2c624..8a7cb80a75 100644 --- a/src/arch/arm/ArmMMU.py +++ b/src/arch/arm/ArmMMU.py @@ -72,7 +72,9 @@ class ArmMMU(BaseMMU): cxx_header = "arch/arm/mmu.hh" # L2 TLBs - l2_shared = ArmTLB(entry_type="unified", size=1280, partial_levels=["L2"]) + l2_shared = ArmTLB( + entry_type="unified", size=1280, assoc=5, partial_levels=["L2"] + ) # L1 TLBs itb = ArmTLB(entry_type="instruction", next_level=Parent.l2_shared) diff --git a/src/arch/arm/ArmTLB.py b/src/arch/arm/ArmTLB.py index c868a322f1..16a245137e 100644 --- a/src/arch/arm/ArmTLB.py +++ b/src/arch/arm/ArmTLB.py @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2009, 2013, 2015, 2021 Arm Limited +# Copyright (c) 2009, 2013, 2015, 2021, 2024 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -36,6 +36,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.BaseTLB import BaseTLB +from m5.objects.ReplacementPolicies import LRURP from m5.params import * from m5.proxy import * from m5.SimObject import SimObject @@ -45,12 +46,42 @@ class ArmLookupLevel(Enum): vals = ["L0", "L1", "L2", "L3"] +class TLBIndexingPolicy(SimObject): + type = "TLBIndexingPolicy" + abstract = True + cxx_class = "gem5::IndexingPolicyTemplate" + cxx_header = "arch/arm/pagetable.hh" + cxx_template_params = ["class Types"] + + # Get the size from the parent (cache) + num_entries = Param.Int(Parent.size, "number of TLB entries") + + # Get the associativity + assoc = Param.Int(Parent.assoc, "associativity") + + +class TLBSetAssociative(TLBIndexingPolicy): + type = "TLBSetAssociative" + cxx_class = "gem5::ArmISA::TLBSetAssociative" + cxx_header = "arch/arm/pagetable.hh" + + class ArmTLB(BaseTLB): type = "ArmTLB" cxx_class = "gem5::ArmISA::TLB" cxx_header = "arch/arm/tlb.hh" sys = Param.System(Parent.any, "system object parameter") size = Param.Int(64, "TLB size") + assoc = Param.Int( + Self.size, "Associativity of the TLB. Fully Associative by default" + ) + indexing_policy = Param.TLBIndexingPolicy( + TLBSetAssociative(assoc=Parent.assoc, num_entries=Parent.size), + "Indexing policy of the TLB", + ) + replacement_policy = Param.BaseReplacementPolicy( + LRURP(), "Replacement policy of the TLB" + ) is_stage2 = Param.Bool(False, "Is this a stage 2 TLB?") partial_levels = VectorParam.ArmLookupLevel( diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index 948cefb4e4..b555c6f12c 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -38,104 +38,127 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') +Import("*") -Source('insts/fplib.cc') +Source("insts/fplib.cc") -if env['CONF']['USE_ARM_ISA']: - env.TagImplies('arm isa', 'gem5 lib') +if env["CONF"]["USE_ARM_ISA"]: + env.TagImplies("arm isa", "gem5 lib") # The GTest function does not have a 'tags' parameter. We therefore apply this # guard to ensure this test is only built when ARM is compiled. # # Note: This will need reconfigured for multi-isa. E.g., if this is # incorporated: https://gem5-review.googlesource.com/c/public/gem5/+/52491 -if env['CONF']['USE_ARM_ISA']: - GTest('aapcs64.test', 'aapcs64.test.cc', - '../../base/debug.cc', - '../../cpu/reg_class.cc', - '../../sim/bufval.cc', '../../sim/cur_tick.cc', - 'regs/int.cc') - GTest('matrix.test', 'matrix.test.cc') -Source('decoder.cc', tags='arm isa') -Source('faults.cc', tags='arm isa') -Source('htm.cc', tags='arm isa') -Source('insts/branch.cc', tags='arm isa') -Source('insts/branch64.cc', tags='arm isa') -Source('insts/data64.cc', tags='arm isa') -Source('insts/macromem.cc', tags='arm isa') -Source('insts/mem.cc', tags='arm isa') -Source('insts/mem64.cc', tags='arm isa') -Source('insts/misc.cc', tags='arm isa') -Source('insts/misc64.cc', tags='arm isa') -Source('insts/pred_inst.cc', tags='arm isa') -Source('insts/pseudo.cc', tags='arm isa') -Source('insts/sme.cc', tags='arm isa') -Source('insts/static_inst.cc', tags='arm isa') -Source('insts/sve.cc', tags='arm isa') -Source('insts/sve_mem.cc', tags='arm isa') -Source('insts/vfp.cc', tags='arm isa') -Source('insts/crypto.cc', tags='arm isa') -Source('insts/tme64.cc', tags='arm isa') -if env['CONF']['PROTOCOL'] == 'MESI_Three_Level_HTM': - Source('insts/tme64ruby.cc', tags='arm isa') +if env["CONF"]["USE_ARM_ISA"]: + GTest( + "aapcs64.test", + "aapcs64.test.cc", + "../../base/debug.cc", + "../../cpu/reg_class.cc", + "../../sim/bufval.cc", + "../../sim/cur_tick.cc", + "regs/int.cc", + ) + GTest("matrix.test", "matrix.test.cc") +Source("decoder.cc", tags="arm isa") +Source("faults.cc", tags="arm isa") +Source("htm.cc", tags="arm isa") +Source("insts/branch.cc", tags="arm isa") +Source("insts/branch64.cc", tags="arm isa") +Source("insts/data64.cc", tags="arm isa") +Source("insts/macromem.cc", tags="arm isa") +Source("insts/mem.cc", tags="arm isa") +Source("insts/mem64.cc", tags="arm isa") +Source("insts/misc.cc", tags="arm isa") +Source("insts/misc64.cc", tags="arm isa") +Source("insts/pred_inst.cc", tags="arm isa") +Source("insts/pseudo.cc", tags="arm isa") +Source("insts/sme.cc", tags="arm isa") +Source("insts/static_inst.cc", tags="arm isa") +Source("insts/sve.cc", tags="arm isa") +Source("insts/sve_mem.cc", tags="arm isa") +Source("insts/vfp.cc", tags="arm isa") +Source("insts/crypto.cc", tags="arm isa") +Source("insts/tme64.cc", tags="arm isa") +if env["CONF"]["PROTOCOL"] == "MESI_Three_Level_HTM": + Source("insts/tme64ruby.cc", tags="arm isa") else: - Source('insts/tme64classic.cc', tags='arm isa') -Source('interrupts.cc', tags='arm isa') -Source('isa.cc', tags='arm isa') -Source('isa_device.cc', tags='arm isa') -Source('linux/process.cc', tags='arm isa') -Source('linux/se_workload.cc', tags='arm isa') -Source('linux/fs_workload.cc', tags='arm isa') -Source('freebsd/fs_workload.cc', tags='arm isa') -Source('freebsd/se_workload.cc', tags='arm isa') -Source('fs_workload.cc', tags='arm isa') -Source('regs/int.cc', tags='arm isa') -Source('regs/misc.cc', tags='arm isa') -Source('mmu.cc', tags='arm isa') -Source('mpam.cc', tags='arm isa') -Source('nativetrace.cc', tags='arm isa') -Source('pagetable.cc', tags='arm isa') -Source('pauth_helpers.cc', tags='arm isa') -Source('pmu.cc', tags='arm isa') -Source('process.cc', tags='arm isa') -Source('qarma.cc', tags='arm isa') -Source('remote_gdb.cc', tags='arm isa') -Source('reg_abi.cc', tags='arm isa') -Source('semihosting.cc', tags='arm isa') -Source('system.cc', tags='arm isa') -Source('table_walker.cc', tags='arm isa') -Source('self_debug.cc', tags='arm isa') -Source('stage2_lookup.cc', tags='arm isa') -Source('tlb.cc', tags='arm isa') -Source('tlbi_op.cc', tags='arm isa') -Source('utility.cc', tags='arm isa') + Source("insts/tme64classic.cc", tags="arm isa") +Source("interrupts.cc", tags="arm isa") +Source("isa.cc", tags="arm isa") +Source("isa_device.cc", tags="arm isa") +Source("linux/process.cc", tags="arm isa") +Source("linux/se_workload.cc", tags="arm isa") +Source("linux/fs_workload.cc", tags="arm isa") +Source("freebsd/fs_workload.cc", tags="arm isa") +Source("freebsd/se_workload.cc", tags="arm isa") +Source("fs_workload.cc", tags="arm isa") +Source("regs/int.cc", tags="arm isa") +Source("regs/misc.cc", tags="arm isa") +Source("mmu.cc", tags="arm isa") +Source("mpam.cc", tags="arm isa") +Source("nativetrace.cc", tags="arm isa") +Source("pagetable.cc", tags="arm isa") +Source("pauth_helpers.cc", tags="arm isa") +Source("pmu.cc", tags="arm isa") +Source("process.cc", tags="arm isa") +Source("qarma.cc", tags="arm isa") +Source("remote_gdb.cc", tags="arm isa") +Source("reg_abi.cc", tags="arm isa") +Source("semihosting.cc", tags="arm isa") +Source("system.cc", tags="arm isa") +Source("table_walker.cc", tags="arm isa") +Source("self_debug.cc", tags="arm isa") +Source("stage2_lookup.cc", tags="arm isa") +Source("tlb.cc", tags="arm isa") +Source("tlbi_op.cc", tags="arm isa") +Source("utility.cc", tags="arm isa") -SimObject('ArmDecoder.py', sim_objects=['ArmDecoder'], tags='arm isa') -SimObject('ArmFsWorkload.py', sim_objects=[ - 'ArmFsWorkload', 'ArmFsLinux', 'ArmFsFreebsd'], - enums=['ArmMachineType'], tags='arm isa') -SimObject('ArmInterrupts.py', sim_objects=['ArmInterrupts'], tags='arm isa') -SimObject('ArmISA.py', sim_objects=['ArmISA'], enums=['DecoderFlavor'], - tags='arm isa') -SimObject('ArmMMU.py', sim_objects=['ArmTableWalker', 'ArmMMU'], - tags='arm isa') -SimObject('ArmNativeTrace.py', sim_objects=['ArmNativeTrace'], tags='arm isa') -SimObject('ArmSemihosting.py', sim_objects=['ArmSemihosting'], tags='arm isa') -SimObject('ArmSeWorkload.py', sim_objects=[ - 'ArmSEWorkload', 'ArmEmuLinux', 'ArmEmuFreebsd'], tags='arm isa') -SimObject('ArmSystem.py', sim_objects=['ArmSystem', 'ArmRelease'], - enums=['ArmExtension'], tags='arm isa') -SimObject('ArmTLB.py', sim_objects=['ArmTLB'], enums=['ArmLookupLevel'], - tags='arm isa') -SimObject('ArmPMU.py', sim_objects=['ArmPMU'], tags='arm isa') +SimObject("ArmDecoder.py", sim_objects=["ArmDecoder"], tags="arm isa") +SimObject( + "ArmFsWorkload.py", + sim_objects=["ArmFsWorkload", "ArmFsLinux", "ArmFsFreebsd"], + enums=["ArmMachineType"], + tags="arm isa", +) +SimObject("ArmInterrupts.py", sim_objects=["ArmInterrupts"], tags="arm isa") +SimObject( + "ArmISA.py", + sim_objects=["ArmISA"], + enums=["DecoderFlavor"], + tags="arm isa", +) +SimObject( + "ArmMMU.py", sim_objects=["ArmTableWalker", "ArmMMU"], tags="arm isa" +) +SimObject("ArmNativeTrace.py", sim_objects=["ArmNativeTrace"], tags="arm isa") +SimObject("ArmSemihosting.py", sim_objects=["ArmSemihosting"], tags="arm isa") +SimObject( + "ArmSeWorkload.py", + sim_objects=["ArmSEWorkload", "ArmEmuLinux", "ArmEmuFreebsd"], + tags="arm isa", +) +SimObject( + "ArmSystem.py", + sim_objects=["ArmSystem", "ArmRelease"], + enums=["ArmExtension"], + tags="arm isa", +) +SimObject( + "ArmTLB.py", + sim_objects=["ArmTLB", "TLBIndexingPolicy", "TLBSetAssociative"], + enums=["ArmLookupLevel"], + tags="arm isa", +) +SimObject("ArmPMU.py", sim_objects=["ArmPMU"], tags="arm isa") -SimObject('ArmCPU.py', sim_objects=[], tags='arm isa') +SimObject("ArmCPU.py", sim_objects=[], tags="arm isa") -DebugFlag('Arm', tags='arm isa') -DebugFlag('ArmTme', 'Transactional Memory Extension', tags='arm isa') -DebugFlag('MPAM', 'MPAM debug flag', tags='arm isa') -DebugFlag('PMUVerbose', "Performance Monitor", tags='arm isa') +DebugFlag("Arm", tags="arm isa") +DebugFlag("ArmTme", "Transactional Memory Extension", tags="arm isa") +DebugFlag("MPAM", "MPAM debug flag", tags="arm isa") +DebugFlag("PMUVerbose", "Performance Monitor", tags="arm isa") # Add files generated by the ISA description. -ISADesc('isa/main.isa', decoder_splits=3, exec_splits=6, tags='arm isa') +ISADesc("isa/main.isa", decoder_splits=3, exec_splits=6, tags="arm isa") diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 66c082a216..16e1635b6f 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -1067,8 +1067,8 @@ AbortFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) tc->setMiscReg(T::FsrIndex, fsr); tc->setMiscReg(T::FarIndex, faultAddr); } - DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\ - "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod); + DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x\n", + source, fsr, faultAddr); } else { // AArch64 // Set the FAR register. Nothing else to do if we are in AArch64 state // because the syndrome register has already been set inside invoke64() @@ -1092,11 +1092,11 @@ template void AbortFault::update(ThreadContext *tc) { - if (tranMethod == ArmFault::UnknownTran) { - tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran - : ArmFault::VmsaTran; + if (tranMethod == TranMethod::UnknownTran) { + tranMethod = longDescFormatInUse(tc) ? TranMethod::LpaeTran + : TranMethod::VmsaTran; - if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) { + if ((tranMethod == TranMethod::VmsaTran) && this->routeToMonitor(tc)) { // See ARM ARM B3-1416 bool override_LPAE = false; TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S); @@ -1109,7 +1109,7 @@ AbortFault::update(ThreadContext *tc) "override detected.\n"); } if (override_LPAE) - tranMethod = ArmFault::LpaeTran; + tranMethod = TranMethod::LpaeTran; } } @@ -1139,8 +1139,8 @@ AbortFault::getFaultStatusCode(ThreadContext *tc) const if (!this->to64) { // AArch32 - assert(tranMethod != ArmFault::UnknownTran); - if (tranMethod == ArmFault::LpaeTran) { + assert(tranMethod != TranMethod::UnknownTran); + if (tranMethod == TranMethod::LpaeTran) { fsc = ArmFault::longDescFaultSources[source]; } else { fsc = ArmFault::shortDescFaultSources[source]; @@ -1162,8 +1162,8 @@ AbortFault::getFsr(ThreadContext *tc) const auto fsc = getFaultStatusCode(tc); // AArch32 - assert(tranMethod != ArmFault::UnknownTran); - if (tranMethod == ArmFault::LpaeTran) { + assert(tranMethod != TranMethod::UnknownTran); + if (tranMethod == TranMethod::LpaeTran) { fsr.status = fsc; fsr.lpae = 1; } else { diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh index 025b670767..c338743941 100644 --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -149,13 +149,6 @@ class ArmFault : public FaultBase AR // DataAbort: Acquire/Release semantics }; - enum TranMethod - { - LpaeTran, - VmsaTran, - UnknownTran - }; - enum DebugType { NODEBUG = 0, @@ -482,18 +475,18 @@ class AbortFault : public ArmFaultVals */ Addr OVAddr; bool write; - TlbEntry::DomainType domain; + DomainType domain; uint8_t source; uint8_t srcEncoded; bool stage2; bool s1ptw; - ArmFault::TranMethod tranMethod; + TranMethod tranMethod; ArmFault::DebugType debugType; public: - AbortFault(Addr _faultAddr, bool _write, TlbEntry::DomainType _domain, + AbortFault(Addr _faultAddr, bool _write, DomainType _domain, uint8_t _source, bool _stage2, - ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran, + TranMethod _tranMethod = TranMethod::UnknownTran, ArmFault::DebugType _debug = ArmFault::NODEBUG) : faultAddr(_faultAddr), OVAddr(0), write(_write), domain(_domain), source(_source), srcEncoded(0), @@ -525,10 +518,10 @@ class PrefetchAbort : public AbortFault static const MiscRegIndex HFarIndex = MISCREG_HIFAR; PrefetchAbort(Addr _addr, uint8_t _source, bool _stage2 = false, - ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran, + TranMethod _tran_method = TranMethod::UnknownTran, ArmFault::DebugType _debug = ArmFault::NODEBUG) : - AbortFault(_addr, false, TlbEntry::DomainType::NoAccess, - _source, _stage2, _tranMethod, _debug) + AbortFault(_addr, false, DomainType::NoAccess, + _source, _stage2, _tran_method, _debug) {} // @todo: external aborts should be routed if SCR.EA == 1 @@ -558,12 +551,12 @@ class DataAbort : public AbortFault bool sf; bool ar; - DataAbort(Addr _addr, TlbEntry::DomainType _domain, bool _write, uint8_t _source, + DataAbort(Addr _addr, DomainType _domain, bool _write, uint8_t _source, bool _stage2=false, - ArmFault::TranMethod _tranMethod=ArmFault::UnknownTran, + TranMethod _tran_method=TranMethod::UnknownTran, ArmFault::DebugType _debug_type=ArmFault::NODEBUG) : AbortFault(_addr, _write, _domain, _source, _stage2, - _tranMethod, _debug_type), + _tran_method, _debug_type), isv(false), sas (0), sse(0), srt(0), cm(0), sf(false), ar(false) {} @@ -586,7 +579,7 @@ class VirtualDataAbort : public AbortFault static const MiscRegIndex FarIndex = MISCREG_DFAR; static const MiscRegIndex HFarIndex = MISCREG_HDFAR; - VirtualDataAbort(Addr _addr, TlbEntry::DomainType _domain, bool _write, + VirtualDataAbort(Addr _addr, DomainType _domain, bool _write, uint8_t _source) : AbortFault(_addr, _write, _domain, _source, false) {} diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index 34155f0f0d..ca78586dd8 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -646,7 +646,7 @@ ArmStaticInst::softwareBreakpoint32(ExecContext *xc, uint16_t imm) const return std::make_shared(readPC(xc), ArmFault::DebugEvent, false, - ArmFault::UnknownTran, + TranMethod::UnknownTran, ArmFault::BRKPOINT); } } diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index bddb932323..aae996b265 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -235,7 +235,7 @@ class Interrupts : public BaseInterrupts return std::make_shared(); if (hcr.va && takeVirtualInt(INT_VIRT_ABT)) return std::make_shared( - 0, TlbEntry::DomainType::NoAccess, false, + 0, DomainType::NoAccess, false, ArmFault::AsynchronousExternalAbort); if (interrupts[INT_RST]) return std::make_shared(); diff --git a/src/arch/arm/mmu.cc b/src/arch/arm/mmu.cc index 7237dc1a01..effbaa0d48 100644 --- a/src/arch/arm/mmu.cc +++ b/src/arch/arm/mmu.cc @@ -45,9 +45,9 @@ #include "arch/arm/reg_abi.hh" #include "arch/arm/stage2_lookup.hh" #include "arch/arm/table_walker.hh" +#include "arch/arm/tlb.hh" #include "arch/arm/tlbi_op.hh" -#include "debug/TLB.hh" -#include "debug/TLBVerbose.hh" +#include "debug/MMU.hh" #include "mem/packet_access.hh" #include "sim/pseudo_inst.hh" #include "sim/process.hh" @@ -134,6 +134,18 @@ MMU::drainResume() s2State.miscRegValid = false; } +ArmISA::TLB * +MMU::getDTBPtr() const +{ + return static_cast(dtb); +} + +ArmISA::TLB * +MMU::getITBPtr() const +{ + return static_cast(itb); +} + TLB * MMU::getTlb(BaseMMU::Mode mode, bool stage2) const { @@ -173,7 +185,7 @@ MMU::translateFunctional(ThreadContext *tc, Addr va, Addr &pa) auto tlb = getTlb(BaseMMU::Read, state.directToStage2); - TlbEntry::Lookup lookup_data; + TlbEntry::KeyType lookup_data; lookup_data.va = va; lookup_data.asn = state.asid; @@ -200,6 +212,70 @@ MMU::invalidateMiscReg() s2State.computeAddrTop.flush(); } +void +MMU::flush(const TLBIOp &tlbi_op) +{ + if (tlbi_op.stage1Flush()) { + flushStage1(tlbi_op); + } + + if (tlbi_op.stage2Flush()) { + flushStage2(tlbi_op); + } +} + +void +MMU::flushStage1(const TLBIOp &tlbi_op) +{ + for (auto tlb : instruction) { + static_cast(tlb)->flush(tlbi_op); + } + for (auto tlb : data) { + static_cast(tlb)->flush(tlbi_op); + } + for (auto tlb : unified) { + static_cast(tlb)->flush(tlbi_op); + } +} + +void +MMU::flushStage2(const TLBIOp &tlbi_op) +{ + itbStage2->flush(tlbi_op); + dtbStage2->flush(tlbi_op); +} + +void +MMU::iflush(const TLBIOp &tlbi_op) +{ + for (auto tlb : instruction) { + static_cast(tlb)->flush(tlbi_op); + } + for (auto tlb : unified) { + static_cast(tlb)->flush(tlbi_op); + } +} + +void +MMU::dflush(const TLBIOp &tlbi_op) +{ + for (auto tlb : data) { + static_cast(tlb)->flush(tlbi_op); + } + for (auto tlb : unified) { + static_cast(tlb)->flush(tlbi_op); + } +} + +void +MMU::flushAll() +{ + BaseMMU::flushAll(); + itbStage2->flushAll(); + dtbStage2->flushAll(); +} + + Fault MMU::testAndFinalize(const RequestPtr &req, ThreadContext *tc, Mode mode, @@ -207,7 +283,7 @@ MMU::testAndFinalize(const RequestPtr &req, { // If we don't have a valid tlb entry it means virtual memory // is not enabled - auto domain = te ? te-> domain : TlbEntry::DomainType::NoAccess; + auto domain = te ? te-> domain : DomainType::NoAccess; mpam::tagRequest(tc, req, mode == Execute); @@ -277,9 +353,9 @@ MMU::translateSe(const RequestPtr &req, ThreadContext *tc, Mode mode, // LPAE is always disabled in SE mode return std::make_shared( vaddr_tainted, - TlbEntry::DomainType::NoAccess, is_write, + DomainType::NoAccess, is_write, ArmFault::AlignmentFault, state.isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); } } } @@ -321,8 +397,8 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, bool is_priv = state.isPriv && !(flags & UserMode); // Get the translation type from the actuall table entry - ArmFault::TranMethod tranMethod = te->longDescFormat ? ArmFault::LpaeTran - : ArmFault::VmsaTran; + TranMethod tran_method = te->longDescFormat ? + TranMethod::LpaeTran : TranMethod::VmsaTran; // If this is the second stage of translation and the request is for a // stage 1 page table walk then we need to check the HCR.PTW bit. This @@ -333,7 +409,7 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, return std::make_shared( vaddr, te->domain, is_write, ArmFault::PermissionLL + te->lookupLevel, - state.isStage2, tranMethod); + state.isStage2, tran_method); } // Generate an alignment fault for unaligned data accesses to device or @@ -343,9 +419,9 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, if (vaddr & mask(flags & AlignmentMask)) { stats.alignFaults++; return std::make_shared( - vaddr, TlbEntry::DomainType::NoAccess, is_write, + vaddr, DomainType::NoAccess, is_write, ArmFault::AlignmentFault, state.isStage2, - tranMethod); + tran_method); } } } @@ -357,7 +433,7 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, // desc. format in all cases return std::make_shared( vaddr, ArmFault::PrefetchUncacheable, - state.isStage2, tranMethod); + state.isStage2, tran_method); } } @@ -365,7 +441,7 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, switch ((state.dacr >> (static_cast(te->domain) * 2)) & 0x3) { case 0: stats.domainFaults++; - DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x" + DPRINTF(MMU, "MMU Fault: Data abort on domain. DACR: %#x" " domain: %#x write:%d\n", state.dacr, static_cast(te->domain), is_write); if (is_fetch) { @@ -375,12 +451,12 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, return std::make_shared( req->getPC(), ArmFault::DomainLL + te->lookupLevel, - state.isStage2, tranMethod); + state.isStage2, tran_method); } else return std::make_shared( vaddr, te->domain, is_write, ArmFault::DomainLL + te->lookupLevel, - state.isStage2, tranMethod); + state.isStage2, tran_method); case 1: // Continue with permissions check break; @@ -408,7 +484,7 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, } else { switch (ap) { case 0: - DPRINTF(TLB, "Access permissions 0, checking rs:%#x\n", + DPRINTF(MMU, "Access permissions 0, checking rs:%#x\n", (int)state.sctlr.rs); if (!state.sctlr.xp) { switch ((int)state.sctlr.rs) { @@ -462,7 +538,7 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, (state.securityState == SecurityState::Secure && te->ns && state.scr.sif))) { stats.permsFaults++; - DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. AP:%d " + DPRINTF(MMU, "MMU Fault: Prefetch abort on permission check. AP:%d " "priv:%d write:%d ns:%d sif:%d sctlr.afe: %d \n", ap, is_priv, is_write, te->ns, state.scr.sif, state.sctlr.afe); @@ -471,15 +547,15 @@ MMU::checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode, return std::make_shared( req->getPC(), ArmFault::PermissionLL + te->lookupLevel, - state.isStage2, tranMethod); + state.isStage2, tran_method); } else if (abt | hapAbt) { stats.permsFaults++; - DPRINTF(TLB, "TLB Fault: Data abort on permission check. AP:%d priv:%d" + DPRINTF(MMU, "MMU Fault: Data abort on permission check. AP:%d priv:%d" " write:%d\n", ap, is_priv, is_write); return std::make_shared( vaddr, te->domain, is_write, ArmFault::PermissionLL + te->lookupLevel, - state.isStage2 | !abt, tranMethod); + state.isStage2 | !abt, tran_method); } return NoFault; } @@ -524,7 +600,7 @@ MMU::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode, return std::make_shared( vaddr_tainted, te->domain, is_write, ArmFault::PermissionLL + te->lookupLevel, - state.isStage2, ArmFault::LpaeTran); + state.isStage2, TranMethod::LpaeTran); } // Generate an alignment fault for unaligned accesses to device or @@ -535,10 +611,10 @@ MMU::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode, stats.alignFaults++; return std::make_shared( vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : is_write, ArmFault::AlignmentFault, state.isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); } } } @@ -551,7 +627,7 @@ MMU::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode, return std::make_shared( vaddr_tainted, ArmFault::PrefetchUncacheable, - state.isStage2, ArmFault::LpaeTran); + state.isStage2, TranMethod::LpaeTran); } } @@ -573,7 +649,7 @@ MMU::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode, if (!grant) { if (is_fetch) { stats.permsFaults++; - DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. " + DPRINTF(MMU, "MMU Fault: Prefetch abort on permission check. " "ns:%d scr.sif:%d sctlr.afe: %d\n", te->ns, state.scr.sif, state.sctlr.afe); // Use PC value instead of vaddr because vaddr might be aligned to @@ -581,16 +657,16 @@ MMU::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode, return std::make_shared( req->getPC(), ArmFault::PermissionLL + te->lookupLevel, - state.isStage2, ArmFault::LpaeTran); + state.isStage2, TranMethod::LpaeTran); } else { stats.permsFaults++; - DPRINTF(TLB, "TLB Fault: Data abort on permission check." + DPRINTF(MMU, "MMU Fault: Data abort on permission check." "ns:%d", te->ns); return std::make_shared( vaddr_tainted, te->domain, (is_atomic && !grant_read) ? false : is_write, ArmFault::PermissionLL + te->lookupLevel, - state.isStage2, ArmFault::LpaeTran); + state.isStage2, TranMethod::LpaeTran); } } @@ -619,7 +695,7 @@ MMU::s2PermBits64(TlbEntry *te, const RequestPtr &req, Mode mode, xn = true; } - DPRINTF(TLBVerbose, + DPRINTF(MMU, "Checking S2 permissions: hap:%d, xn:%d, pxn:%d, r:%d, " "w:%d, x:%d\n", te->hap, xn, pxn, r, w, x); @@ -651,7 +727,7 @@ MMU::s1PermBits64(TlbEntry *te, const RequestPtr &req, Mode mode, uint8_t xn = te->xn; uint8_t pxn = te->pxn; - DPRINTF(TLBVerbose, "Checking S1 permissions: ap:%d, xn:%d, pxn:%d, r:%d, " + DPRINTF(MMU, "Checking S1 permissions: ap:%d, xn:%d, pxn:%d, r:%d, " "w:%d, x:%d, is_priv: %d, wxn: %d\n", ap, xn, pxn, r, w, x, is_priv, wxn); @@ -825,13 +901,13 @@ MMU::translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode, if (is_fetch) f = std::make_shared(vaddr, ArmFault::AddressSizeLL, state.isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); else f = std::make_shared( vaddr, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : mode==Write, ArmFault::AddressSizeLL, state.isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); return f; } } @@ -867,7 +943,7 @@ MMU::translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode, temp_te.outerShareable = false; } temp_te.setAttributes(long_desc_format); - DPRINTF(TLBVerbose, "(No MMU) setting memory attributes: shareable: " + DPRINTF(MMU, "(No MMU) setting memory attributes: shareable: " "%d, innerAttrs: %d, outerAttrs: %d, stage2: %d\n", temp_te.shareable, temp_te.innerAttrs, temp_te.outerAttrs, state.isStage2); @@ -880,7 +956,7 @@ Fault MMU::translateMmuOn(ThreadContext* tc, const RequestPtr &req, Mode mode, Translation *translation, bool &delay, bool timing, bool functional, Addr vaddr, - ArmFault::TranMethod tranMethod, CachedState &state) + TranMethod tran_method, CachedState &state) { TlbEntry *te = NULL; bool is_fetch = (mode == Execute); @@ -898,7 +974,7 @@ MMU::translateMmuOn(ThreadContext* tc, const RequestPtr &req, Mode mode, // request that triggered the translation if (isCompleteTranslation(te)) { // Set memory attributes - DPRINTF(TLBVerbose, + DPRINTF(MMU, "Setting memory attributes: shareable: %d, innerAttrs: %d, " "outerAttrs: %d, mtype: %d, stage2: %d\n", te->shareable, te->innerAttrs, te->outerAttrs, @@ -931,9 +1007,9 @@ MMU::translateMmuOn(ThreadContext* tc, const RequestPtr &req, Mode mode, bool is_write = (mode == Write); return std::make_shared( vaddr_tainted, - TlbEntry::DomainType::NoAccess, is_write, + DomainType::NoAccess, is_write, ArmFault::AlignmentFault, state.isStage2, - tranMethod); + tran_method); } if (fault == NoFault) @@ -965,16 +1041,16 @@ MMU::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode, bool is_fetch = (mode == Execute); bool is_write = (mode == Write); bool long_desc_format = state.aarch64 || longDescFormatInUse(tc); - ArmFault::TranMethod tranMethod = long_desc_format ? ArmFault::LpaeTran - : ArmFault::VmsaTran; + TranMethod tran_method = long_desc_format ? + TranMethod::LpaeTran : TranMethod::VmsaTran; - DPRINTF(TLBVerbose, + DPRINTF(MMU, "CPSR is priv:%d UserMode:%d secure:%d S1S2NsTran:%d\n", state.isPriv, flags & UserMode, state.securityState == SecurityState::Secure, tran_type & S1S2NsTran); - DPRINTF(TLB, "translateFs addr %#x, mode %d, st2 %d, scr %#x sctlr %#x " + DPRINTF(MMU, "translateFs addr %#x, mode %d, st2 %d, scr %#x sctlr %#x " "flags %#lx tranType 0x%x\n", vaddr_tainted, mode, state.isStage2, state.scr, state.sctlr, flags, tran_type); @@ -993,9 +1069,9 @@ MMU::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode, stats.alignFaults++; return std::make_shared( vaddr_tainted, - TlbEntry::DomainType::NoAccess, is_write, + DomainType::NoAccess, is_write, ArmFault::AlignmentFault, state.isStage2, - tranMethod); + tran_method); } } } @@ -1013,11 +1089,11 @@ MMU::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode, fault = translateMmuOff(tc, req, mode, tran_type, vaddr, long_desc_format, state); } else { - DPRINTF(TLBVerbose, "Translating %s=%#x context=%d\n", + DPRINTF(MMU, "Translating %s=%#x context=%d\n", state.isStage2 ? "IPA" : "VA", vaddr_tainted, state.asid); // Translation enabled fault = translateMmuOn(tc, req, mode, translation, delay, timing, - functional, vaddr, tranMethod, state); + functional, vaddr, tran_method, state); } // Check for Debug Exceptions @@ -1119,7 +1195,7 @@ MMU::translateComplete(const RequestPtr &req, ThreadContext *tc, else fault = translateSe(req, tc, mode, translation, delay, true, state); - DPRINTF(TLBVerbose, "Translation returning delay=%d fault=%d\n", delay, + DPRINTF(MMU, "Translation returning delay=%d fault=%d\n", delay, fault != NoFault); // If we have a translation, and we're not in the middle of doing a stage // 2 translation tell the translation that we've either finished or its @@ -1180,7 +1256,7 @@ MMU::updateMiscReg(ThreadContext *tc, ((tran_type == state.curTranType) || stage2)) { } else { - DPRINTF(TLBVerbose, "TLB variables changed!\n"); + DPRINTF(MMU, "MMU variables changed!\n"); state.updateMiscReg(tc, tran_type); itbStage2->setVMID(state.vmid); @@ -1396,7 +1472,7 @@ MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, SecurityState ss, { TLB *tlb = getTlb(mode, stage2); - TlbEntry::Lookup lookup_data; + TlbEntry::KeyType lookup_data; lookup_data.va = va; lookup_data.asn = asid; @@ -1448,7 +1524,7 @@ MMU::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode, // start translation table walk, pass variables rather than // re-retreaving in table walker for speed - DPRINTF(TLB, + DPRINTF(MMU, "TLB Miss: Starting hardware table walker for %#x(%d:%d)\n", vaddr_tainted, state.asid, state.vmid); @@ -1534,7 +1610,7 @@ MMU::getResultTe(TlbEntry **te, const RequestPtr &req, // This case deals with an S1 hit (or bypass), followed by // an S2 hit-but-perms issue if (state.isStage2) { - DPRINTF(TLBVerbose, "s2TLB: reqVa %#x, reqPa %#x, fault %p\n", + DPRINTF(MMU, "s2TLB: reqVa %#x, reqPa %#x, fault %p\n", vaddr_tainted, req->hasPaddr() ? req->getPaddr() : ~0, fault); if (fault != NoFault) { @@ -1587,7 +1663,7 @@ MMU::setTestInterface(SimObject *_ti) Fault MMU::testTranslation(const RequestPtr &req, Mode mode, - TlbEntry::DomainType domain, CachedState &state) const + DomainType domain, CachedState &state) const { if (!test || !req->hasSize() || req->getSize() == 0 || req->isCacheMaintenance()) { diff --git a/src/arch/arm/mmu.hh b/src/arch/arm/mmu.hh index 46d904278a..921b335cc4 100644 --- a/src/arch/arm/mmu.hh +++ b/src/arch/arm/mmu.hh @@ -42,10 +42,10 @@ #define __ARCH_ARM_MMU_HH__ #include "arch/arm/page_size.hh" -#include "arch/arm/tlb.hh" #include "arch/arm/utility.hh" #include "arch/generic/mmu.hh" #include "base/memoizer.hh" +#include "base/statistics.hh" #include "enums/ArmLookupLevel.hh" #include "params/ArmMMU.hh" @@ -56,23 +56,18 @@ namespace gem5 namespace ArmISA { class TableWalker; +class TLB; +class TlbEntry; +class TLBIOp; +class TlbTestInterface; class MMU : public BaseMMU { protected: using LookupLevel = enums::ArmLookupLevel; - ArmISA::TLB * - getDTBPtr() const - { - return static_cast(dtb); - } - - ArmISA::TLB * - getITBPtr() const - { - return static_cast(itb); - } + ArmISA::TLB * getDTBPtr() const; + ArmISA::TLB * getITBPtr() const; TLB * getTlb(BaseMMU::Mode mode, bool stage2) const; TableWalker * getTableWalker(BaseMMU::Mode mode, bool stage2) const; @@ -270,7 +265,7 @@ class MMU : public BaseMMU CachedState &state); Fault translateMmuOn(ThreadContext *tc, const RequestPtr &req, Mode mode, Translation *translation, bool &delay, bool timing, bool functional, - Addr vaddr, ArmFault::TranMethod tranMethod, + Addr vaddr, TranMethod tran_method, CachedState &state); Fault translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode, @@ -297,73 +292,13 @@ class MMU : public BaseMMU void invalidateMiscReg(); - template - void - flush(const OP &tlbi_op) - { - if (tlbi_op.stage1Flush()) { - flushStage1(tlbi_op); - } + void flush(const TLBIOp &tlbi_op); + void flushStage1(const TLBIOp &tlbi_op); + void flushStage2(const TLBIOp &tlbi_op); + void iflush(const TLBIOp &tlbi_op); + void dflush(const TLBIOp &tlbi_op); - if (tlbi_op.stage2Flush()) { - flushStage2(tlbi_op); - } - } - - template - void - flushStage1(const OP &tlbi_op) - { - for (auto tlb : instruction) { - static_cast(tlb)->flush(tlbi_op); - } - for (auto tlb : data) { - static_cast(tlb)->flush(tlbi_op); - } - for (auto tlb : unified) { - static_cast(tlb)->flush(tlbi_op); - } - } - - template - void - flushStage2(const OP &tlbi_op) - { - itbStage2->flush(tlbi_op); - dtbStage2->flush(tlbi_op); - } - - template - void - iflush(const OP &tlbi_op) - { - for (auto tlb : instruction) { - static_cast(tlb)->flush(tlbi_op); - } - for (auto tlb : unified) { - static_cast(tlb)->flush(tlbi_op); - } - } - - template - void - dflush(const OP &tlbi_op) - { - for (auto tlb : data) { - static_cast(tlb)->flush(tlbi_op); - } - for (auto tlb : unified) { - static_cast(tlb)->flush(tlbi_op); - } - } - - void - flushAll() override - { - BaseMMU::flushAll(); - itbStage2->flushAll(); - dtbStage2->flushAll(); - } + void flushAll() override; uint64_t getAttr() const @@ -462,7 +397,7 @@ class MMU : public BaseMMU void setTestInterface(SimObject *ti); Fault testTranslation(const RequestPtr &req, Mode mode, - TlbEntry::DomainType domain, CachedState &state) const; + DomainType domain, CachedState &state) const; protected: bool checkWalkCache() const; diff --git a/src/arch/arm/pagetable.cc b/src/arch/arm/pagetable.cc index e93e00e844..ce95a4c8aa 100644 --- a/src/arch/arm/pagetable.cc +++ b/src/arch/arm/pagetable.cc @@ -489,5 +489,14 @@ getPageTableOps(GrainSize trans_granule) } } +TLBTypes::KeyType::KeyType(const TlbEntry &entry) + : va(entry.vpn << entry.N), pageSize(entry.N), size(0), + asn(entry.asid), ignoreAsn(false), + vmid(entry.vmid), ss(entry.ss), + functional(false), + targetRegime(entry.regime), + mode(BaseMMU::Read) +{} + } // namespace ArmISA } // namespace gem5 diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh index 8a3f7943d5..0f8b0797d3 100644 --- a/src/arch/arm/pagetable.hh +++ b/src/arch/arm/pagetable.hh @@ -49,6 +49,10 @@ #include "arch/generic/mmu.hh" #include "enums/TypeTLB.hh" #include "enums/ArmLookupLevel.hh" +#include "mem/cache/replacement_policies/replaceable_entry.hh" +#include "mem/cache/tags/indexing_policies/base.hh" +#include "params/TLBIndexingPolicy.hh" +#include "params/TLBSetAssociative.hh" #include "sim/serialize.hh" namespace gem5 @@ -161,31 +165,20 @@ struct V8PageTableOps64k : public PageTableOps LookupLevel lastLevel() const override; }; -// ITB/DTB table entry -struct TlbEntry : public Serializable +struct TlbEntry; + +class TLBTypes { public: - typedef enums::ArmLookupLevel LookupLevel; - - enum class MemoryType : std::uint8_t + struct KeyType { - StronglyOrdered, - Device, - Normal - }; + KeyType() = default; + explicit KeyType(const TlbEntry &entry); - enum class DomainType : std::uint8_t - { - NoAccess = 0, - Client, - Reserved, - Manager - }; - - struct Lookup - { // virtual address Addr va = 0; + // page size + Addr pageSize = Grain4KB; // lookup size: // * != 0 -> this is a range based lookup. // end_address = va + size @@ -208,6 +201,48 @@ struct TlbEntry : public Serializable BaseMMU::Mode mode = BaseMMU::Read; }; + using Params = TLBIndexingPolicyParams; +}; +using TLBIndexingPolicy = IndexingPolicyTemplate; + +class TLBSetAssociative : public TLBIndexingPolicy +{ + public: + PARAMS(TLBSetAssociative); + TLBSetAssociative(const Params &p) + : TLBIndexingPolicy(p, p.num_entries, 0) + {} + + std::vector + getPossibleEntries(const KeyType &key) const override + { + Addr set_number = (key.va >> key.pageSize) & setMask; + return sets[set_number]; + } + + Addr + regenerateAddr(const KeyType &key, + const ReplaceableEntry *entry) const override + { + panic("Unimplemented\n"); + } +}; + +// ITB/DTB table entry +struct TlbEntry : public ReplaceableEntry, Serializable +{ + public: + using LookupLevel = enums::ArmLookupLevel; + using KeyType = TLBTypes::KeyType; + using IndexingPolicy = TLBIndexingPolicy; + + enum class MemoryType : std::uint8_t + { + StronglyOrdered, + Device, + Normal + }; + // Matching variables Addr pfn; Addr size; // Size of this entry, == Type of TLB Rec @@ -305,6 +340,59 @@ struct TlbEntry : public Serializable // @todo Check the memory type } + TlbEntry(const TlbEntry &rhs) = default; + TlbEntry& operator=(TlbEntry rhs) + { + swap(rhs); + return *this; + } + + void + swap(TlbEntry &rhs) + { + std::swap(pfn, rhs.pfn); + std::swap(size, rhs.size); + std::swap(vpn, rhs.vpn); + std::swap(attributes, rhs.attributes); + std::swap(lookupLevel, rhs.lookupLevel); + std::swap(asid, rhs.asid); + std::swap(vmid, rhs.vmid); + std::swap(tg, rhs.tg); + std::swap(N, rhs.N); + std::swap(innerAttrs, rhs.innerAttrs); + std::swap(outerAttrs, rhs.outerAttrs); + std::swap(ap, rhs.ap); + std::swap(hap, rhs.hap); + std::swap(domain, rhs.domain); + std::swap(mtype, rhs.mtype); + std::swap(longDescFormat, rhs.longDescFormat); + std::swap(global, rhs.global); + std::swap(valid, rhs.valid); + std::swap(ns, rhs.ns); + std::swap(ss, rhs.ss); + std::swap(regime, rhs.regime); + std::swap(type, rhs.type); + std::swap(partial, rhs.partial); + std::swap(nonCacheable, rhs.nonCacheable); + std::swap(shareable, rhs.shareable); + std::swap(outerShareable, rhs.outerShareable); + std::swap(xn, rhs.xn); + std::swap(pxn, rhs.pxn); + std::swap(xs, rhs.xs); + } + + /** Need for compliance with the AssociativeCache interface */ + void + invalidate() + { + valid = false; + } + + /** Need for compliance with the AssociativeCache interface */ + void insert(const KeyType &key) {} + + /** Need for compliance with the AssociativeCache interface */ + bool isValid() const { return valid; } void updateVaddr(Addr new_vaddr) @@ -319,32 +407,32 @@ struct TlbEntry : public Serializable } bool - matchAddress(const Lookup &lookup) const + matchAddress(const KeyType &key) const { Addr page_addr = vpn << N; - if (lookup.size) { + if (key.size) { // This is a range based loookup - return lookup.va <= page_addr + size && - lookup.va + lookup.size > page_addr; + return key.va <= page_addr + size && + key.va + key.size > page_addr; } else { // This is a normal lookup - return lookup.va >= page_addr && lookup.va <= page_addr + size; + return key.va >= page_addr && key.va <= page_addr + size; } } bool - match(const Lookup &lookup) const + match(const KeyType &key) const { bool match = false; - if (valid && matchAddress(lookup) && lookup.ss == ss) + if (valid && matchAddress(key) && key.ss == ss) { - match = checkRegime(lookup.targetRegime); + match = checkRegime(key.targetRegime); - if (match && !lookup.ignoreAsn) { - match = global || (lookup.asn == asid); + if (match && !key.ignoreAsn) { + match = global || (key.asn == asid); } - if (match && useVMID(lookup.targetRegime)) { - match = lookup.vmid == vmid; + if (match && useVMID(key.targetRegime)) { + match = key.vmid == vmid; } } return match; @@ -487,6 +575,9 @@ struct TlbEntry : public Serializable const PageTableOps *getPageTableOps(GrainSize trans_granule); } // namespace ArmISA + +template class IndexingPolicyTemplate; + } // namespace gem5 #endif // __ARCH_ARM_PAGETABLE_H__ diff --git a/src/arch/arm/self_debug.cc b/src/arch/arm/self_debug.cc index a99cf0a81e..243efde7b3 100644 --- a/src/arch/arm/self_debug.cc +++ b/src/arch/arm/self_debug.cc @@ -110,7 +110,7 @@ SelfDebug::triggerException(ThreadContext *tc, Addr vaddr) if (to32) { return std::make_shared(vaddr, ArmFault::DebugEvent, false, - ArmFault::UnknownTran, + TranMethod::UnknownTran, ArmFault::BRKPOINT); } else { return std::make_shared(vaddr, 0x22); @@ -145,9 +145,9 @@ SelfDebug::triggerWatchpointException(ThreadContext *tc, Addr vaddr, ArmFault::DebugType d = cm? ArmFault::WPOINT_CM: ArmFault::WPOINT_NOCM; return std::make_shared(vaddr, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, write, ArmFault::DebugEvent, cm, - ArmFault::UnknownTran, d); + TranMethod::UnknownTran, d); } else { return std::make_shared(0, vaddr, write, cm); } diff --git a/src/arch/arm/self_debug.hh b/src/arch/arm/self_debug.hh index 069df24066..79796e0415 100644 --- a/src/arch/arm/self_debug.hh +++ b/src/arch/arm/self_debug.hh @@ -40,7 +40,6 @@ #define __ARCH_ARM_SELF_DEBUG_HH__ -#include "arch/arm/faults.hh" #include "arch/arm/regs/misc.hh" #include "arch/arm/system.hh" #include "arch/arm/types.hh" diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 4357b0057c..efb69fe142 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -640,14 +640,14 @@ TableWalker::processWalk() currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); else return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); } ttbr = currState->tc->readMiscReg(snsBankedIndex( MISCREG_TTBR0, currState->tc, @@ -661,14 +661,14 @@ TableWalker::processWalk() currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); else return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); } ttbr = ttbr1; currState->ttbcr.n = 0; @@ -758,15 +758,15 @@ TableWalker::processWalkLPAE() currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); else return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); } ttbr = currState->tc->readMiscReg(snsBankedIndex( MISCREG_TTBR0, currState->tc, @@ -784,15 +784,15 @@ TableWalker::processWalkLPAE() currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); else return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); } ttbr = currState->tc->readMiscReg(snsBankedIndex( MISCREG_TTBR1, currState->tc, @@ -809,14 +809,14 @@ TableWalker::processWalkLPAE() currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); else return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L1, - isStage2, ArmFault::LpaeTran); + isStage2, TranMethod::LpaeTran); } } @@ -1074,14 +1074,14 @@ TableWalker::processWalkAArch64() return std::make_shared( currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L0, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); } else { return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L0, - isStage2, ArmFault::LpaeTran); + isStage2, TranMethod::LpaeTran); } } @@ -1111,15 +1111,15 @@ TableWalker::processWalkAArch64() currState->vaddr_tainted, ArmFault::AddressSizeLL + start_lookup_level, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); else return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::AddressSizeLL + start_lookup_level, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); } Request::Flags flag = Request::PT_WALK; @@ -1687,15 +1687,15 @@ TableWalker::doL1Descriptor() currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); else currState->fault = std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L1, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); return; case L1Descriptor::Section: if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { @@ -1710,7 +1710,7 @@ TableWalker::doL1Descriptor() is_atomic ? false : currState->isWrite, ArmFault::AccessFlagLL + LookupLevel::L1, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); } if (currState->l1Desc.supersection()) { panic("Haven't implemented supersections\n"); @@ -1758,15 +1758,15 @@ TableWalker::generateLongDescFault(ArmFault::FaultSource src) currState->vaddr_tainted, src + currState->longDesc.lookupLevel, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); } else { return std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, currState->req->isAtomic() ? false : currState->isWrite, src + currState->longDesc.lookupLevel, isStage2, - ArmFault::LpaeTran); + TranMethod::LpaeTran); } } @@ -1953,14 +1953,14 @@ TableWalker::doL2Descriptor() currState->vaddr_tainted, ArmFault::TranslationLL + LookupLevel::L2, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); else currState->fault = std::make_shared( currState->vaddr_tainted, currState->l1Desc.domain(), is_atomic ? false : currState->isWrite, ArmFault::TranslationLL + LookupLevel::L2, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); return; } @@ -1973,10 +1973,10 @@ TableWalker::doL2Descriptor() currState->fault = std::make_shared( currState->vaddr_tainted, - TlbEntry::DomainType::NoAccess, + DomainType::NoAccess, is_atomic ? false : currState->isWrite, ArmFault::AccessFlagLL + LookupLevel::L2, isStage2, - ArmFault::VmsaTran); + TranMethod::VmsaTran); } insertTableEntry(currState->l2Desc, false); @@ -2312,7 +2312,7 @@ TableWalker::insertPartialTableEntry(LongDescriptor &descriptor) descriptor.getRawData()); // Insert the entry into the TLBs - tlb->multiInsert(te); + tlb->multiInsert(TlbEntry::KeyType(te), te); } void @@ -2386,7 +2386,7 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool long_descriptor) descriptor.getRawData()); // Insert the entry into the TLBs - tlb->multiInsert(te); + tlb->multiInsert(TlbEntry::KeyType(te), te); if (!currState->timing) { currState->tc = NULL; currState->req = NULL; @@ -2427,7 +2427,7 @@ TableWalker::pendingChange() } Fault -TableWalker::testWalk(const RequestPtr &walk_req, TlbEntry::DomainType domain, +TableWalker::testWalk(const RequestPtr &walk_req, DomainType domain, LookupLevel lookup_level) { if (!test) { diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index 8568be760f..19697b2028 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -79,7 +79,7 @@ class TableWalker : public ClockedObject LookupLevel lookupLevel; virtual Addr pfn() const = 0; - virtual TlbEntry::DomainType domain() const = 0; + virtual DomainType domain() const = 0; virtual bool xn() const = 0; virtual uint8_t ap() const = 0; virtual bool global(WalkerState *currState) const = 0; @@ -209,10 +209,10 @@ class TableWalker : public ClockedObject } /** Domain Client/Manager: ARM DDI 0406B: B3-31 */ - TlbEntry::DomainType + DomainType domain() const override { - return static_cast(bits(data, 8, 5)); + return static_cast(bits(data, 8, 5)); } /** Address of L2 descriptor if it exists */ @@ -316,7 +316,7 @@ class TableWalker : public ClockedObject return "Inserting L2 Descriptor into TLB\n"; } - TlbEntry::DomainType + DomainType domain() const override { return l1Parent->domain(); @@ -744,11 +744,11 @@ class TableWalker : public ClockedObject return ((!rw) << 2) | (user << 1); } - TlbEntry::DomainType + DomainType domain() const override { // Long-desc. format only supports Client domain - return TlbEntry::DomainType::Client; + return DomainType::Client; } /** Attribute index */ @@ -1249,7 +1249,7 @@ class TableWalker : public ClockedObject void setTestInterface(TlbTestInterface *ti); - Fault testWalk(const RequestPtr &walk_req, TlbEntry::DomainType domain, + Fault testWalk(const RequestPtr &walk_req, DomainType domain, LookupLevel lookup_level); }; diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index a8216204f8..24819d6ec0 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -58,8 +58,41 @@ namespace gem5 using namespace ArmISA; +TlbEntry* +TLB::Table::accessEntry(const KeyType &key) +{ + auto entry = findEntry(key); + + if (entry && !key.functional) { + accessEntry(entry); + } + + return entry; +} + +TlbEntry* +TLB::Table::findEntry(const KeyType &key) const +{ + auto candidates = indexingPolicy->getPossibleEntries(key); + + for (auto candidate : candidates) { + auto entry = static_cast(candidate); + // We check for pageSize match outside of the Entry::match + // as the latter is also used to match entries in TLBI invalidation + // where we don't care about the pageSize + if (entry->N == key.pageSize && entry->match(key)) { + return entry; + } + } + + return nullptr; +} + TLB::TLB(const ArmTLBParams &p) - : BaseTLB(p), table(new TlbEntry[p.size]), size(p.size), + : BaseTLB(p), + table(name().c_str(), p.size, p.assoc, + p.replacement_policy, p.indexing_policy), + size(p.size), isStage2(p.is_stage2), _walkCache(false), tableWalker(nullptr), @@ -88,11 +121,12 @@ TLB::TLB(const ArmTLBParams &p) partialLevels[lookup_lvl] = false; } } + + table.setDebugFlag(::gem5::debug::TLB); } TLB::~TLB() { - delete[] table; } void @@ -103,62 +137,19 @@ TLB::setTableWalker(TableWalker *table_walker) } TlbEntry* -TLB::match(const Lookup &lookup_data) -{ - // Vector of TLB entry candidates. - // Only one of them will be assigned to retval and will - // be returned to the MMU (in case of a hit) - // The vector has one entry per lookup level as it stores - // both complete and partial matches - std::vector> hits{ - LookupLevel::Num_ArmLookupLevel, {0, nullptr}}; - - int x = 0; - while (x < size) { - if (table[x].match(lookup_data)) { - const TlbEntry &entry = table[x]; - hits[entry.lookupLevel] = std::make_pair(x, &entry); - - // This is a complete translation, no need to loop further - if (!entry.partial) - break; - } - ++x; - } - - // Loop over the list of TLB entries matching our translation - // request, starting from the highest lookup level (complete - // translation) and iterating backwards (using reverse iterators) - for (auto it = hits.rbegin(); it != hits.rend(); it++) { - const auto& [idx, entry] = *it; - if (!entry) { - // No match for the current LookupLevel - continue; - } - - // Maintaining LRU array - // We only move the hit entry ahead when the position is higher - // than rangeMRU - if (idx > rangeMRU && !lookup_data.functional) { - TlbEntry tmp_entry = *entry; - for (int i = idx; i > 0; i--) - table[i] = table[i - 1]; - table[0] = tmp_entry; - return &table[0]; - } else { - return &table[idx]; - } - } - - return nullptr; -} - -TlbEntry* -TLB::lookup(const Lookup &lookup_data) +TLB::lookup(Lookup lookup_data) { const auto mode = lookup_data.mode; - TlbEntry *retval = match(lookup_data); + TlbEntry *retval = nullptr; + // We iterate over all stored sizes, starting from the + // smallest until the biggest. In this way we prioritize + // complete translations over partial translations + for (const auto &page_size : observedPageSizes) { + lookup_data.pageSize = page_size; + if (retval = table.accessEntry(lookup_data); retval) + break; + } DPRINTF(TLBVerbose, "Lookup %#x, asn %#x -> %s vmn 0x%x ss %s " "ppn %#x size: %#x pa: %#x ap:%d ns:%d ss:%s g:%d asid: %d " @@ -217,7 +208,7 @@ TLB::multiLookup(const Lookup &lookup_data) // Insert entry only if this is not a functional // lookup and if the translation is complete (unless this // TLB caches partial translations) - insert(*te); + insert(lookup_data, *te); } } } @@ -240,59 +231,40 @@ TLB::checkPromotion(TlbEntry *entry, BaseMMU::Mode mode) // insert a new TLB entry void -TLB::insert(TlbEntry &entry) +TLB::insert(const Lookup &lookup_data, TlbEntry &entry) { - DPRINTF(TLB, "Inserting entry into TLB with pfn:%#x size:%#x vpn: %#x" - " asid:%d vmid:%d N:%d global:%d valid:%d nc:%d xn:%d" - " ap:%#x domain:%#x ns:%d ss:%s xs:%d regime: %s\n", entry.pfn, - entry.size, entry.vpn, entry.asid, entry.vmid, entry.N, - entry.global, entry.valid, entry.nonCacheable, entry.xn, - entry.ap, static_cast(entry.domain), entry.ns, - entry.ss, entry.xs, regimeToStr(entry.regime)); + TlbEntry *victim = table.findVictim(lookup_data); - if (table[size - 1].valid) - DPRINTF(TLB, " - Replacing Valid entry %#x, asn %d vmn %d ppn %#x " - "size: %#x ap:%d ns:%d ss:%s g:%d xs:%d regime: %s\n", - table[size-1].vpn << table[size-1].N, table[size-1].asid, - table[size-1].vmid, table[size-1].pfn << table[size-1].N, - table[size-1].size, table[size-1].ap, table[size-1].ns, - table[size-1].ss, table[size-1].global, - table[size-1].xs, regimeToStr(table[size-1].regime)); + *victim = entry; - // inserting to MRU position and evicting the LRU one - for (int i = size - 1; i > 0; --i) - table[i] = table[i-1]; - table[0] = entry; + table.insertEntry(lookup_data, victim); + observedPageSizes.insert(entry.N); stats.inserts++; ppRefills->notify(1); } void -TLB::multiInsert(TlbEntry &entry) +TLB::multiInsert(const Lookup &lookup, TlbEntry &entry) { // Insert a partial translation only if the TLB is configured // as a walk cache if (!entry.partial || partialLevels[entry.lookupLevel]) { - insert(entry); + insert(lookup, entry); } if (auto next_level = static_cast(nextLevel())) { - next_level->multiInsert(entry); + next_level->multiInsert(lookup, entry); } } void TLB::printTlb() const { - int x = 0; - TlbEntry *te; DPRINTF(TLB, "Current TLB contents:\n"); - while (x < size) { - te = &table[x]; - if (te->valid) - DPRINTF(TLB, " * %s\n", te->print()); - ++x; + for (auto& te : table) { + if (te.valid) + DPRINTF(TLB, " * %s\n", te.print()); } } @@ -300,38 +272,34 @@ void TLB::flushAll() { DPRINTF(TLB, "Flushing all TLB entries\n"); - int x = 0; - TlbEntry *te; - while (x < size) { - te = &table[x]; - - if (te->valid) { - DPRINTF(TLB, " - %s\n", te->print()); - te->valid = false; + for (auto& te : table) { + if (te.valid) { + DPRINTF(TLB, " - %s\n", te.print()); + table.invalidate(&te); stats.flushedEntries++; } - ++x; } stats.flushTlb++; + observedPageSizes.clear(); } void TLB::flush(const TLBIOp& tlbi_op) { - int x = 0; - TlbEntry *te; - while (x < size) { - te = &table[x]; - if (tlbi_op.match(te, vmid)) { - DPRINTF(TLB, " - %s\n", te->print()); - te->valid = false; + bool valid_entry = false; + for (auto& te : table) { + if (tlbi_op.match(&te, vmid)) { + DPRINTF(TLB, " - %s\n", te.print()); + table.invalidate(&te); stats.flushedEntries++; } - ++x; + valid_entry = valid_entry || te.valid; } stats.flushTlb++; + if (!valid_entry) + observedPageSizes.clear(); } void diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index 01d945d5dc..e3307df3f0 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -46,6 +46,7 @@ #include "arch/arm/pagetable.hh" #include "arch/arm/utility.hh" #include "arch/generic/tlb.hh" +#include "base/cache/associative_cache.hh" #include "base/statistics.hh" #include "enums/TypeTLB.hh" #include "mem/request.hh" @@ -79,7 +80,7 @@ class TlbTestInterface */ virtual Fault translationCheck(const RequestPtr &req, bool is_priv, BaseMMU::Mode mode, - TlbEntry::DomainType domain) = 0; + DomainType domain) = 0; /** * Check if a page table walker access should be forced to fail. @@ -95,14 +96,21 @@ class TlbTestInterface virtual Fault walkCheck(const RequestPtr &walk_req, Addr va, bool is_secure, Addr is_priv, BaseMMU::Mode mode, - TlbEntry::DomainType domain, + DomainType domain, enums::ArmLookupLevel lookup_level) = 0; }; class TLB : public BaseTLB { protected: - TlbEntry* table; + class Table : public AssociativeCache + { + public: + using AssociativeCache::AssociativeCache; + using AssociativeCache::accessEntry; + TlbEntry* accessEntry(const KeyType &key) override; + TlbEntry* findEntry(const KeyType &key) const override; + } table; /** TLB Size */ int size; @@ -156,9 +164,19 @@ class TLB : public BaseTLB int rangeMRU; //On lookup, only move entries ahead when outside rangeMRU vmid_t vmid; + /** Set of observed page sizes in the TLB + * We update the set conservatively, therefore allowing + * false positives but not false negatives. + * This means there could be a stored page size with + * no matching TLB entry (e.g. it has been invalidated), + * but if the page size is not in the set, we are certain + * there is no associated TLB with that size + */ + std::set observedPageSizes; + public: using Params = ArmTLBParams; - using Lookup = TlbEntry::Lookup; + using Lookup = TlbEntry::KeyType; using LookupLevel = enums::ArmLookupLevel; TLB(const Params &p); @@ -167,7 +185,7 @@ class TLB : public BaseTLB /** Lookup an entry in the TLB * @return pointer to TLB entry if it exists */ - TlbEntry *lookup(const Lookup &lookup_data); + TlbEntry *lookup(Lookup lookup_data); /** Lookup an entry in the TLB and in the next levels by * following the nextLevel pointer @@ -192,10 +210,10 @@ class TLB : public BaseTLB void setVMID(vmid_t _vmid) { vmid = _vmid; } /** Insert a PTE in the current TLB */ - void insert(TlbEntry &pte); + void insert(const Lookup &lookup_data, TlbEntry &pte); /** Insert a PTE in the current TLB and in the higher levels */ - void multiInsert(TlbEntry &pte); + void multiInsert(const Lookup &lookup_data, TlbEntry &pte); /** Reset the entire TLB. Used for CPU switching to prevent stale * translations after multiple switches @@ -275,10 +293,6 @@ class TLB : public BaseTLB * data access or a data TLB entry on an instruction access: */ void checkPromotion(TlbEntry *entry, BaseMMU::Mode mode); - - /** Helper function looking up for a matching TLB entry - * Does not update stats; see lookup method instead */ - TlbEntry *match(const Lookup &lookup_data); }; } // namespace ArmISA diff --git a/src/arch/arm/tlbi_op.cc b/src/arch/arm/tlbi_op.cc index 40a4e8d8c2..a884200e97 100644 --- a/src/arch/arm/tlbi_op.cc +++ b/src/arch/arm/tlbi_op.cc @@ -206,10 +206,10 @@ TLBIALLN::matchEntry(TlbEntry* te, vmid_t vmid) const te->checkRegime(targetRegime); } -TlbEntry::Lookup +TlbEntry::KeyType TLBIMVAA::lookupGen(vmid_t vmid) const { - TlbEntry::Lookup lookup_data; + TlbEntry::KeyType lookup_data; lookup_data.va = sext<56>(addr); lookup_data.ignoreAsn = true; lookup_data.vmid = vmid; @@ -234,15 +234,15 @@ TLBIMVAA::operator()(ThreadContext* tc) bool TLBIMVAA::matchEntry(TlbEntry* te, vmid_t vmid) const { - TlbEntry::Lookup lookup_data = lookupGen(vmid); + TlbEntry::KeyType lookup_data = lookupGen(vmid); return te->match(lookup_data) && (!lastLevel || !te->partial); } -TlbEntry::Lookup +TlbEntry::KeyType TLBIMVA::lookupGen(vmid_t vmid) const { - TlbEntry::Lookup lookup_data; + TlbEntry::KeyType lookup_data; lookup_data.va = sext<56>(addr); lookup_data.asn = asid; lookup_data.ignoreAsn = false; @@ -269,7 +269,7 @@ TLBIMVA::operator()(ThreadContext* tc) bool TLBIMVA::matchEntry(TlbEntry* te, vmid_t vmid) const { - TlbEntry::Lookup lookup_data = lookupGen(vmid); + TlbEntry::KeyType lookup_data = lookupGen(vmid); return te->match(lookup_data) && (!lastLevel || !te->partial); } @@ -309,10 +309,10 @@ TLBIIPA::operator()(ThreadContext* tc) } } -TlbEntry::Lookup +TlbEntry::KeyType TLBIIPA::lookupGen(vmid_t vmid) const { - TlbEntry::Lookup lookup_data; + TlbEntry::KeyType lookup_data; lookup_data.va = szext<56>(addr); lookup_data.ignoreAsn = true; lookup_data.vmid = vmid; @@ -326,7 +326,7 @@ TLBIIPA::lookupGen(vmid_t vmid) const bool TLBIIPA::matchEntry(TlbEntry* te, vmid_t vmid) const { - TlbEntry::Lookup lookup_data = lookupGen(vmid); + TlbEntry::KeyType lookup_data = lookupGen(vmid); return te->match(lookup_data) && (!lastLevel || !te->partial) && ipaSpace == te->ipaSpace; @@ -335,7 +335,7 @@ TLBIIPA::matchEntry(TlbEntry* te, vmid_t vmid) const bool TLBIRMVA::matchEntry(TlbEntry* te, vmid_t vmid) const { - TlbEntry::Lookup lookup_data = lookupGen(vmid); + TlbEntry::KeyType lookup_data = lookupGen(vmid); lookup_data.size = rangeSize(); auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial); @@ -351,7 +351,7 @@ TLBIRMVA::matchEntry(TlbEntry* te, vmid_t vmid) const bool TLBIRMVAA::matchEntry(TlbEntry* te, vmid_t vmid) const { - TlbEntry::Lookup lookup_data = lookupGen(vmid); + TlbEntry::KeyType lookup_data = lookupGen(vmid); lookup_data.size = rangeSize(); auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial); @@ -367,7 +367,7 @@ TLBIRMVAA::matchEntry(TlbEntry* te, vmid_t vmid) const bool TLBIRIPA::matchEntry(TlbEntry* te, vmid_t vmid) const { - TlbEntry::Lookup lookup_data = lookupGen(vmid); + TlbEntry::KeyType lookup_data = lookupGen(vmid); lookup_data.size = rangeSize(); auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial); diff --git a/src/arch/arm/tlbi_op.hh b/src/arch/arm/tlbi_op.hh index 20d31a7e25..980991b899 100644 --- a/src/arch/arm/tlbi_op.hh +++ b/src/arch/arm/tlbi_op.hh @@ -279,7 +279,7 @@ class TLBIALLN : public TLBIOp class TLBIMVAA : public TLBIOp { protected: - TlbEntry::Lookup lookupGen(vmid_t vmid) const; + TlbEntry::KeyType lookupGen(vmid_t vmid) const; public: TLBIMVAA(TranslationRegime _target_regime, SecurityState _ss, Addr _addr, bool last_level, Attr _attr=Attr::None) @@ -299,7 +299,7 @@ class TLBIMVAA : public TLBIOp class TLBIMVA : public TLBIOp { protected: - TlbEntry::Lookup lookupGen(vmid_t vmid) const; + TlbEntry::KeyType lookupGen(vmid_t vmid) const; public: TLBIMVA(TranslationRegime _target_regime, SecurityState _ss, @@ -405,7 +405,7 @@ class TLBIRange class TLBIIPA : public TLBIOp { protected: - TlbEntry::Lookup lookupGen(vmid_t vmid) const; + TlbEntry::KeyType lookupGen(vmid_t vmid) const; public: TLBIIPA(TranslationRegime _target_regime, SecurityState _ss, Addr _addr, bool last_level, Attr _attr=Attr::None) diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index d0a578a524..795c9066f0 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -282,6 +282,21 @@ namespace ArmISA Secure }; + enum class TranMethod + { + LpaeTran, + VmsaTran, + UnknownTran + }; + + enum class DomainType : std::uint8_t + { + NoAccess = 0, + Client, + Reserved, + Manager + }; + enum ExceptionLevel { EL0 = 0,