51#include "debug/Checkpoint.hh"
52#include "debug/Drain.hh"
53#include "debug/PageTableWalker.hh"
54#include "debug/TLB.hh"
55#include "debug/TLBVerbose.hh"
61using namespace ArmISA;
65 requestorId(
p.sys->getRequestorId(this)),
66 port(new
Port(*this)),
67 isStage2(
p.is_stage2),
tlb(NULL),
68 currState(NULL), pending(false),
69 numSquashable(
p.num_squash_per_cycle),
75 doL2DescEvent([
this]{ doL2DescriptorWrapper(); },
name()),
76 doL0LongDescEvent([
this]{ doL0LongDescriptorWrapper(); },
name()),
77 doL1LongDescEvent([
this]{ doL1LongDescriptorWrapper(); },
name()),
78 doL2LongDescEvent([
this]{ doL2LongDescriptorWrapper(); },
name()),
79 doL3LongDescEvent([
this]{ doL3LongDescriptorWrapper(); },
name()),
80 LongDescEventByLevel { &doL0LongDescEvent, &doL1LongDescEvent,
81 &doL2LongDescEvent, &doL3LongDescEvent },
82 doProcessEvent([
this]{ processWalkWrapper(); },
name()),
89 ArmSystem *arm_sys =
dynamic_cast<ArmSystem *
>(
p.sys);
91 _physAddrRange = arm_sys->physAddrRange();
92 _haveLargeAsid64 = arm_sys->haveLargeAsid64();
94 _haveLargeAsid64 =
false;
114 if (if_name ==
"port") {
129 physAddrRange(0), req(nullptr),
130 asid(0), vmid(0), transState(nullptr),
131 vaddr(0), vaddr_tainted(0),
132 sctlr(0), scr(0), cpsr(0), tcr(0),
133 htcr(0), hcr(0), vtcr(0),
134 isWrite(false), isFetch(false),
isSecure(false),
135 isUncacheable(false), longDescData(
std::nullopt),
136 hpd(false),
sh(0), irgn(0), orgn(0), stage2Req(false),
137 stage2Tran(nullptr), timing(false), functional(false),
139 delayed(false), tableWalker(nullptr)
146 reqQueue(_walker, *this),
147 snoopRespQueue(_walker, *this)
162 state->delay = delay;
172 auto pkt = createPacket(req,
data, 0,
nullptr);
176 handleRespPacket(pkt);
184 auto pkt = createPacket(req,
data, delay,
nullptr);
186 Tick lat = sendAtomic(pkt);
188 handleRespPacket(pkt, lat);
197 auto pkt = createPacket(req,
data, delay,
event);
199 schedTimingReq(pkt,
curTick());
206 assert(pkt->
req->isUncacheable() ||
209 handleRespPacket(pkt);
249 DPRINTF(Drain,
"TableWalker done draining, processing drain event\n");
257 bool state_queues_not_empty =
false;
259 for (
int i = 0;
i < LookupLevel::Num_ArmLookupLevel; ++
i) {
261 state_queues_not_empty =
true;
267 DPRINTF(Drain,
"TableWalker not drained\n");
270 DPRINTF(Drain,
"TableWalker free, no need to drain\n");
288 bool disable_cacheability =
isStage2 ?
299 bool _stage2Req,
const TlbEntry *walk_entry)
301 assert(!(_functional && _timing));
310 DPRINTF(PageTableWalker,
"creating new instance of WalkerState\n");
314 }
else if (_functional) {
319 "creating functional instance of WalkerState\n");
323 }
else if (_timing) {
332 return std::make_shared<ReExec>();
399 assert(
release->
has(ArmExtension::VIRTUALIZATION));
409 panic(
"Invalid translation regime");
434 if (long_desc_format) {
461 }
else if (long_desc_format) {
523 if (
te &&
te->partial) {
529 }
else if (long_desc_format) {
556 unsigned num_squashed = 0;
560 (
te && !
te->partial))) {
565 DPRINTF(TLB,
"Squashing table walk for address %#x\n",
571 std::make_shared<UnimpFault>(
"Squashed Inst"),
612 const auto irgn0_mask = 0x1;
613 const auto irgn1_mask = 0x40;
619 const bool have_security =
release->
has(ArmExtension::SECURITY);
621 DPRINTF(
TLB,
"Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n",
633 return std::make_shared<PrefetchAbort>(
639 return std::make_shared<DataAbort>(
653 return std::make_shared<PrefetchAbort>(
659 return std::make_shared<DataAbort>(
672 DPRINTF(
TLB,
" - Descriptor at address %#x (%s)\n", l1desc_addr,
686 sizeof(uint32_t), flag, LookupLevel::L1,
696 Addr ttbr, ttbr0_max, ttbr1_min, desc_addr;
700 DPRINTF(
TLB,
"Beginning table walk for address %#x, TTBCR: %#x\n",
712 DPRINTF(
TLB,
" - Selecting VTTBR (long-desc.)\n");
716 LookupLevel::L1 : LookupLevel::L2;
719 DPRINTF(
TLB,
" - Selecting HTTBR (long-desc.)\n");
730 ttbr0_max = (1ULL << 32) -
733 ttbr0_max = (1ULL << 32) - 1;
735 ttbr1_min = (1ULL << 32) - (1ULL << (32 -
currState->
ttbcr.t1sz));
746 DPRINTF(
TLB,
" - Selecting TTBR0 (long-desc.)\n");
750 return std::make_shared<PrefetchAbort>(
756 return std::make_shared<DataAbort>(
768 if (ttbr0_max < (1ULL << 30))
769 start_lookup_level = LookupLevel::L2;
771 DPRINTF(
TLB,
" - Selecting TTBR1 (long-desc.)\n");
775 return std::make_shared<PrefetchAbort>(
781 return std::make_shared<DataAbort>(
794 if (ttbr1_min >= (1ULL << 31) + (1ULL << 30))
795 start_lookup_level = LookupLevel::L2;
799 return std::make_shared<PrefetchAbort>(
805 return std::make_shared<DataAbort>(
816 if (start_lookup_level == LookupLevel::L1) {
818 desc_addr =
mbits(ttbr, 39,
n) |
820 DPRINTF(
TLB,
" - Descriptor at address %#x (%s) (long-desc.)\n",
824 n = (tsz >= 2 ? 14 - tsz : 12);
825 desc_addr =
mbits(ttbr, 39,
n) |
827 DPRINTF(
TLB,
" - Descriptor at address %#x (%s) (long-desc.)\n",
841 sizeof(uint64_t), flag, start_lookup_level,
858 int in_max = (have_lva && tg ==
Grain64KB) ? 52 : 48;
859 int in_min = 64 - (tg ==
Grain64KB ? 47 : 48);
861 return tsz > in_max || tsz < in_min || (low_range ?
878 DPRINTF(
TLB,
"Beginning table walk for address %#llx, TCR: %#llx\n",
895 bool vaddr_fault =
false;
900 DPRINTF(
TLB,
" - Selecting VSTTBR_EL2 (AArch64 stage 2)\n");
903 DPRINTF(
TLB,
" - Selecting VTTBR_EL2 (AArch64 stage 2)\n");
916 DPRINTF(
TLB,
" - Selecting TTBR0_EL1 (AArch64)\n");
925 top_bit, tg, tsz,
true);
931 DPRINTF(
TLB,
" - Selecting TTBR1_EL1 (AArch64)\n");
940 top_bit, tg, tsz,
false);
956 DPRINTF(
TLB,
" - Selecting TTBR0_EL2 (AArch64)\n");
966 top_bit, tg, tsz,
true);
973 DPRINTF(
TLB,
" - Selecting TTBR1_EL2 (AArch64)\n");
982 top_bit, tg, tsz,
false);
997 DPRINTF(
TLB,
" - Selecting TTBR0_EL3 (AArch64)\n");
1006 top_bit, tg, tsz,
true);
1026 return std::make_shared<PrefetchAbort>(
1031 return std::make_shared<DataAbort>(
1041 warn_once(
"Reserved granule size requested; gem5's IMPLEMENTATION "
1042 "DEFINED behavior takes this to mean 4KB granules\n");
1054 auto [table_addr, desc_addr, start_lookup_level] =
walkAddresses(
1055 ttbr, tg, tsz, pa_range);
1060 DPRINTF(
TLB,
"Address size fault before any lookup\n");
1062 return std::make_shared<PrefetchAbort>(
1068 return std::make_shared<DataAbort>(
1092 sizeof(uint64_t), flag, start_lookup_level,
1099std::tuple<Addr, Addr, TableWalker::LookupLevel>
1104 LookupLevel first_level = LookupLevel::Num_ArmLookupLevel;
1105 Addr table_addr = 0;
1112 "Walk Cache hit: va=%#x, level=%d, table address=%#x\n",
1122 table_addr = entry->
pfn;
1128 ptops->firstLevel(64 - tsz);
1129 panic_if(first_level == LookupLevel::Num_ArmLookupLevel,
1130 "Table walker couldn't find lookup level\n");
1133 int base_addr_lo = 3 + tsz -
stride * (3 - first_level) - tg;
1135 if (pa_range == 52) {
1136 int z = (base_addr_lo < 6) ? 6 : base_addr_lo;
1137 table_addr =
mbits(ttbr, 47,
z);
1138 table_addr |= (
bits(ttbr, 5, 2) << 48);
1140 table_addr =
mbits(ttbr, 47, base_addr_lo);
1144 desc_addr = table_addr + ptops->index(
currState->
vaddr, first_level, tsz);
1146 return std::make_tuple(table_addr, desc_addr, first_level);
1151 uint8_t texcb,
bool s)
1155 DPRINTF(TLBVerbose,
"memAttrs texcb:%d s:%d\n", texcb,
s);
1156 te.shareable =
false;
1157 te.nonCacheable =
false;
1158 te.outerShareable =
false;
1162 te.nonCacheable =
true;
1164 te.shareable =
true;
1169 te.nonCacheable =
true;
1171 te.shareable =
true;
1179 te.outerAttrs =
bits(texcb, 1, 0);
1185 te.outerAttrs =
bits(texcb, 1, 0);
1188 te.nonCacheable =
true;
1192 te.outerAttrs =
bits(texcb, 1, 0);
1195 panic(
"Reserved texcb value!\n");
1198 panic(
"Implementation-defined texcb value!\n");
1207 te.nonCacheable =
true;
1209 te.shareable =
false;
1214 panic(
"Reserved texcb value!\n");
1219 if (
bits(texcb, 1,0) == 0 ||
bits(texcb, 3,2) == 0)
1220 te.nonCacheable =
true;
1221 te.innerAttrs =
bits(texcb, 1, 0);
1222 te.outerAttrs =
bits(texcb, 3, 2);
1225 panic(
"More than 32 states for 5 bits?\n");
1233 DPRINTF(TLBVerbose,
"memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
1234 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
1235 switch(
bits(texcb, 2,0)) {
1240 te.outerShareable = (prrr.nos0 == 0);
1246 te.outerShareable = (prrr.nos1 == 0);
1252 te.outerShareable = (prrr.nos2 == 0);
1258 te.outerShareable = (prrr.nos3 == 0);
1264 te.outerShareable = (prrr.nos4 == 0);
1270 te.outerShareable = (prrr.nos5 == 0);
1273 panic(
"Imp defined type\n");
1278 te.outerShareable = (prrr.nos7 == 0);
1284 DPRINTF(TLBVerbose,
"StronglyOrdered\n");
1286 te.nonCacheable =
true;
1289 te.shareable =
true;
1292 DPRINTF(TLBVerbose,
"Device ds1:%d ds0:%d s:%d\n",
1293 prrr.ds1, prrr.ds0,
s);
1295 te.nonCacheable =
true;
1299 te.shareable =
true;
1301 te.shareable =
true;
1304 DPRINTF(TLBVerbose,
"Normal ns1:%d ns0:%d s:%d\n",
1305 prrr.ns1, prrr.ns0,
s);
1308 te.shareable =
true;
1310 te.shareable =
true;
1313 panic(
"Reserved type");
1319 te.nonCacheable =
true;
1335 te.nonCacheable =
true;
1350 DPRINTF(TLBVerbose,
"memAttrs: shareable: %d, innerAttrs: %d, "
1352 te.shareable,
te.innerAttrs,
te.outerAttrs);
1353 te.setAttributes(
false);
1363 uint8_t
sh = l_descriptor.
sh();
1368 uint8_t attr_3_2 = (
attr >> 2) & 0x3;
1369 uint8_t attr_1_0 =
attr & 0x3;
1371 DPRINTF(TLBVerbose,
"memAttrsLPAE MemAttr:%#x sh:%#x\n",
attr,
sh);
1373 if (attr_3_2 == 0) {
1377 te.innerAttrs = attr_1_0 == 0 ? 1 : 3;
1378 te.nonCacheable =
true;
1381 te.outerAttrs = attr_3_2 == 1 ? 0 :
1382 attr_3_2 == 2 ? 2 : 1;
1383 te.innerAttrs = attr_1_0 == 1 ? 0 :
1384 attr_1_0 == 2 ? 6 : 5;
1385 te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1);
1388 uint8_t attrIndx = l_descriptor.
attrIndx();
1396 attr = (mair >> (8 * (attrIndx % 4))) & 0xff;
1397 uint8_t attr_7_4 =
bits(
attr, 7, 4);
1398 uint8_t attr_3_0 =
bits(
attr, 3, 0);
1399 DPRINTF(TLBVerbose,
"memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx,
sh,
attr);
1404 te.nonCacheable =
false;
1409 if (attr_3_0 == 0x0)
1411 else if (attr_3_0 == 0x4)
1414 panic(
"Unpredictable behavior\n");
1415 te.nonCacheable =
true;
1422 if (attr_3_0 == 0x4)
1424 te.nonCacheable =
true;
1425 else if (attr_3_0 < 0x8)
1426 panic(
"Unpredictable behavior\n");
1436 if (attr_7_4 & 0x4) {
1437 te.outerAttrs = (attr_7_4 & 1) ? 1 : 3;
1439 te.outerAttrs = 0x2;
1443 if (attr_3_0 != 0x4 && attr_3_0 < 0x8)
1444 panic(
"Unpredictable behavior\n");
1447 panic(
"Unpredictable behavior\n");
1453 te.innerAttrs = 0x1;
1456 te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0;
1468 te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7;
1471 panic(
"Unpredictable behavior\n");
1476 te.outerShareable =
sh == 2;
1477 te.shareable = (
sh & 0x2) ?
true :
false;
1478 te.setAttributes(
true);
1479 te.attributes |= (uint64_t)
attr << 56;
1489 uint8_t
sh = l_descriptor.
sh();
1493 uint8_t attr_hi = (
attr >> 2) & 0x3;
1494 uint8_t attr_lo =
attr & 0x3;
1496 DPRINTF(TLBVerbose,
"memAttrsAArch64 MemAttr:%#x sh:%#x\n",
attr,
sh);
1502 te.innerAttrs = attr_lo == 0 ? 1 : 3;
1503 te.nonCacheable =
true;
1506 te.outerAttrs = attr_hi == 1 ? 0 :
1507 attr_hi == 2 ? 2 : 1;
1508 te.innerAttrs = attr_lo == 1 ? 0 :
1509 attr_lo == 2 ? 6 : 5;
1512 te.nonCacheable = (attr_hi == 1) || (attr_hi == 2) ||
1513 (attr_lo == 1) || (attr_lo == 2);
1516 uint8_t attrIndx = l_descriptor.
attrIndx();
1518 DPRINTF(TLBVerbose,
"memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx,
sh);
1534 panic(
"Invalid exception level");
1539 attr =
bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
1547 te.nonCacheable =
false;
1549 te.nonCacheable =
true;
1557 te.nonCacheable =
true;
1562 warn_if(!attr_hi,
"Unpredictable behavior");
1568 te.nonCacheable =
true;
1571 te.shareable =
sh == 2;
1572 te.outerShareable = (
sh & 0x2) ?
true :
false;
1574 te.attributes = ((uint64_t)
attr << 56) |
1589 te.nonCacheable =
true;
1594 te.nonCacheable = (
te.outerAttrs == 0 ||
te.outerAttrs == 2) &&
1595 (
te.innerAttrs == 0 ||
te.innerAttrs == 2);
1609 DPRINTF(
TLB,
"L1 descriptor for %#x is %#x\n",
1622 DPRINTF(
TLB,
"L1 Descriptor Reserved/Ignore, causing fault\n");
1625 std::make_shared<PrefetchAbort>(
1632 std::make_shared<DataAbort>(
1655 panic(
"Haven't implemented supersections\n");
1664 DPRINTF(
TLB,
"L1 descriptor points to page table at: %#x (%s)\n",
1678 sizeof(uint32_t), flag, LookupLevel::L2,
1687 panic(
"A new type in a 2 bit field?\n");
1695 return std::make_shared<PrefetchAbort>(
1701 return std::make_shared<DataAbort>(
1721 DPRINTF(
TLB,
"L%d descriptor for %#llx is %#llx (%s)\n",
1728 DPRINTF(PageTableWalker,
"Analyzing L%d descriptor: %#llx, pxn: %d, "
1729 "xn: %d, ap: %d, af: %d, type: %d\n",
1738 DPRINTF(PageTableWalker,
"Analyzing L%d descriptor: %#llx, type: %d\n",
1748 DPRINTF(
TLB,
"L%d descriptor Invalid, causing fault type %d\n",
1767 DPRINTF(
TLB,
"L%d descriptor causing Address Size Fault\n",
1774 DPRINTF(
TLB,
"L%d descriptor causing Access Fault\n",
1808 DPRINTF(
TLB,
"L%d descriptor points to L%d descriptor at: %#x (%s)\n",
1817 DPRINTF(
TLB,
"L%d descriptor causing Address Size Fault\n",
1839 Event *
event = NULL;
1841 case LookupLevel::L1:
1843 case LookupLevel::L2:
1844 case LookupLevel::L3:
1848 panic(
"Wrong lookup level in table walk\n");
1854 sizeof(uint64_t), flag,
L,
event,
1861 panic(
"A new type in a 2 bit field?\n");
1875 DPRINTF(
TLB,
"L2 descriptor for %#x is %#x\n",
1882 DPRINTF(
TLB,
"L2 descriptor invalid, causing fault\n");
1907 DPRINTF(
TLB,
"Generating access fault at L2, afe: %d, ap: %d\n",
1933 DPRINTF(PageTableWalker,
"L1 Desc object host addr: %p\n",
1935 DPRINTF(PageTableWalker,
"L1 Desc object data: %08x\n",
1938 DPRINTF(PageTableWalker,
"calling doL1Descriptor for vaddr:%#x\n",
1961 DPRINTF(PageTableWalker,
"calling translateTiming again\n");
1994 DPRINTF(PageTableWalker,
"calling doL2Descriptor for vaddr:%#x\n",
2005 DPRINTF(PageTableWalker,
"calling translateTiming again\n");
2064 DPRINTF(PageTableWalker,
"calling doLongDescriptor for vaddr:%#x\n",
2084 DPRINTF(PageTableWalker,
"calling translateTiming again\n");
2101 if (curr_lookup_level >= LookupLevel::Num_ArmLookupLevel - 1)
2102 panic(
"Max. number of lookups already reached in table walk\n");
2128 "Fetching descriptor at address: 0x%x stage2Req: %d\n",
2143 fault = tran->fault;
2159 (this->*doDescriptor)();
2184 (this->*doDescriptor)();
2187 (this->*doDescriptor)();
2195 DPRINTF(PageTableWalker,
"Adding to walker fifo: "
2196 "queue size before adding: %d\n",
2205 const bool have_security =
release->
has(ArmExtension::SECURITY);
2210 te.longDescFormat =
true;
2220 te.size = (1ULL <<
te.N) - 1;
2226 te.type = TypeTLB::unified;
2239 DPRINTF(
TLB,
" - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
2241 DPRINTF(
TLB,
" - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
2242 "vmid:%d nc:%d ns:%d\n",
te.vpn,
te.xn,
te.pxn,
2243 te.ap,
static_cast<uint8_t
>(
te.domain),
te.asid,
te.
vmid,
2244 te.nonCacheable,
te.ns);
2245 DPRINTF(
TLB,
" - domain from L%d desc:%d data:%#x\n",
2256 const bool have_security =
release->
has(ArmExtension::SECURITY);
2261 te.longDescFormat = long_descriptor;
2266 te.size = (1<<
te.N) - 1;
2267 te.pfn = descriptor.
pfn();
2272 te.xn = descriptor.
xn();
2274 TypeTLB::instruction : TypeTLB::data;
2284 if (long_descriptor) {
2294 te.hap = l_descriptor.
ap();
2297 descriptor.
ap() >> 1) << 1) |
2305 te.ap = descriptor.
ap();
2312 DPRINTF(
TLB,
" - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
2314 DPRINTF(
TLB,
" - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
2315 "vmid:%d nc:%d ns:%d\n",
te.vpn,
te.xn,
te.pxn,
2316 te.ap,
static_cast<uint8_t
>(
te.domain),
te.asid,
te.
vmid,
2317 te.nonCacheable,
te.ns);
2318 DPRINTF(
TLB,
" - domain from L%d desc:%d data:%#x\n",
2333 switch (lookup_level_as_int) {
2334 case LookupLevel::L1:
2335 return LookupLevel::L1;
2336 case LookupLevel::L2:
2337 return LookupLevel::L2;
2338 case LookupLevel::L3:
2339 return LookupLevel::L3;
2341 panic(
"Invalid lookup level conversion");
2398 panic(
"unknown page size");
2411 auto req = std::make_shared<Request>();
2465 :
data(_data), numBytes(0),
event(_event), parent(_parent),
2468 req = std::make_shared<Request>();
2487 parent.getTableWalkerPort().sendTimingReq(req,
data,
2499 parent.mmu->translateTiming(req, tc,
this,
mode, tranType,
true);
2503 : statistics::
Group(parent),
2504 ADD_STAT(walks, statistics::units::Count::get(),
2505 "Table walker walks requested"),
2506 ADD_STAT(walksShortDescriptor, statistics::units::Count::get(),
2507 "Table walker walks initiated with short descriptors"),
2508 ADD_STAT(walksLongDescriptor, statistics::units::Count::get(),
2509 "Table walker walks initiated with long descriptors"),
2510 ADD_STAT(walksShortTerminatedAtLevel, statistics::units::Count::get(),
2511 "Level at which table walker walks with short descriptors "
2513 ADD_STAT(walksLongTerminatedAtLevel, statistics::units::Count::get(),
2514 "Level at which table walker walks with long descriptors "
2516 ADD_STAT(squashedBefore, statistics::units::Count::get(),
2517 "Table walks squashed before starting"),
2518 ADD_STAT(squashedAfter, statistics::units::Count::get(),
2519 "Table walks squashed after completion"),
2521 "Table walker wait (enqueue to first request) latency"),
2522 ADD_STAT(walkServiceTime, statistics::units::
Tick::get(),
2523 "Table walker service (enqueue to completion) latency"),
2525 "Table walker pending requests distribution"),
2526 ADD_STAT(pageSizes, statistics::units::Count::get(),
2527 "Table walker page sizes translated"),
2528 ADD_STAT(requestOrigin, statistics::units::Count::get(),
2529 "Table walker requests started/completed, data/inst")
FaultSource
Generic fault source enums used to index into {short/long/aarch64}DescFaultSources[] to get the actua...
virtual void annotate(AnnotationIDs id, uint64_t val)
static bool hasUnprivRegime(TranslationRegime regime)
static ExceptionLevel tranTypeEL(CPSR cpsr, SCR scr, ArmTranslationType type)
Determine the EL to use for the purpose of a translation given a specific translation type.
void translateTiming(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode) override
TlbEntry * lookup(Addr vpn, uint16_t asn, vmid_t vmid, bool secure, bool functional, bool ignore_asn, TranslationRegime target_regime, bool stage2, BaseMMU::Mode mode)
Lookup an entry in the TLB.
bool hasWalkCache() const
Fault translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode) override
TranslationGenPtr translateFunctional(Addr start, Addr size, ThreadContext *tc, Mode mode, Request::Flags flags) override
Returns a translation generator for a region of virtual addresses, instead of directly translating a ...
const ArmRelease * release() const
void multiInsert(TlbEntry &pte)
Insert a PTE in the current TLB and in the higher levels.
virtual bool global(WalkerState *currState) const =0
virtual bool xn() const =0
virtual uint8_t * getRawPtr()=0
virtual uint64_t getRawData() const =0
virtual uint8_t texcb() const
virtual std::string dbgHeader() const =0
virtual uint8_t ap() const =0
virtual bool shareable() const
virtual uint8_t offsetBits() const =0
virtual Addr pfn() const =0
LookupLevel lookupLevel
Current lookup level for this descriptor.
virtual TlbEntry::DomainType domain() const =0
virtual bool secure(bool have_security, WalkerState *currState) const =0
uint32_t data
The raw bits of the entry.
bool supersection() const
Is the page a Supersection (16 MiB)?
Addr l2Addr() const
Address of L2 descriptor if it exists.
uint8_t ap() const override
Three bit access protection flags.
TlbEntry::DomainType domain() const override
Domain Client/Manager: ARM DDI 0406B: B3-31.
uint8_t ap() const override
Three bit access protection flags.
uint32_t data
The raw bits of the entry.
bool invalid() const
Is the entry invalid.
Long-descriptor format (LPAE)
uint8_t sh() const
2-bit shareability field
uint8_t memAttr() const
Memory attributes, only used by stage 2 translations.
uint8_t rwTable() const
R/W protection flag for subsequent levels of lookup.
uint8_t offsetBits() const override
Return the bit width of the page/block offset.
bool pxn() const
Is privileged execution allowed on this mapping? (LPAE only)
bool af() const
Returns true if the access flag (AF) is set.
bool pxnTable() const
Is privileged execution allowed on subsequent lookup levels?
bool aarch64
True if the current lookup is performed in AArch64 state.
EntryType type() const
Return the descriptor type.
bool xn() const override
Is execution allowed on this mapping?
bool secure(bool have_security, WalkerState *currState) const override
Returns true if this entry targets the secure physical address map.
std::string dbgHeader() const override
Addr nextTableAddr() const
Return the address of the next page table.
GrainSize grainSize
Width of the granule size in bits.
uint8_t attrIndx() const
Attribute index.
uint8_t ap() const override
2-bit access protection flags
uint64_t data
The raw bits of the entry.
Addr nextDescAddr(Addr va) const
Return the address of the next descriptor.
Addr paddr() const
Return the physical address of the entry.
uint8_t userTable() const
User/privileged mode protection flag for subsequent levels of lookup.
bool secureTable() const
Whether the subsequent levels of lookup are secure.
TlbEntry::DomainType domain() const override
uint64_t getRawData() const override
bool xnTable() const
Is execution allowed on subsequent lookup levels?
Port(TableWalker &_walker)
void sendAtomicReq(const RequestPtr &req, uint8_t *data, Tick delay)
void handleResp(TableWalkerState *state, Addr addr, Addr size, Tick delay=0)
void sendFunctionalReq(const RequestPtr &req, uint8_t *data)
void handleRespPacket(PacketPtr pkt, Tick delay=0)
void sendTimingReq(const RequestPtr &req, uint8_t *data, Tick delay, Event *event)
PacketPtr createPacket(const RequestPtr &req, uint8_t *data, Tick delay, Event *event)
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
This translation class is used to trigger the data fetch once a timing translation returns the transl...
void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode)
void setVirt(Addr vaddr, int size, Request::Flags flags, int requestorId)
Stage2Walk(TableWalker &_parent, uint8_t *_data, Event *_event, Addr vaddr, BaseMMU::Mode mode, MMU::ArmTranslationType tran_type)
void translateTiming(ThreadContext *tc)
bool isWrite
If the access is a write.
Addr vaddr_tainted
The virtual address that is being translated.
RequestPtr req
Request that is currently being serviced.
VTCR_t vtcr
Cached copy of the vtcr as it existed when translation began.
HCR hcr
Cached copy of the htcr as it existed when translation began.
Addr vaddr
The virtual address that is being translated with tagging removed.
bool functional
If the atomic mode should be functional.
bool secureLookup
Whether lookups should be treated as using the secure state.
bool isUncacheable
True if table walks are uncacheable (for table descriptors)
ThreadContext * tc
Thread context that we're doing the walk for.
bool hpd
Hierarchical access permission disable.
BaseMMU::Translation * transState
Translation state for delayed requests.
std::optional< LongDescData > longDescData
bool isSecure
If the access comes from the secure state.
BaseMMU::Mode mode
Save mode for use in delayed response.
HTCR htcr
Cached copy of the htcr as it existed when translation began.
ExceptionLevel el
Current exception level.
MMU::ArmTranslationType tranType
The translation type that has been requested.
SCTLR sctlr
Cached copy of the sctlr as it existed when translation began.
TableWalker * tableWalker
Fault fault
The fault that we are going to return.
Tick startTime
Timestamp for calculating elapsed time in service (for stats)
bool isFetch
If the access is a fetch (for execution, and no-exec) must be checked?
bool stage2Req
Flag indicating if a second stage of lookup is required.
TlbEntry walkEntry
Initial walk entry allowing to skip lookup levels.
TranslationRegime regime
Current translation regime.
bool timing
If the mode is timing or atomic.
LongDescriptor longDesc
Long-format descriptor (LPAE and AArch64)
int physAddrRange
Current physical address range in bits.
bool delayed
Whether the response is delayed in timing mode due to additional lookups.
uint16_t asid
ASID that we're servicing the request under.
L1Descriptor l1Desc
Short-format descriptors.
bool aarch64
If the access is performed in AArch64 state.
BaseMMU::Translation * stage2Tran
A pointer to the stage 2 translation that's in progress.
Fault walk(const RequestPtr &req, ThreadContext *tc, uint16_t asid, vmid_t _vmid, BaseMMU::Mode mode, BaseMMU::Translation *_trans, bool timing, bool functional, bool secure, MMU::ArmTranslationType tran_type, bool stage2, const TlbEntry *walk_entry)
void doL2DescriptorWrapper()
static LookupLevel toLookupLevel(uint8_t lookup_level_as_int)
enums::ArmLookupLevel LookupLevel
void doL2LongDescriptorWrapper()
void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, uint8_t texcb, bool s)
void doL3LongDescriptorWrapper()
const ArmRelease * release
Cached copies of system-level properties.
EventFunctionWrapper doL1DescEvent
EventFunctionWrapper doProcessEvent
static const unsigned REQUESTED
static const unsigned COMPLETED
bool uncacheableWalk() const
Returns true if the table walk should be uncacheable.
Event * LongDescEventByLevel[4]
void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, LongDescriptor &lDescriptor)
void insertPartialTableEntry(LongDescriptor &descriptor)
void doL1LongDescriptorWrapper()
void fetchDescriptor(Addr desc_addr, DescriptorBase &descriptor, int num_bytes, Request::Flags flags, LookupLevel lookup_lvl, Event *event, void(TableWalker::*doDescriptor)())
void drainResume() override
Resume execution after a successful drain.
void doLongDescriptorWrapper(LookupLevel curr_lookup_level)
void doL0LongDescriptorWrapper()
bool pending
If a timing translation is currently in progress.
Port * port
Port shared by the two table walkers.
Fault testWalk(const RequestPtr &walk_req, TlbEntry::DomainType domain, LookupLevel lookup_level)
Fault generateLongDescFault(ArmFault::FaultSource src)
std::tuple< Addr, Addr, LookupLevel > walkAddresses(Addr ttbr, GrainSize tg, int tsz, int pa_range)
Returns a tuple made of: 1) The address of the first page table 2) The address of the first descripto...
Fault readDataUntimed(ThreadContext *tc, Addr vaddr, Addr desc_addr, uint8_t *data, int num_bytes, Request::Flags flags, BaseMMU::Mode mode, MMU::ArmTranslationType tran_type, bool functional)
TableWalker(const Params &p)
void doL1DescriptorWrapper()
void nextWalk(ThreadContext *tc)
void readDataTimed(ThreadContext *tc, Addr desc_addr, Stage2Walk *translation, int num_bytes, Request::Flags flags)
EventFunctionWrapper doL2DescEvent
bool checkVAddrSizeFaultAArch64(Addr addr, int top_bit, GrainSize granule, int tsz, bool low_range)
gem5::Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
std::list< WalkerState * > pendingQueue
Queue of requests that have passed are waiting because the walker is currently busy.
MMU * mmu
The MMU to forward second stage look upts to.
RequestorID requestorId
Requestor id assigned by the MMU.
gem5::ArmISA::TableWalker::TableWalkerStats stats
Port & getTableWalkerPort()
Fault processWalkAArch64()
const bool isStage2
Indicates whether this table walker is part of the stage 2 mmu.
bool checkAddrSizeFaultAArch64(Addr addr, int pa_range)
Returns true if the address exceeds the range permitted by the system-wide setting or by the TCR_ELx ...
void mpamTagTableWalk(RequestPtr &req) const
static uint8_t pageSizeNtoStatBin(uint8_t N)
void completeDrain()
Checks if all state is cleared and if so, completes drain.
void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
DrainState drain() override
Provide a default implementation of the drain interface for objects that don't need draining.
std::list< WalkerState * > stateQueues[LookupLevel::Num_ArmLookupLevel]
Queues of requests for all the different lookup levels.
unsigned numSquashable
The number of walks belonging to squashed instructions that can be removed from the pendingQueue per ...
TLB * tlb
TLB that is initiating these table walks.
void memAttrsLPAE(ThreadContext *tc, TlbEntry &te, LongDescriptor &lDescriptor)
void setTestInterface(TlbTestInterface *ti)
void memAttrsWalkAArch64(TlbEntry &te)
SCTLR sctlr
Cached copy of the sctlr as it existed when translation began.
void processWalkWrapper()
void stashCurrState(int queue_idx)
Timing mode: saves the currState into the stateQueues.
bool has(ArmExtension ext) const
virtual bool squashed() const
This function is used by the page table walker to determine if it should translate the a pending requ...
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode)=0
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
ClockedObjectParams Params
Parameters of ClockedObject.
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Cycles is a wrapper class for representing cycle counts, i.e.
virtual std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
SenderState * senderState
This packet's sender state.
RequestPtr req
A pointer to the original request.
bool cacheResponding() const
Ports are used to interface objects to each other.
The QueuedRequestPort combines two queues, a request queue and a snoop response queue,...
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
@ PT_WALK
The request is a page table walk.
@ SECURE
The request targets the secure memory space.
@ UNCACHEABLE
The request is to an uncacheable address.
@ NO_ACCESS
The request should not cause a memory access.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
virtual BaseCPU * getCpuPtr()=0
Derived & ysubname(off_type index, const std::string &subname)
Derived & subname(off_type index, const std::string &name)
Set the subfield name for the given index, and marks this stat to print at the end of simulation.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Histogram & init(size_type size)
Set the parameters of this histogram.
Derived & init(size_type _x, size_type _y)
Derived & init(size_type size)
Set this vector to have the given size.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
void signalDrainDone() const
Signal that an object is drained.
DrainState drainState() const
Return the current drain state of an object.
DrainState
Object drain/handover states.
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void schedule(Event &event, Tick when)
void set(Type mask)
Set all flag's bits matching the given mask.
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
const Params & params() const
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
void tagRequest(ThreadContext *tc, const RequestPtr &req, bool ind)
Tag a memory request with MPAM information.
ByteOrder byteOrder(const ThreadContext *tc)
const PageTableOps * getPageTableOps(GrainSize trans_granule)
bool isSecure(ThreadContext *tc)
bool longDescFormatInUse(ThreadContext *tc)
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
const GrainSize GrainMap_tg1[]
TranslationRegime translationRegime(ThreadContext *tc, ExceptionLevel el)
ExceptionLevel translationEl(TranslationRegime regime)
int computeAddrTop(ThreadContext *tc, bool selbit, bool is_instr, TCR tcr, ExceptionLevel el)
Bitfield< 21, 20 > stride
int decodePhysAddrRange64(uint8_t pa_enc)
Returns the n.
const GrainSize GrainMap_tg0[]
int snsBankedIndex(MiscRegIndex reg, ThreadContext *tc)
bool HaveExt(ThreadContext *tc, ArmExtension ext)
Returns true if the provided ThreadContext supports the ArmExtension passed as a second argument.
Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el, TCR tcr, bool is_instr)
Removes the tag from tagged addresses if that mode is enabled.
const FlagsType pdf
Print the percent of the total that this entry represents.
const FlagsType nonan
Don't print if this is NAN.
const FlagsType nozero
Don't print if this is zero.
const FlagsType total
Print the total.
const FlagsType dist
Print the distribution.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
std::shared_ptr< FaultBase > Fault
std::shared_ptr< Request > RequestPtr
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
uint64_t Tick
Tick count type.
T htog(T value, ByteOrder guest_byte_order)
constexpr decltype(nullptr) NoFault
Overload hash function for BasicBlockRange type.
statistics::Scalar squashedBefore
statistics::Vector2d requestOrigin
TableWalkerStats(statistics::Group *parent)
statistics::Scalar walksLongDescriptor
statistics::Scalar walksShortDescriptor
statistics::Histogram walkWaitTime
statistics::Vector walksShortTerminatedAtLevel
statistics::Vector pageSizes
statistics::Vector walksLongTerminatedAtLevel
statistics::Histogram walkServiceTime
statistics::Histogram pendingWalks
statistics::Scalar squashedAfter
Helper variables used to implement hierarchical access permissions when the long-desc.
const std::string & name()