63 #include "debug/Checkpoint.hh" 64 #include "debug/TLB.hh" 65 #include "debug/TLBVerbose.hh" 68 #include "params/ArmTLB.hh" 75 TLB::TLB(
const ArmTLBParams *
p)
77 isStage2(p->is_stage2), stage2Req(false), stage2DescReq(false), _attr(0),
78 directToStage2(false), tableWalker(p->walker), stage2Tlb(NULL),
79 stage2Mmu(NULL),
test(nullptr), rangeMRU(1),
80 aarch64(false), aarch64EL(
EL0), isPriv(false), isSecure(false),
81 isHyp(false),
asid(0), vmid(0), hcr(0), dacr(0),
82 miscRegValid(false), miscRegContext(0), curTranType(NormalTran)
138 const Addr paddr = req->getPaddr();
155 while (retval == NULL && x <
size) {
156 if ((!ignore_asn &&
table[x].match(va, asn, vmid, hyp, secure,
false,
158 (ignore_asn &&
table[x].match(va, vmid, hyp, secure, target_el))) {
163 for (
int i = x;
i > 0;
i--)
165 table[0] = tmp_entry;
175 DPRINTF(TLBVerbose,
"Lookup %#x, asn %#x -> %s vmn 0x%x hyp %d secure %d " 176 "ppn %#x size: %#x pa: %#x ap:%d ns:%d nstid:%d g:%d asid: %d " 178 va, asn, retval ?
"hit" :
"miss", vmid, hyp, secure,
179 retval ? retval->
pfn : 0, retval ? retval->
size : 0,
180 retval ? retval->
pAddr(va) : 0, retval ? retval->
ap : 0,
181 retval ? retval->
ns : 0, retval ? retval->
nstid : 0,
182 retval ? retval->
global : 0, retval ? retval->
asid : 0,
183 retval ? retval->
el : 0);
192 DPRINTF(
TLB,
"Inserting entry into TLB with pfn:%#x size:%#x vpn: %#x" 193 " asid:%d vmid:%d N:%d global:%d valid:%d nc:%d xn:%d" 194 " ap:%#x domain:%#x ns:%d nstid:%d isHyp:%d\n", entry.
pfn,
201 DPRINTF(
TLB,
" - Replacing Valid entry %#x, asn %d vmn %d ppn %#x " 202 "size: %#x ap:%d ns:%d nstid:%d g:%d isHyp:%d el: %d\n",
211 for (
int i =
size - 1;
i > 0; --
i)
237 DPRINTF(
TLB,
"Flushing all TLB entries (%s lookup)\n",
238 (secure_lookup ?
"secure" :
"non-secure"));
243 const bool el_match = ignore_el ?
246 if (te->
valid && secure_lookup == !te->
nstid &&
247 (te->
vmid ==
vmid || secure_lookup) && el_match) {
268 bool hyp = target_el ==
EL2;
270 DPRINTF(
TLB,
"Flushing all NS TLB entries (%s lookup)\n",
271 (hyp ?
"hyp" :
"non-hyp"));
276 const bool el_match = ignore_el ?
300 DPRINTF(
TLB,
"Flushing TLB entries with mva: %#x, asid: %#x " 301 "(%s lookup)\n", mva, asn, (secure_lookup ?
302 "secure" :
"non-secure"));
303 _flushMva(mva, asn, secure_lookup,
false, target_el);
310 DPRINTF(
TLB,
"Flushing TLB entries with asid: %#x (%s lookup)\n", asn,
311 (secure_lookup ?
"secure" :
"non-secure"));
318 if (te->
valid && te->
asid == asn && secure_lookup == !te->
nstid &&
319 (te->
vmid ==
vmid || secure_lookup) &&
334 DPRINTF(
TLB,
"Flushing TLB entries with mva: %#x (%s lookup)\n", mva,
335 (secure_lookup ?
"secure" :
"non-secure"));
336 _flushMva(mva, 0xbeef, secure_lookup,
true, target_el);
348 bool hyp = target_el ==
EL2;
350 te =
lookup(mva, asn,
vmid, hyp, secure_lookup,
false, ignore_asn,
353 if (secure_lookup == !te->
nstid) {
358 te =
lookup(mva, asn,
vmid, hyp, secure_lookup,
false, ignore_asn,
381 TLB *otlb =
dynamic_cast<TLB*
>(_otlb);
398 panic(
"Incompatible TLB type!");
408 .
desc(
"ITB inst hits")
413 .
desc(
"ITB inst misses")
418 .
desc(
"ITB inst accesses")
423 .
desc(
"DTB read hits")
428 .
desc(
"DTB read misses")
433 .
desc(
"DTB read accesses")
438 .
desc(
"DTB write hits")
443 .
desc(
"DTB write misses")
448 .
desc(
"DTB write accesses")
463 .
desc(
"DTB accesses")
468 .
desc(
"Number of times complete TLB was flushed")
473 .
desc(
"Number of times TLB was flushed by MVA")
477 .
name(
name() +
".flush_tlb_mva_asid")
478 .
desc(
"Number of times TLB was flushed by MVA & ASID")
483 .
desc(
"Number of times TLB was flushed by ASID")
488 .
desc(
"Number of entries that have been flushed from TLB")
493 .
desc(
"Number of TLB faults due to alignment restrictions")
498 .
desc(
"Number of TLB faults due to prefetch")
503 .
desc(
"Number of TLB faults due to domain restrictions")
508 .
desc(
"Number of TLB faults due to permissions restrictions")
527 Translation *translation,
bool &delay,
bool timing)
530 Addr vaddr_tainted = req->getVaddr();
536 vaddr = vaddr_tainted;
539 bool is_fetch = (mode ==
Execute);
540 bool is_write = (mode ==
Write);
543 assert(flags &
MustBeOne || req->isPrefetch());
547 return std::make_shared<DataAbort>(
560 return std::make_shared<GenericPageTableFault>(vaddr_tainted);
561 req->setPaddr(paddr);
571 if (req->isCacheMaintenance()) {
577 bool is_fetch = (mode ==
Execute);
578 bool is_write = (mode ==
Write);
591 return std::make_shared<DataAbort>(
603 return std::make_shared<DataAbort>(
613 if (req->isPrefetch()) {
616 return std::make_shared<PrefetchAbort>(
623 switch ((
dacr >> (static_cast<uint8_t>(te->
domain) * 2)) & 0x3) {
626 DPRINTF(
TLB,
"TLB Fault: Data abort on domain. DACR: %#x" 627 " domain: %#x write:%d\n",
dacr,
628 static_cast<uint8_t>(te->
domain), is_write);
633 return std::make_shared<PrefetchAbort>(
638 return std::make_shared<DataAbort>(
646 panic(
"UNPRED domain\n");
654 uint8_t hap = te->
hap;
660 bool isWritable =
true;
669 DPRINTF(
TLB,
"Access permissions 0, checking rs:%#x\n",
672 switch ((
int)
sctlr.rs) {
677 abt = is_write || !is_priv;
693 abt = !is_priv && is_write;
694 isWritable = is_priv;
700 panic(
"UNPRED premissions\n");
702 abt = !is_priv || is_write;
711 panic(
"Unknown permissions %#x\n", ap);
715 bool hapAbt = is_write ? !(hap & 2) : !(hap & 1);
716 bool xn = te->
xn || (isWritable &&
sctlr.wxn) ||
717 (ap == 3 &&
sctlr.uwxn && is_priv);
718 if (is_fetch && (abt || xn ||
722 DPRINTF(
TLB,
"TLB Fault: Prefetch abort on permission check. AP:%d " 723 "priv:%d write:%d ns:%d sif:%d sctlr.afe: %d \n",
724 ap, is_priv, is_write, te->
ns,
scr.sif,
sctlr.afe);
727 return std::make_shared<PrefetchAbort>(
731 }
else if (abt | hapAbt) {
733 DPRINTF(
TLB,
"TLB Fault: Data abort on permission check. AP:%d priv:%d" 734 " write:%d\n", ap, is_priv, is_write);
735 return std::make_shared<DataAbort>(
759 Addr vaddr_tainted = req->getVaddr();
764 bool is_fetch = (mode ==
Execute);
766 bool is_write = !req->isCacheClean() && mode ==
Write;
767 bool is_atomic = req->isAtomic();
778 return std::make_shared<DataAbort>(
779 vaddr_tainted, te->
domain, is_write,
790 return std::make_shared<DataAbort>(
793 is_atomic ? false : is_write,
802 if (req->isPrefetch()) {
805 return std::make_shared<PrefetchAbort>(
812 uint8_t ap = 0x3 & (te->
ap);
816 uint8_t pxn = te->
pxn;
817 bool r = !is_write && !is_fetch;
825 bool grant_read =
true;
826 DPRINTF(TLBVerbose,
"Checking permissions: ap:%d, xn:%d, pxn:%d, r:%d, " 827 "w:%d, x:%d\n", ap, xn, pxn, r, w, x);
834 uint8_t hap = 0x3 & te->
hap;
835 grant_read = hap & 0x1;
838 grant = !
sctlr.wxn && !xn;
839 }
else if (is_write) {
848 grant_read = ap & 0x1;
849 uint8_t perm = (ap << 2) | (xn << 1) | pxn;
859 grant = r || w || (x && !
sctlr.wxn);
886 uint8_t perm = (ap << 2) | (xn << 1) | pxn;
890 grant = r || w || (x && !
sctlr.wxn);
928 uint8_t perm = (ap & 0x2) | xn;
931 grant = r || w || (x && !
sctlr.wxn) ;
953 DPRINTF(
TLB,
"TLB Fault: Prefetch abort on permission check. " 954 "AP:%d priv:%d write:%d ns:%d sif:%d " 956 ap, is_priv, is_write, te->
ns,
scr.sif,
sctlr.afe);
959 return std::make_shared<PrefetchAbort>(
965 DPRINTF(
TLB,
"TLB Fault: Data abort on permission check. AP:%d " 966 "priv:%d write:%d\n", ap, is_priv, is_write);
967 return std::make_shared<DataAbort>(
968 vaddr_tainted, te->
domain,
969 (is_atomic && !grant_read) ?
false : is_write,
989 if (mmfr1.pan &&
cpsr.pan && (ap & 0x1) && mode !=
Execute &&
990 (!req->isCacheMaintenance() ||
1002 bool is_fetch = (mode ==
Execute);
1003 req->setPaddr(vaddr);
1010 if (long_desc_format ||
sctlr.tre == 0 ||
nmrr.ir0 == 0 ||
1011 nmrr.or0 == 0 ||
prrr.tr0 != 0x2) {
1012 if (!req->isCacheMaintenance()) {
1038 DPRINTF(TLBVerbose,
"(No MMU) setting memory attributes: shareable: " 1039 "%d, innerAttrs: %d, outerAttrs: %d, isStage2: %d\n",
1049 Translation *translation,
bool &delay,
bool timing,
1054 bool is_fetch = (mode ==
Execute);
1058 Addr vaddr_tainted = req->getVaddr();
1061 functional, &mergeTe);
1063 if ((te == NULL) && (fault ==
NoFault)) delay =
true;
1070 "Setting memory attributes: shareable: %d, innerAttrs: %d, " 1071 "outerAttrs: %d, mtype: %d, isStage2: %d\n",
1096 bool is_write = (mode ==
Write);
1097 return std::make_shared<DataAbort>(
1120 Translation *translation,
bool &delay,
bool timing,
1124 assert(!(timing && functional));
1128 Addr vaddr_tainted = req->getVaddr();
1134 vaddr = vaddr_tainted;
1137 bool is_fetch = (mode ==
Execute);
1138 bool is_write = (mode ==
Write);
1145 DPRINTF(TLBVerbose,
"CPSR is priv:%d UserMode:%d secure:%d S1S2NsTran:%d\n",
1148 DPRINTF(
TLB,
"translateFs addr %#x, mode %d, st2 %d, scr %#x sctlr %#x " 1149 "flags %#lx tranType 0x%x\n", vaddr_tainted, mode,
isStage2,
1152 if ((req->isInstFetch() && (!
sctlr.i)) ||
1153 ((!req->isInstFetch()) && (!
sctlr.c))){
1154 if (!req->isCacheMaintenance()) {
1160 assert(flags &
MustBeOne || req->isPrefetch());
1164 return std::make_shared<DataAbort>(
1178 DPRINTF(TLBVerbose,
"Translating %s=%#x context=%d\n",
1182 functional, vaddr, tranMethod);
1200 fault =
translateFs(req, tc, mode, NULL, delay,
false, tranType);
1202 fault =
translateSe(req, tc, mode, NULL, delay,
false);
1221 fault =
translateFs(req, tc, mode, NULL, delay,
false, tranType,
true);
1223 fault =
translateSe(req, tc, mode, NULL, delay,
false);
1240 assert(translation);
1253 fault =
translateFs(req, tc, mode, translation, delay,
true, tranType);
1255 fault =
translateSe(req, tc, mode, translation, delay,
true);
1256 DPRINTF(TLBVerbose,
"Translation returning delay=%d fault=%d\n", delay, fault !=
1264 if (translation && (callFromS2 || !
stage2Req || req->hasPaddr() || fault !=
NoFault)) {
1266 translation->
finish(fault, req, tc, mode);
1290 DPRINTF(TLBVerbose,
"TLB variables changed!\n");
1304 switch (aarch64EL) {
1310 uint64_t ttbr_asid =
ttbcr.a1 ?
1336 isHyp &= (tranType &
S1CTran) == 0;
1342 !(tranType &
S1CTran) && (aarch64EL <
EL2) &&
1370 asid = context_id.asid;
1385 isHyp &= (tranType &
S1CTran) == 0;
1434 panic(
"Unknown translation mode!\n");
1440 Translation *translation,
bool timing,
bool functional,
1448 bool is_fetch = (mode ==
Execute);
1449 bool is_write = (mode ==
Write);
1451 Addr vaddr_tainted = req->getVaddr();
1458 vaddr = vaddr_tainted;
1462 if (req->isPrefetch()) {
1467 return std::make_shared<PrefetchAbort>(
1480 DPRINTF(
TLB,
"TLB Miss: Starting hardware table walker for %#x(%d:%d)\n",
1484 translation, timing, functional, is_secure,
1487 if (timing || fault !=
NoFault) {
1509 Translation *translation,
bool timing,
bool functional,
1519 fault =
getTE(&s2Te, req, tc, mode, translation, timing, functional,
1522 if ((s2Te != NULL) && (fault ==
NoFault)) {
1534 Addr vaddr_tainted = req->getVaddr();
1537 fault =
getTE(&s1Te, req, tc, mode, translation, timing, functional,
1540 if ((s1Te != NULL) && (fault ==
NoFault)) {
1548 req, translation, mode, timing, functional,
curTranType);
1549 fault = s2Lookup->
getTe(tc, mergeTe);
1564 DPRINTF(TLBVerbose,
"s2TLB: reqVa %#x, reqPa %#x, fault %p\n",
1565 vaddr_tainted, req->hasPaddr() ? req->getPaddr() : ~0, fault);
1585 fatal_if(!ti,
"%s is not a valid ARM TLB tester\n", _ti->
name());
1594 if (!
test || !req->hasSize() || req->getSize() == 0 ||
1595 req->isCacheMaintenance()) {
1598 return test->translationCheck(req,
isPriv, mode, domain);
1609 return test->walkCheck(pa, size, va, is_secure,
isPriv, mode,
1610 domain, lookup_level);
1616 ArmTLBParams::create()
#define panic(...)
This implements a cprintf based panic() function.
ProbePoints::PMUUPtr ppRefills
PMU probe for TLB refills.
The request is to an uncacheable address.
Ports are used to interface objects to each other.
void translateTiming(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode, ArmTranslationType tranType)
Fault checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode, ThreadContext *tc)
Fault getResultTe(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode, Translation *translation, bool timing, bool functional, TlbEntry *mergeTe)
decltype(nullptr) constexpr NoFault
static ExceptionLevel currEL(ThreadContext *tc)
Fault getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode, Translation *translation, bool timing, bool functional, bool is_secure, ArmTranslationType tranType)
void flushAllNs(ExceptionLevel target_el, bool ignore_el=false)
Remove all entries in the non secure world, depending on whether they were allocated in hyp mode or n...
void flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el)
Remove all entries that match the va regardless of asn.
DmaPort & getDMAPort()
Get the port that ultimately belongs to the stage-two MMU, but is used by the two table walkers...
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
bool contains(const Addr &a) const
Determine if the range contains an address.
std::shared_ptr< Request > RequestPtr
void flushAllSecurity(bool secure_lookup, ExceptionLevel target_el, bool ignore_el=false)
Reset the entire TLB.
virtual void markDelayed()=0
Signal that the translation has been delayed due to a hw page table walk.
The request is required to be strictly ordered by CPU models and is non-speculative.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
virtual Process * getProcessPtr()=0
The request targets the secure memory space.
static ExceptionLevel tranTypeEL(CPSR cpsr, ArmTranslationType type)
Determine the EL to use for the purpose of a translation given a specific translation type...
virtual void regStats()
Callback to set stat parameters.
Overload hash function for BasicBlockRange type.
std::string print() const
void regStats() override
Callback to set stat parameters.
Stats::Scalar prefetchFaults
bool checkPAN(ThreadContext *tc, uint8_t ap, const RequestPtr &req, Mode mode)
void drainResume() override
Resume execution after a successful drain.
Port * getTableWalkerPort() override
Get the table walker port.
Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el, TCR tcr, bool isInstr)
Removes the tag from tagged addresses if that mode is enabled.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
Fault walk(const RequestPtr &req, ThreadContext *tc, uint16_t asid, uint8_t _vmid, bool _isHyp, TLB::Mode mode, TLB::Translation *_trans, bool timing, bool functional, bool secure, TLB::ArmTranslationType tranType, bool _stage2Req)
Fault testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode, TlbEntry::DomainType domain, LookupLevel lookup_level)
Stats::Formula writeAccesses
TableWalker * tableWalker
bool haveVirtualization() const
Stats::Scalar flushedEntries
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
bool haveLargeAsid64() const
Fault getTe(ThreadContext *tc, TlbEntry *destTe)
Fault finalizePhysical(const RequestPtr &req, ThreadContext *tc, Mode mode) const override
Do post-translation physical address finalization.
Stats::Scalar permsFaults
Stats::Scalar writeMisses
bool translate(Addr vaddr, Addr &paddr)
Translate function.
void _flushMva(Addr mva, uint64_t asn, bool secure_lookup, bool ignore_asn, ExceptionLevel target_el)
Remove any entries that match both a va and asn.
virtual void annotate(AnnotationIDs id, uint64_t val)
void flushAsid(uint64_t asn, bool secure_lookup, ExceptionLevel target_el)
Remove any entries that match the asn.
void setMMU(Stage2MMU *m, MasterID master_id)
Stats::Scalar domainFaults
void updateMiscReg(ThreadContext *tc, ArmTranslationType tranType=NormalTran)
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Fault translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing, ArmTranslationType tranType, bool functional=false)
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, Mode mode)=0
bool checkELMatch(ExceptionLevel target_el) const
This request is to a memory mapped register.
Addr pAddr(Addr va) const
bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr)
Do a functional lookup on the TLB (for debugging) and don't modify any internal state.
bool haveVirtualization() const
Returns true if this system implements the virtualization Extensions.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Declaration of IniFile object.
Fault checkPermissions(TlbEntry *te, const RequestPtr &req, Mode mode)
virtual const std::string name() const
Stats::Scalar flushTlbMva
void init() override
setup all the back pointers
Stats::Scalar flushTlbMvaAsid
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
const AddrRange & m5opRange() const
Range used by memory-mapped m5 pseudo-ops if enabled.
ProbePointArg generates a point for the class of Arg.
void flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el)
Invalidate all entries in the stage 2 TLB that match the given ipa and the current VMID...
Stats::Formula readAccesses
EmulationPageTable * pTable
Stats::Scalar alignFaults
void flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup, ExceptionLevel target_el)
Remove any entries that match both a va and asn.
Declarations of a non-full system Page Table.
bool longDescFormatInUse(ThreadContext *tc)
TlbEntry * lookup(Addr vpn, uint16_t asn, uint8_t vmid, bool hyp, bool secure, bool functional, bool ignore_asn, ExceptionLevel target_el)
Lookup an entry in the TLB.
This is a write that is targeted and zeroing an entire cache block.
void insert(Addr vaddr, TlbEntry &pte)
void regProbePoints() override
Register probe points for this object.
Fault translateSe(const RequestPtr &req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing)
void setMMU(Stage2MMU *m, MasterID master_id)
ProbeManager * getProbeManager()
Get the probe manager for this object.
int snsBankedIndex(MiscRegIndex reg, ThreadContext *tc)
Fault translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode, TLB::ArmTranslationType tranType, Addr vaddr, bool long_desc_format)
virtual ContextID contextId() const =0
Stats::Formula instAccesses
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Stats::Scalar flushTlbAsid
bool inSecureState(ThreadContext *tc)
Fault translateComplete(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode, ArmTranslationType tranType, bool callFromS2)
static const int NumArgumentRegs M5_VAR_USED
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
void takeOverFrom(BaseTLB *otlb) override
Take over from an old tlb context.
ArmTranslationType curTranType
virtual RegVal readMiscReg(RegIndex misc_reg)=0
void setAttr(uint64_t attr)
Accessor functions for memory attributes for last accessed TLB entry.
std::shared_ptr< FaultBase > Fault
Fault translateMmuOn(ThreadContext *tc, const RequestPtr &req, Mode mode, Translation *translation, bool &delay, bool timing, bool functional, Addr vaddr, ArmFault::TranMethod tranMethod)
Fault translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode, ArmTranslationType tranType)
Abstract superclass for simulation objects.
void setAttributes(bool lpae)
void setTestInterface(SimObject *ti)
Fault testTranslation(const RequestPtr &req, Mode mode, TlbEntry::DomainType domain)