64 #include "debug/Checkpoint.hh"
65 #include "debug/TLB.hh"
66 #include "debug/TLBVerbose.hh"
69 #include "params/ArmTLB.hh"
74 using namespace ArmISA;
76 TLB::TLB(
const ArmTLBParams *
p)
78 isStage2(p->is_stage2), stage2Req(false), _attr(0),
79 directToStage2(false), tableWalker(p->walker), stage2Tlb(NULL),
80 stage2Mmu(NULL), test(nullptr), rangeMRU(1),
81 aarch64(false), aarch64EL(
EL0), isPriv(false), isSecure(false),
82 isHyp(false),
asid(0), vmid(0), dacr(0),
83 miscRegValid(false), miscRegContext(0), curTranType(NormalTran)
152 bool functional,
bool ignore_asn, uint8_t target_el)
159 while (retval == NULL && x <
size) {
160 if ((!ignore_asn &&
table[x].match(va, asn, vmid, hyp, secure,
false,
162 (ignore_asn &&
table[x].match(va, vmid, hyp, secure, target_el))) {
167 for (
int i = x;
i > 0;
i--)
169 table[0] = tmp_entry;
179 DPRINTF(TLBVerbose,
"Lookup %#x, asn %#x -> %s vmn 0x%x hyp %d secure %d "
180 "ppn %#x size: %#x pa: %#x ap:%d ns:%d nstid:%d g:%d asid: %d "
182 va, asn, retval ?
"hit" :
"miss", vmid, hyp, secure,
183 retval ? retval->
pfn : 0, retval ? retval->
size : 0,
184 retval ? retval->
pAddr(va) : 0, retval ? retval->
ap : 0,
185 retval ? retval->
ns : 0, retval ? retval->
nstid : 0,
186 retval ? retval->
global : 0, retval ? retval->
asid : 0,
187 retval ? retval->
el : 0);
196 DPRINTF(
TLB,
"Inserting entry into TLB with pfn:%#x size:%#x vpn: %#x"
197 " asid:%d vmid:%d N:%d global:%d valid:%d nc:%d xn:%d"
198 " ap:%#x domain:%#x ns:%d nstid:%d isHyp:%d\n", entry.
pfn,
205 DPRINTF(
TLB,
" - Replacing Valid entry %#x, asn %d vmn %d ppn %#x "
206 "size: %#x ap:%d ns:%d nstid:%d g:%d isHyp:%d el: %d\n",
215 for (
int i =
size - 1;
i > 0; --
i)
240 DPRINTF(
TLB,
"Flushing all TLB entries (%s lookup)\n",
241 (secure_lookup ?
"secure" :
"non-secure"));
246 if (te->
valid && secure_lookup == !te->
nstid &&
247 (te->
vmid ==
vmid || secure_lookup) &&
269 DPRINTF(
TLB,
"Flushing all NS TLB entries (%s lookup)\n",
270 (hyp ?
"hyp" :
"non-hyp"));
296 DPRINTF(
TLB,
"Flushing TLB entries with mva: %#x, asid: %#x "
297 "(%s lookup)\n", mva, asn, (secure_lookup ?
298 "secure" :
"non-secure"));
299 _flushMva(mva, asn, secure_lookup,
false,
false, target_el);
306 DPRINTF(
TLB,
"Flushing TLB entries with asid: %#x (%s lookup)\n", asn,
307 (secure_lookup ?
"secure" :
"non-secure"));
314 if (te->
valid && te->
asid == asn && secure_lookup == !te->
nstid &&
315 (te->
vmid ==
vmid || secure_lookup) &&
330 DPRINTF(
TLB,
"Flushing TLB entries with mva: %#x (%s lookup)\n", mva,
331 (secure_lookup ?
"secure" :
"non-secure"));
332 _flushMva(mva, 0xbeef, secure_lookup, hyp,
true, target_el);
338 bool ignore_asn, uint8_t target_el)
343 te =
lookup(mva, asn,
vmid, hyp, secure_lookup,
false, ignore_asn,
346 if (secure_lookup == !te->nstid) {
351 te =
lookup(mva, asn,
vmid, hyp, secure_lookup,
false, ignore_asn,
368 if (target_el == 2 || target_el == 3) {
369 elMatch = (tentry_el == target_el);
371 elMatch = (tentry_el == 0) || (tentry_el == 1);
388 TLB *otlb =
dynamic_cast<TLB*
>(_otlb);
404 panic(
"Incompatible TLB type!");
411 DPRINTF(Checkpoint,
"Serializing Arm TLB\n");
418 int num_entries =
size;
427 DPRINTF(Checkpoint,
"Unserializing Arm TLB\n");
436 for (
int i = 0;
i < min(
size, num_entries);
i++)
446 .
desc(
"ITB inst hits")
451 .
desc(
"ITB inst misses")
456 .
desc(
"ITB inst accesses")
461 .
desc(
"DTB read hits")
466 .
desc(
"DTB read misses")
471 .
desc(
"DTB read accesses")
476 .
desc(
"DTB write hits")
481 .
desc(
"DTB write misses")
486 .
desc(
"DTB write accesses")
501 .
desc(
"DTB accesses")
506 .
desc(
"Number of times complete TLB was flushed")
511 .
desc(
"Number of times TLB was flushed by MVA")
515 .
name(
name() +
".flush_tlb_mva_asid")
516 .
desc(
"Number of times TLB was flushed by MVA & ASID")
521 .
desc(
"Number of times TLB was flushed by ASID")
526 .
desc(
"Number of entries that have been flushed from TLB")
531 .
desc(
"Number of TLB faults due to alignment restrictions")
536 .
desc(
"Number of TLB faults due to prefetch")
541 .
desc(
"Number of TLB faults due to domain restrictions")
546 .
desc(
"Number of TLB faults due to permissions restrictions")
565 Translation *translation,
bool &delay,
bool timing)
573 vaddr = vaddr_tainted;
576 bool is_fetch = (mode ==
Execute);
577 bool is_write = (mode ==
Write);
584 return std::make_shared<DataAbort>(
597 return std::make_shared<GenericPageTableFault>(vaddr_tainted);
608 bool is_fetch = (mode ==
Execute);
609 bool is_write = (mode ==
Write);
622 return std::make_shared<DataAbort>(
634 return std::make_shared<DataAbort>(
647 return std::make_shared<PrefetchAbort>(
654 switch ((
dacr >> (static_cast<uint8_t>(te->
domain) * 2)) & 0x3) {
657 DPRINTF(
TLB,
"TLB Fault: Data abort on domain. DACR: %#x"
658 " domain: %#x write:%d\n",
dacr,
659 static_cast<uint8_t>(te->
domain), is_write);
664 return std::make_shared<PrefetchAbort>(
669 return std::make_shared<DataAbort>(
677 panic(
"UNPRED domain\n");
685 uint8_t hap = te->
hap;
691 bool isWritable =
true;
700 DPRINTF(
TLB,
"Access permissions 0, checking rs:%#x\n",
703 switch ((
int)
sctlr.rs) {
708 abt = is_write || !is_priv;
724 abt = !is_priv && is_write;
725 isWritable = is_priv;
731 panic(
"UNPRED premissions\n");
733 abt = !is_priv || is_write;
742 panic(
"Unknown permissions %#x\n", ap);
746 bool hapAbt = is_write ? !(hap & 2) : !(hap & 1);
747 bool xn = te->
xn || (isWritable &&
sctlr.wxn) ||
748 (ap == 3 &&
sctlr.uwxn && is_priv);
749 if (is_fetch && (abt || xn ||
753 DPRINTF(
TLB,
"TLB Fault: Prefetch abort on permission check. AP:%d "
754 "priv:%d write:%d ns:%d sif:%d sctlr.afe: %d \n",
755 ap, is_priv, is_write, te->
ns,
scr.sif,
sctlr.afe);
758 return std::make_shared<PrefetchAbort>(
762 }
else if (abt | hapAbt) {
764 DPRINTF(
TLB,
"TLB Fault: Data abort on permission check. AP:%d priv:%d"
765 " write:%d\n", ap, is_priv, is_write);
766 return std::make_shared<DataAbort>(
785 bool is_fetch = (mode ==
Execute);
786 bool is_write = (mode ==
Write);
797 return std::make_shared<DataAbort>(
798 vaddr_tainted, te->
domain, is_write,
809 return std::make_shared<DataAbort>(
823 return std::make_shared<PrefetchAbort>(
830 uint8_t ap = 0x3 & (te->
ap);
834 uint8_t pxn = te->
pxn;
835 bool r = !is_write && !is_fetch;
838 DPRINTF(TLBVerbose,
"Checking permissions: ap:%d, xn:%d, pxn:%d, r:%d, "
839 "w:%d, x:%d\n", ap, xn, pxn, r, w, x);
846 uint8_t hap = 0x3 & te->
hap;
849 grant = !
sctlr.wxn && !xn;
850 }
else if (is_write) {
859 uint8_t perm = (ap << 2) | (xn << 1) | pxn;
869 grant = r || w || (x && !
sctlr.wxn);
890 uint8_t perm = (ap << 2) | (xn << 1) | pxn;
894 grant = r || w || (x && !
sctlr.wxn);
926 uint8_t perm = (ap & 0x2) | xn;
929 grant = r || w || (x && !
sctlr.wxn) ;
951 DPRINTF(
TLB,
"TLB Fault: Prefetch abort on permission check. "
952 "AP:%d priv:%d write:%d ns:%d sif:%d "
954 ap, is_priv, is_write, te->
ns,
scr.sif,
sctlr.afe);
957 return std::make_shared<PrefetchAbort>(
963 DPRINTF(
TLB,
"TLB Fault: Data abort on permission check. AP:%d "
964 "priv:%d write:%d\n", ap, is_priv, is_write);
965 return std::make_shared<DataAbort>(
966 vaddr_tainted, te->
domain, is_write,
977 Translation *translation,
bool &delay,
bool timing,
981 assert(!(timing && functional));
990 vaddr = vaddr_tainted;
993 bool is_fetch = (mode ==
Execute);
994 bool is_write = (mode ==
Write);
1001 DPRINTF(TLBVerbose,
"CPSR is priv:%d UserMode:%d secure:%d S1S2NsTran:%d\n",
1004 DPRINTF(
TLB,
"translateFs addr %#x, mode %d, st2 %d, scr %#x sctlr %#x "
1005 "flags %#lx tranType 0x%x\n", vaddr_tainted, mode,
isStage2,
1017 return std::make_shared<DataAbort>(
1036 if (long_desc_format ||
sctlr.tre == 0) {
1063 DPRINTF(TLBVerbose,
"(No MMU) setting memory attributes: shareable: "
1064 "%d, innerAttrs: %d, outerAttrs: %d, isStage2: %d\n",
1072 DPRINTF(TLBVerbose,
"Translating %s=%#x context=%d\n",
1079 functional, &mergeTe);
1081 if ((te == NULL) && (fault ==
NoFault)) delay =
true;
1088 "Setting memory attributes: shareable: %d, innerAttrs: %d, "
1089 "outerAttrs: %d, mtype: %d, isStage2: %d\n",
1114 return std::make_shared<DataAbort>(
1129 return std::make_shared<IllegalInstSetStateFault>();
1154 fault =
translateFs(req, tc, mode, NULL, delay,
false, tranType);
1156 fault =
translateSe(req, tc, mode, NULL, delay,
false);
1175 fault =
translateFs(req, tc, mode, NULL, delay,
false, tranType,
true);
1177 fault =
translateSe(req, tc, mode, NULL, delay,
false);
1193 assert(translation);
1206 fault =
translateFs(req, tc, mode, translation, delay,
true, tranType);
1208 fault =
translateSe(req, tc, mode, translation, delay,
true);
1209 DPRINTF(TLBVerbose,
"Translation returning delay=%d fault=%d\n", delay, fault !=
1219 translation->
finish(fault, req, tc, mode);
1243 DPRINTF(TLBVerbose,
"TLB variables changed!\n");
1251 aarch64 = opModeIs64(op_mode) ||
1285 uint64_t ttbr_asid =
ttbcr.a1 ?
1310 isHyp &= (tranType &
S1CTran) == 0;
1341 asid = context_id.asid;
1356 isHyp &= (tranType &
S1CTran) == 0;
1380 Translation *translation,
bool timing,
bool functional,
1383 bool is_fetch = (mode ==
Execute);
1384 bool is_write = (mode ==
Write);
1392 vaddr = vaddr_tainted;
1401 return std::make_shared<PrefetchAbort>(
1414 DPRINTF(
TLB,
"TLB Miss: Starting hardware table walker for %#x(%d:%d)\n",
1418 translation, timing, functional, is_secure,
1421 if (timing || fault !=
NoFault) {
1442 Translation *translation,
bool timing,
bool functional,
1452 fault =
getTE(&s2Te, req, tc, mode, translation, timing, functional,
1455 if ((s2Te != NULL) && (fault =
NoFault)) {
1470 fault =
getTE(&s1Te, req, tc, mode, translation, timing, functional,
1473 if ((s1Te != NULL) && (fault ==
NoFault)) {
1481 req, translation, mode, timing, functional,
curTranType);
1482 fault = s2Lookup->
getTe(tc, mergeTe);
1497 DPRINTF(TLBVerbose,
"s2TLB: reqVa %#x, reqPa %#x, fault %p\n",
1518 fatal_if(!ti,
"%s is not a valid ARM TLB tester\n", _ti->
name());
1541 domain, lookup_level);
1547 ArmTLBParams::create()
ProbePoints::PMUUPtr ppRefills
PMU probe for TLB refills.
void flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup, uint8_t target_el)
Remove any entries that match both a va and asn.
Fault finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
decltype(nullptr) constexpr NoFault
bool checkELMatch(uint8_t target_el, uint8_t tentry_el, bool ignore_el)
Fault translateFs(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing, ArmTranslationType tranType, bool functional=false)
virtual Fault translationCheck(RequestPtr req, bool is_priv, BaseTLB::Mode mode, TlbEntry::DomainType domain)=0
Check if a TLB translation should be forced to fail.
void setAsid(int asid)
Accessor function for asid.
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
void flushAllSecurity(bool secure_lookup, uint8_t 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.
bool hasSize() const
Accessor for size.
DmaPort & getPort()
Get the port that ultimately belongs to the stage-two MMU, but is used by the two table walkers...
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
virtual Process * getProcessPtr()=0
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Addr getPC() const
Accessor function for pc.
bool contains(const Addr &a) const
Determine if the range contains an address.
void regStats() override
Register statistics for this object.
Stats::Scalar prefetchFaults
virtual void regStats()
Register statistics for this object.
bool haveVirtualization() const
void drainResume() override
Resume execution after a successful drain.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
Fault testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode, TlbEntry::DomainType domain, LookupLevel lookup_level)
Stats::Formula writeAccesses
TableWalker * tableWalker
void _flushMva(Addr mva, uint64_t asn, bool secure_lookup, bool hyp, bool ignore_asn, uint8_t target_el)
Remove any entries that match both a va and asn.
Stats::Scalar flushedEntries
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
Addr iprAddressPseudoInst(uint8_t func, uint8_t subfunc)
Generate a generic IPR address that emulates a pseudo inst.
#define UNSERIALIZE_SCALAR(scalar)
Fault translateComplete(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode, ArmTranslationType tranType, bool callFromS2)
Fault getTe(ThreadContext *tc, TlbEntry *destTe)
Stats::Scalar permsFaults
std::string csprintf(const char *format, const Args &...args)
Stats::Scalar writeMisses
void flushMva(Addr mva, bool secure_lookup, bool hyp, uint8_t target_el)
Remove all entries that match the va regardless of asn.
bool translate(Addr vaddr, Addr &paddr)
Translate function.
Fault translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode, ArmTranslationType tranType=NormalTran)
virtual void annotate(AnnotationIDs id, uint64_t val)
void setMMU(Stage2MMU *m, MasterID master_id)
The request is to an uncacheable address.
Addr pAddr(Addr va) const
BaseMasterPort * getMasterPort() override
Get the table walker master port.
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Fault getTE(TlbEntry **te, RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool timing, bool functional, bool is_secure, ArmTranslationType tranType)
static ExceptionLevel opModeToEL(OperatingMode mode)
Stats::Scalar domainFaults
void updateMiscReg(ThreadContext *tc, ArmTranslationType tranType=NormalTran)
const AddrRange & m5opRange() const
Range used by memory-mapped m5 pseudo-ops if enabled.
TlbEntry * lookup(Addr vpn, uint16_t asn, uint8_t vmid, bool hyp, bool secure, bool functional, bool ignore_asn, uint8_t target_el)
Lookup an entry in the TLB.
virtual Fault walkCheck(Addr pa, Addr size, Addr va, bool is_secure, Addr is_priv, BaseTLB::Mode mode, TlbEntry::DomainType domain, LookupLevel lookup_level)=0
Check if a page table walker access should be forced to fail.
Fault checkPermissions64(TlbEntry *te, RequestPtr req, Mode mode, ThreadContext *tc)
bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr)
Do a functional lookup on the TLB (for debugging) and don't modify any internal state.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Declaration of IniFile object.
Stats::Scalar flushTlbMva
void init() override
setup all the back pointers
#define SERIALIZE_SCALAR(scalar)
virtual MiscReg readMiscReg(int misc_reg)=0
static const int NumArgumentRegs M5_VAR_USED
Flags getFlags()
Accessor for flags.
Stats::Scalar flushTlbMvaAsid
std::string print() const
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
ProbePointArg generates a point for the class of Arg.
Stats::Formula readAccesses
virtual const std::string name() const
Stats::Scalar alignFaults
Declarations of a non-full system Page Table.
bool longDescFormatInUse(ThreadContext *tc)
void flushAsid(uint64_t asn, bool secure_lookup, uint8_t target_el)
Remove any entries that match the asn.
bool haveVirtualization() const
Returns true if this system implements the virtualization Extensions.
std::ostream CheckpointOut
void insert(Addr vaddr, TlbEntry &pte)
ISA-generic helper functions for memory mapped IPR accesses.
void regProbePoints() override
Register probe points for this object.
Fault walk(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)
void setMMU(Stage2MMU *m, MasterID master_id)
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
virtual int contextId() const =0
ProbeManager * getProbeManager()
Get the probe manager for this object.
Fault getResultTe(TlbEntry **te, RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool timing, bool functional, TlbEntry *mergeTe)
The request is required to be strictly ordered by CPU models and is non-speculative.
Stats::Formula instAccesses
void serialize(CheckpointOut &cp) const override
Serialize an object.
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode, ArmTranslationType tranType=NormalTran)
The request targets the secure memory space.
Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el, TTBCR tcr)
Removes the tag from tagged addresses if that mode is enabled.
Fault checkPermissions(TlbEntry *te, RequestPtr req, Mode mode)
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
void flushIpaVmid(Addr ipa, bool secure_lookup, bool hyp, uint8_t target_el)
Invalidate all entries in the stage 2 TLB that match the given ipa and the current VMID...
Stats::Scalar flushTlbAsid
Fault testTranslation(RequestPtr req, Mode mode, TlbEntry::DomainType domain)
bool inSecureState(ThreadContext *tc)
int flattenMiscRegNsBanked(MiscRegIndex reg, ThreadContext *tc)
fatal_if(p->js_features.size() > 16,"Too many job slot feature registers specified (%i)\n", p->js_features.size())
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
This request is to a memory mapped register.
The request should be handled by the generic IPR code (only valid together with MMAPPED_IPR) ...
void takeOverFrom(BaseTLB *otlb) override
Take over from an old tlb context.
void flushAllNs(bool hyp, uint8_t 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...
Fault translateSe(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing)
void setPaddr(Addr paddr)
Set just the physical address.
ArmTranslationType curTranType
bool haveLargeAsid64() const
void setAttr(uint64_t attr)
Accessor functions for memory attributes for last accessed TLB entry.
virtual void finish(const Fault &fault, RequestPtr req, ThreadContext *tc, Mode mode)=0
void setFlags(Flags flags)
Note that unlike other accessors, this function sets specific flags (ORs them in); it does not assign...
std::shared_ptr< FaultBase > Fault
Abstract superclass for simulation objects.
bool hasPaddr() const
Accessor for paddr.
void setAttributes(bool lpae)
void setTestInterface(SimObject *ti)