50#include "debug/Checkpoint.hh"
51#include "debug/Drain.hh"
52#include "debug/PageTableWalker.hh"
53#include "debug/TLB.hh"
54#include "debug/TLBVerbose.hh"
60using namespace ArmISA;
64 requestorId(
p.sys->getRequestorId(this)),
65 port(new
Port(*this, requestorId)),
66 isStage2(
p.is_stage2),
tlb(NULL),
67 currState(NULL), pending(false),
68 numSquashable(
p.num_squash_per_cycle),
74 doL2DescEvent([
this]{ doL2DescriptorWrapper(); },
name()),
75 doL0LongDescEvent([
this]{ doL0LongDescriptorWrapper(); },
name()),
76 doL1LongDescEvent([
this]{ doL1LongDescriptorWrapper(); },
name()),
77 doL2LongDescEvent([
this]{ doL2LongDescriptorWrapper(); },
name()),
78 doL3LongDescEvent([
this]{ doL3LongDescriptorWrapper(); },
name()),
79 LongDescEventByLevel { &doL0LongDescEvent, &doL1LongDescEvent,
80 &doL2LongDescEvent, &doL3LongDescEvent },
81 doProcessEvent([
this]{ processWalkWrapper(); },
name())
87 ArmSystem *arm_sys =
dynamic_cast<ArmSystem *
>(
p.sys);
89 _physAddrRange = arm_sys->physAddrRange();
90 _haveLargeAsid64 = arm_sys->haveLargeAsid64();
92 _haveLargeAsid64 =
false;
112 if (if_name ==
"port") {
126 tc(nullptr),
aarch64(false),
el(
EL0), physAddrRange(0), req(nullptr),
127 asid(0), vmid(0), isHyp(false), transState(nullptr),
128 vaddr(0), vaddr_tainted(0),
129 sctlr(0), scr(0), cpsr(0), tcr(0),
130 htcr(0), hcr(0), vtcr(0),
131 isWrite(false), isFetch(false),
isSecure(false),
132 isUncacheable(false),
133 secureLookup(false), rwTable(false), userTable(false), xnTable(false),
134 pxnTable(false),
hpd(false), stage2Req(false),
135 stage2Tran(nullptr), timing(false), functional(false),
137 delayed(false), tableWalker(nullptr)
144 reqQueue(_walker, *this),
145 snoopRespQueue(_walker, *this),
152 Addr desc_addr,
int size,
165 state->delay = delay;
173 Addr desc_addr,
int size,
176 auto pkt = createPacket(desc_addr, size,
data,
flags, 0,
nullptr);
180 handleRespPacket(pkt);
185 Addr desc_addr,
int size,
188 auto pkt = createPacket(desc_addr, size,
data,
flags, delay,
nullptr);
190 Tick lat = sendAtomic(pkt);
192 handleRespPacket(pkt, lat);
197 Addr desc_addr,
int size,
201 auto pkt = createPacket(desc_addr, size,
data,
flags, delay,
event);
203 schedTimingReq(pkt,
curTick());
210 assert(pkt->
req->isUncacheable() ||
213 handleRespPacket(pkt);
253 DPRINTF(Drain,
"TableWalker done draining, processing drain event\n");
261 bool state_queues_not_empty =
false;
263 for (
int i = 0;
i < LookupLevel::Num_ArmLookupLevel; ++
i) {
265 state_queues_not_empty =
true;
271 DPRINTF(Drain,
"TableWalker not drained\n");
274 DPRINTF(Drain,
"TableWalker free, no need to drain\n");
294 bool _stage2Req,
const TlbEntry *walk_entry)
296 assert(!(_functional && _timing));
305 DPRINTF(PageTableWalker,
"creating new instance of WalkerState\n");
309 }
else if (_functional) {
314 "creating functional instance of WalkerState\n");
318 }
else if (_timing) {
327 return std::make_shared<ReExec>();
401 assert(
release->
has(ArmExtension::VIRTUALIZATION));
411 panic(
"Invalid exception level");
435 if (long_desc_format) {
452 else if (long_desc_format)
475 else if (long_desc_format)
509 if (
te &&
te->partial) {
524 curr_state_copy->
tc, curr_state_copy->
mode);
526 delete curr_state_copy;
534 unsigned num_squashed = 0;
538 (
te && !
te->partial))) {
543 DPRINTF(
TLB,
"Squashing table walk for address %#x\n",
549 std::make_shared<UnimpFault>(
"Squashed Inst"),
590 const auto irgn0_mask = 0x1;
591 const auto irgn1_mask = 0x40;
597 const bool have_security =
release->
has(ArmExtension::SECURITY);
599 DPRINTF(
TLB,
"Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n",
611 return std::make_shared<PrefetchAbort>(
617 return std::make_shared<DataAbort>(
631 return std::make_shared<PrefetchAbort>(
637 return std::make_shared<DataAbort>(
650 DPRINTF(
TLB,
" - Descriptor at address %#x (%s)\n", l1desc_addr,
655 f =
testWalk(l1desc_addr,
sizeof(uint32_t),
681 sizeof(uint32_t), flag, LookupLevel::L1,
694 Addr ttbr, ttbr0_max, ttbr1_min, desc_addr;
698 DPRINTF(
TLB,
"Beginning table walk for address %#x, TTBCR: %#x\n",
710 DPRINTF(
TLB,
" - Selecting VTTBR (long-desc.)\n");
714 LookupLevel::L1 : LookupLevel::L2;
717 DPRINTF(
TLB,
" - Selecting HTTBR (long-desc.)\n");
728 ttbr0_max = (1ULL << 32) -
731 ttbr0_max = (1ULL << 32) - 1;
733 ttbr1_min = (1ULL << 32) - (1ULL << (32 -
currState->
ttbcr.t1sz));
744 DPRINTF(
TLB,
" - Selecting TTBR0 (long-desc.)\n");
748 return std::make_shared<PrefetchAbort>(
754 return std::make_shared<DataAbort>(
766 if (ttbr0_max < (1ULL << 30))
767 start_lookup_level = LookupLevel::L2;
769 DPRINTF(
TLB,
" - Selecting TTBR1 (long-desc.)\n");
773 return std::make_shared<PrefetchAbort>(
779 return std::make_shared<DataAbort>(
792 if (ttbr1_min >= (1ULL << 31) + (1ULL << 30))
793 start_lookup_level = LookupLevel::L2;
797 return std::make_shared<PrefetchAbort>(
803 return std::make_shared<DataAbort>(
814 if (start_lookup_level == LookupLevel::L1) {
816 desc_addr =
mbits(ttbr, 39,
n) |
818 DPRINTF(
TLB,
" - Descriptor at address %#x (%s) (long-desc.)\n",
822 n = (tsz >= 2 ? 14 - tsz : 12);
823 desc_addr =
mbits(ttbr, 39,
n) |
825 DPRINTF(
TLB,
" - Descriptor at address %#x (%s) (long-desc.)\n",
855 sizeof(uint64_t), flag, start_lookup_level,
875 int in_max = (have_lva && tg ==
Grain64KB) ? 52 : 48;
876 int in_min = 64 - (tg ==
Grain64KB ? 47 : 48);
878 return tsz > in_max || tsz < in_min || (low_range ?
895 DPRINTF(
TLB,
"Beginning table walk for address %#llx, TCR: %#llx\n",
912 bool vaddr_fault =
false;
929 DPRINTF(
TLB,
" - Selecting TTBR0 (AArch64)\n");
936 top_bit, tg, tsz,
true);
942 DPRINTF(
TLB,
" - Selecting TTBR1 (AArch64)\n");
949 top_bit, tg, tsz,
false);
964 DPRINTF(
TLB,
" - Selecting VSTTBR_EL2 (AArch64 stage 2)\n");
967 DPRINTF(
TLB,
" - Selecting VTTBR_EL2 (AArch64 stage 2)\n");
978 DPRINTF(
TLB,
" - Selecting TTBR0_EL1 (AArch64)\n");
985 top_bit, tg, tsz,
true);
991 DPRINTF(
TLB,
" - Selecting TTBR1_EL1 (AArch64)\n");
998 top_bit, tg, tsz,
false);
1013 DPRINTF(
TLB,
" - Selecting TTBR0_EL2 (AArch64)\n");
1021 top_bit, tg, tsz,
true);
1028 DPRINTF(
TLB,
" - Selecting TTBR1_EL2 (AArch64)\n");
1035 top_bit, tg, tsz,
false);
1050 DPRINTF(
TLB,
" - Selecting TTBR0_EL3 (AArch64)\n");
1057 top_bit, tg, tsz,
true);
1075 f = std::make_shared<PrefetchAbort>(
1080 f = std::make_shared<DataAbort>(
1100 warn_once(
"Reserved granule size requested; gem5's IMPLEMENTATION "
1101 "DEFINED behavior takes this to mean 4KB granules\n");
1113 auto [table_addr, desc_addr, start_lookup_level] =
walkAddresses(
1114 ttbr, tg, tsz, pa_range);
1119 DPRINTF(
TLB,
"Address size fault before any lookup\n");
1122 f = std::make_shared<PrefetchAbort>(
1128 f = std::make_shared<DataAbort>(
1181 sizeof(uint64_t), flag, start_lookup_level,
1185 sizeof(uint64_t), flag, -1, NULL,
1193std::tuple<Addr, Addr, TableWalker::LookupLevel>
1198 LookupLevel first_level = LookupLevel::Num_ArmLookupLevel;
1199 Addr table_addr = 0;
1206 "Walk Cache hit: va=%#x, level=%d, table address=%#x\n",
1214 table_addr = entry->
pfn;
1220 ptops->firstLevel(64 - tsz);
1221 panic_if(first_level == LookupLevel::Num_ArmLookupLevel,
1222 "Table walker couldn't find lookup level\n");
1225 int base_addr_lo = 3 + tsz -
stride * (3 - first_level) - tg;
1227 if (pa_range == 52) {
1228 int z = (base_addr_lo < 6) ? 6 : base_addr_lo;
1229 table_addr =
mbits(ttbr, 47,
z);
1230 table_addr |= (
bits(ttbr, 5, 2) << 48);
1232 table_addr =
mbits(ttbr, 47, base_addr_lo);
1236 desc_addr = table_addr + ptops->index(
currState->
vaddr, first_level, tsz);
1238 return std::make_tuple(table_addr, desc_addr, first_level);
1243 uint8_t texcb,
bool s)
1247 DPRINTF(TLBVerbose,
"memAttrs texcb:%d s:%d\n", texcb,
s);
1248 te.shareable =
false;
1249 te.nonCacheable =
false;
1250 te.outerShareable =
false;
1254 te.nonCacheable =
true;
1256 te.shareable =
true;
1261 te.nonCacheable =
true;
1263 te.shareable =
true;
1271 te.outerAttrs =
bits(texcb, 1, 0);
1277 te.outerAttrs =
bits(texcb, 1, 0);
1280 te.nonCacheable =
true;
1284 te.outerAttrs =
bits(texcb, 1, 0);
1287 panic(
"Reserved texcb value!\n");
1290 panic(
"Implementation-defined texcb value!\n");
1299 te.nonCacheable =
true;
1301 te.shareable =
false;
1306 panic(
"Reserved texcb value!\n");
1311 if (
bits(texcb, 1,0) == 0 ||
bits(texcb, 3,2) == 0)
1312 te.nonCacheable =
true;
1313 te.innerAttrs =
bits(texcb, 1, 0);
1314 te.outerAttrs =
bits(texcb, 3, 2);
1317 panic(
"More than 32 states for 5 bits?\n");
1325 DPRINTF(TLBVerbose,
"memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
1326 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
1327 switch(
bits(texcb, 2,0)) {
1332 te.outerShareable = (prrr.nos0 == 0);
1338 te.outerShareable = (prrr.nos1 == 0);
1344 te.outerShareable = (prrr.nos2 == 0);
1350 te.outerShareable = (prrr.nos3 == 0);
1356 te.outerShareable = (prrr.nos4 == 0);
1362 te.outerShareable = (prrr.nos5 == 0);
1365 panic(
"Imp defined type\n");
1370 te.outerShareable = (prrr.nos7 == 0);
1376 DPRINTF(TLBVerbose,
"StronglyOrdered\n");
1378 te.nonCacheable =
true;
1381 te.shareable =
true;
1384 DPRINTF(TLBVerbose,
"Device ds1:%d ds0:%d s:%d\n",
1385 prrr.ds1, prrr.ds0,
s);
1387 te.nonCacheable =
true;
1391 te.shareable =
true;
1393 te.shareable =
true;
1396 DPRINTF(TLBVerbose,
"Normal ns1:%d ns0:%d s:%d\n",
1397 prrr.ns1, prrr.ns0,
s);
1400 te.shareable =
true;
1402 te.shareable =
true;
1405 panic(
"Reserved type");
1411 te.nonCacheable =
true;
1427 te.nonCacheable =
true;
1442 DPRINTF(TLBVerbose,
"memAttrs: shareable: %d, innerAttrs: %d, "
1444 te.shareable,
te.innerAttrs,
te.outerAttrs);
1445 te.setAttributes(
false);
1455 uint8_t
sh = l_descriptor.
sh();
1460 uint8_t attr_3_2 = (
attr >> 2) & 0x3;
1461 uint8_t attr_1_0 =
attr & 0x3;
1463 DPRINTF(TLBVerbose,
"memAttrsLPAE MemAttr:%#x sh:%#x\n",
attr,
sh);
1465 if (attr_3_2 == 0) {
1469 te.innerAttrs = attr_1_0 == 0 ? 1 : 3;
1470 te.nonCacheable =
true;
1473 te.outerAttrs = attr_3_2 == 1 ? 0 :
1474 attr_3_2 == 2 ? 2 : 1;
1475 te.innerAttrs = attr_1_0 == 1 ? 0 :
1476 attr_1_0 == 2 ? 6 : 5;
1477 te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1);
1480 uint8_t attrIndx = l_descriptor.
attrIndx();
1488 attr = (mair >> (8 * (attrIndx % 4))) & 0xff;
1489 uint8_t attr_7_4 =
bits(
attr, 7, 4);
1490 uint8_t attr_3_0 =
bits(
attr, 3, 0);
1491 DPRINTF(TLBVerbose,
"memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx,
sh,
attr);
1496 te.nonCacheable =
false;
1501 if (attr_3_0 == 0x0)
1503 else if (attr_3_0 == 0x4)
1506 panic(
"Unpredictable behavior\n");
1507 te.nonCacheable =
true;
1514 if (attr_3_0 == 0x4)
1516 te.nonCacheable =
true;
1517 else if (attr_3_0 < 0x8)
1518 panic(
"Unpredictable behavior\n");
1528 if (attr_7_4 & 0x4) {
1529 te.outerAttrs = (attr_7_4 & 1) ? 1 : 3;
1531 te.outerAttrs = 0x2;
1535 if (attr_3_0 != 0x4 && attr_3_0 < 0x8)
1536 panic(
"Unpredictable behavior\n");
1539 panic(
"Unpredictable behavior\n");
1545 te.innerAttrs = 0x1;
1548 te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0;
1560 te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7;
1563 panic(
"Unpredictable behavior\n");
1568 te.outerShareable =
sh == 2;
1569 te.shareable = (
sh & 0x2) ?
true :
false;
1570 te.setAttributes(
true);
1571 te.attributes |= (uint64_t)
attr << 56;
1581 uint8_t
sh = l_descriptor.
sh();
1585 uint8_t attr_hi = (
attr >> 2) & 0x3;
1586 uint8_t attr_lo =
attr & 0x3;
1588 DPRINTF(TLBVerbose,
"memAttrsAArch64 MemAttr:%#x sh:%#x\n",
attr,
sh);
1594 te.innerAttrs = attr_lo == 0 ? 1 : 3;
1595 te.nonCacheable =
true;
1598 te.outerAttrs = attr_hi == 1 ? 0 :
1599 attr_hi == 2 ? 2 : 1;
1600 te.innerAttrs = attr_lo == 1 ? 0 :
1601 attr_lo == 2 ? 6 : 5;
1604 te.nonCacheable = (attr_hi == 1) || (attr_hi == 2) ||
1605 (attr_lo == 1) || (attr_lo == 2);
1608 uint8_t attrIndx = l_descriptor.
attrIndx();
1610 DPRINTF(TLBVerbose,
"memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx,
sh);
1627 panic(
"Invalid exception level");
1632 attr =
bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
1640 te.nonCacheable =
false;
1642 te.nonCacheable =
true;
1650 te.nonCacheable =
true;
1655 warn_if(!attr_hi,
"Unpredictable behavior");
1661 te.nonCacheable =
true;
1664 te.shareable =
sh == 2;
1665 te.outerShareable = (
sh & 0x2) ?
true :
false;
1667 te.attributes = ((uint64_t)
attr << 56) |
1684 DPRINTF(
TLB,
"L1 descriptor for %#x is %#x\n",
1697 DPRINTF(
TLB,
"L1 Descriptor Reserved/Ignore, causing fault\n");
1700 std::make_shared<PrefetchAbort>(
1707 std::make_shared<DataAbort>(
1730 panic(
"Haven't implemented supersections\n");
1739 DPRINTF(
TLB,
"L1 descriptor points to page table at: %#x (%s)\n",
1776 panic(
"A new type in a 2 bit field?\n");
1784 return std::make_shared<PrefetchAbort>(
1790 return std::make_shared<DataAbort>(
1810 DPRINTF(
TLB,
"L%d descriptor for %#llx is %#llx (%s)\n",
1817 DPRINTF(PageTableWalker,
"Analyzing L%d descriptor: %#llx, pxn: %d, "
1818 "xn: %d, ap: %d, af: %d, type: %d\n",
1827 DPRINTF(PageTableWalker,
"Analyzing L%d descriptor: %#llx, type: %d\n",
1837 DPRINTF(
TLB,
"L%d descriptor Invalid, causing fault type %d\n",
1856 DPRINTF(
TLB,
"L%d descriptor causing Address Size Fault\n",
1863 DPRINTF(
TLB,
"L%d descriptor causing Access Fault\n",
1893 DPRINTF(
TLB,
"L%d descriptor points to L%d descriptor at: %#x (%s)\n",
1902 DPRINTF(
TLB,
"L%d descriptor causing Address Size Fault\n",
1938 Event *
event = NULL;
1940 case LookupLevel::L1:
1942 case LookupLevel::L2:
1943 case LookupLevel::L3:
1947 panic(
"Wrong lookup level in table walk\n");
1953 sizeof(uint64_t), flag, -1,
event,
1961 panic(
"A new type in a 2 bit field?\n");
1975 DPRINTF(
TLB,
"L2 descriptor for %#x is %#x\n",
1982 DPRINTF(
TLB,
"L2 descriptor invalid, causing fault\n");
2007 DPRINTF(
TLB,
"Generating access fault at L2, afe: %d, ap: %d\n",
2033 DPRINTF(PageTableWalker,
"L1 Desc object host addr: %p\n",
2035 DPRINTF(PageTableWalker,
"L1 Desc object data: %08x\n",
2038 DPRINTF(PageTableWalker,
"calling doL1Descriptor for vaddr:%#x\n",
2061 DPRINTF(PageTableWalker,
"calling translateTiming again\n");
2094 DPRINTF(PageTableWalker,
"calling doL2Descriptor for vaddr:%#x\n",
2105 DPRINTF(PageTableWalker,
"calling translateTiming again\n");
2164 DPRINTF(PageTableWalker,
"calling doLongDescriptor for vaddr:%#x\n",
2184 DPRINTF(PageTableWalker,
"calling translateTiming again\n");
2201 if (curr_lookup_level >= LookupLevel::Num_ArmLookupLevel - 1)
2202 panic(
"Max. number of lookups already reached in table walk\n");
2227 "Fetching descriptor at address: 0x%x stage2Req: %d\n",
2242 fault = tran->fault;
2255 if (queueIndex >= 0) {
2256 DPRINTF(PageTableWalker,
"Adding to walker fifo: "
2257 "queue size before adding: %d\n",
2263 (this->*doDescriptor)();
2270 if (queueIndex >= 0) {
2271 DPRINTF(PageTableWalker,
"Adding to walker fifo: "
2272 "queue size before adding: %d\n",
2281 (this->*doDescriptor)();
2284 (this->*doDescriptor)();
2293 const bool have_security =
release->
has(ArmExtension::SECURITY);
2298 te.longDescFormat =
true;
2309 te.size = (1ULL <<
te.N) - 1;
2315 te.type = TypeTLB::unified;
2328 DPRINTF(
TLB,
" - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
2330 DPRINTF(
TLB,
" - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
2331 "vmid:%d hyp:%d nc:%d ns:%d\n",
te.vpn,
te.xn,
te.pxn,
2332 te.ap,
static_cast<uint8_t
>(
te.domain),
te.asid,
te.vmid,
te.isHyp,
2333 te.nonCacheable,
te.ns);
2334 DPRINTF(
TLB,
" - domain from L%d desc:%d data:%#x\n",
2345 const bool have_security =
release->
has(ArmExtension::SECURITY);
2350 te.longDescFormat = long_descriptor;
2356 te.size = (1<<
te.N) - 1;
2357 te.pfn = descriptor.
pfn();
2362 te.xn = descriptor.
xn();
2364 TypeTLB::instruction : TypeTLB::data;
2377 if (long_descriptor) {
2386 te.hap = l_descriptor.
ap();
2396 te.ap = descriptor.
ap();
2403 DPRINTF(
TLB,
" - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
2405 DPRINTF(
TLB,
" - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
2406 "vmid:%d hyp:%d nc:%d ns:%d\n",
te.vpn,
te.xn,
te.pxn,
2407 te.ap,
static_cast<uint8_t
>(
te.domain),
te.asid,
te.vmid,
te.isHyp,
2408 te.nonCacheable,
te.ns);
2409 DPRINTF(
TLB,
" - domain from L%d desc:%d data:%#x\n",
2424 switch (lookup_level_as_int) {
2425 case LookupLevel::L1:
2426 return LookupLevel::L1;
2427 case LookupLevel::L2:
2428 return LookupLevel::L2;
2429 case LookupLevel::L3:
2430 return LookupLevel::L3;
2432 panic(
"Invalid lookup level conversion");
2479 panic(
"unknown page size");
2492 auto req = std::make_shared<Request>();
2540 :
data(_data), numBytes(0),
event(_event), parent(_parent),
2543 req = std::make_shared<Request>();
2562 parent.getTableWalkerPort().sendTimingReq(
2563 req->getPaddr(), numBytes,
data, req->getFlags(),
2575 parent.mmu->translateTiming(req, tc,
this,
mode, tranType,
true);
2579 : statistics::
Group(parent),
2580 ADD_STAT(walks, statistics::units::Count::get(),
2581 "Table walker walks requested"),
2582 ADD_STAT(walksShortDescriptor, statistics::units::Count::get(),
2583 "Table walker walks initiated with short descriptors"),
2584 ADD_STAT(walksLongDescriptor, statistics::units::Count::get(),
2585 "Table walker walks initiated with long descriptors"),
2586 ADD_STAT(walksShortTerminatedAtLevel, statistics::units::Count::get(),
2587 "Level at which table walker walks with short descriptors "
2589 ADD_STAT(walksLongTerminatedAtLevel, statistics::units::Count::get(),
2590 "Level at which table walker walks with long descriptors "
2592 ADD_STAT(squashedBefore, statistics::units::Count::get(),
2593 "Table walks squashed before starting"),
2594 ADD_STAT(squashedAfter, statistics::units::Count::get(),
2595 "Table walks squashed after completion"),
2597 "Table walker wait (enqueue to first request) latency"),
2598 ADD_STAT(walkServiceTime, statistics::units::
Tick::get(),
2599 "Table walker service (enqueue to completion) latency"),
2601 "Table walker pending requests distribution"),
2602 ADD_STAT(pageSizes, statistics::units::Count::get(),
2603 "Table walker page sizes translated"),
2604 ADD_STAT(requestOrigin, statistics::units::Count::get(),
2605 "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(ExceptionLevel el, bool e2h)
TlbEntry * lookup(Addr vpn, uint16_t asn, vmid_t vmid, bool hyp, bool secure, bool functional, bool ignore_asn, ExceptionLevel target_el, bool in_host, bool stage2, BaseMMU::Mode mode)
Lookup an entry in the TLB.
Fault testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode, TlbEntry::DomainType domain, LookupLevel lookup_level, bool stage2)
void translateTiming(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode) override
bool hasWalkCache() const
static ExceptionLevel tranTypeEL(CPSR cpsr, ArmTranslationType type)
Determine the EL to use for the purpose of a translation given a specific translation type.
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 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?
void sendFunctionalReq(Addr desc_addr, int size, uint8_t *data, Request::Flags flag)
void sendTimingReq(Addr desc_addr, int size, uint8_t *data, Request::Flags flag, Tick delay, Event *event)
PacketPtr createPacket(Addr desc_addr, int size, uint8_t *data, Request::Flags flag, Tick delay, Event *event)
void handleResp(TableWalkerState *state, Addr addr, Addr size, Tick delay=0)
void handleRespPacket(PacketPtr pkt, Tick delay=0)
void sendAtomicReq(Addr desc_addr, int size, uint8_t *data, Request::Flags flag, Tick delay)
Port(TableWalker &_walker, RequestorID id)
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
Helper variables used to implement hierarchical access permissions when the long-desc.
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.
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.
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.
void doL2DescriptorWrapper()
static LookupLevel toLookupLevel(uint8_t lookup_level_as_int)
enums::ArmLookupLevel LookupLevel
Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain, LookupLevel lookup_level, bool stage2)
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.
void doL1DescriptorWrapper()
Fault generateLongDescFault(ArmFault::FaultSource src)
EventFunctionWrapper doL1DescEvent
EventFunctionWrapper doProcessEvent
static const unsigned REQUESTED
static const unsigned COMPLETED
Event * LongDescEventByLevel[4]
void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, LongDescriptor &lDescriptor)
void insertPartialTableEntry(LongDescriptor &descriptor)
void doL1LongDescriptorWrapper()
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.
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 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.
Fault walk(const RequestPtr &req, ThreadContext *tc, uint16_t asid, vmid_t _vmid, bool hyp, BaseMMU::Mode mode, BaseMMU::Translation *_trans, bool timing, bool functional, bool secure, MMU::ArmTranslationType tran_type, bool stage2, const TlbEntry *walk_entry)
MMU * mmu
The MMU to forward second stage look upts to.
RequestorID requestorId
Requestor id assigned by the MMU.
bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, Request::Flags flags, int queueIndex, Event *event, void(TableWalker::*doDescriptor)())
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 ...
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 processWalkWrapper()
SCTLR sctlr
Cached copy of the sctlr as it existed when translation began.
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.
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...
ByteOrder byteOrder(const ThreadContext *tc)
const PageTableOps * getPageTableOps(GrainSize trans_granule)
bool isSecure(ThreadContext *tc)
ExceptionLevel s1TranslationRegime(ThreadContext *tc, ExceptionLevel el)
bool longDescFormatInUse(ThreadContext *tc)
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
const GrainSize GrainMap_tg1[]
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.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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
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
const std::string & name()