41#include "debug/SMMUv3.hh"
42#include "debug/SMMUv3Hazard.hh"
59 req.
sid =
pkt->req->streamId();
60 req.
ssid =
pkt->req->hasSubstreamId() ?
61 pkt->req->substreamId() : 0;
93 assert(
ifc.xlateSlotsRemaining > 0);
94 ifc.xlateSlotsRemaining--;
96 ifc.pendingMemAccesses++;
103 assert(
ifc.pendingMemAccesses > 0);
104 ifc.pendingMemAccesses--;
108 if (
ifc.pendingMemAccesses == 0) {
109 ifc.signalDrainDone();
124 assert(
smmu.system.isTimingMode());
126 assert(!
"Stalls are broken");
131 DPRINTF(
SMMUv3,
"Resume at tick = %d. Fault duration = %d (%.3fus)\n",
150 const Addr next4k = (
request.addr + 0x1000ULL) & ~0xfffULL;
153 panic(
"Transaction crosses 4k boundary (addr=%#x size=%#x)!\n",
157 unsigned numResponderBeats =
request.isWrite ?
175 bool wasPrefetched =
false;
267 bool haveConfig =
true;
287 }
else if (
context.stage2Enable) {
294 smmu.stats.ptwTimeDist.sample(
curTick() - ptwStartTick);
318 if (!
ifc.microTLBEnable)
328 DPRINTF(
SMMUv3,
"micro TLB miss vaddr=%#x sid=%#x ssid=%#x\n",
335 "micro TLB hit vaddr=%#x amask=%#x sid=%#x ssid=%#x paddr=%#x\n",
350 if (!
ifc.mainTLBEnable)
361 "RESPONSE Interface TLB miss vaddr=%#x sid=%#x ssid=%#x\n",
368 "RESPONSE Interface TLB hit vaddr=%#x amask=%#x sid=%#x ssid=%#x "
376 wasPrefetched =
e->prefetched;
394 DPRINTF(
SMMUv3,
"SMMU TLB miss vaddr=%#x asid=%#x vmid=%#x\n",
401 "SMMU TLB hit vaddr=%#x amask=%#x asid=%#x vmid=%#x paddr=%#x\n",
418 if (!
ifc.microTLBEnable)
423 e.prefetched =
false;
428 e.pa = tr.
addr &
e.vaMask;
436 "micro TLB upd vaddr=%#x amask=%#x paddr=%#x sid=%#x ssid=%#x\n",
437 e.va,
e.vaMask,
e.pa,
e.sid,
e.ssid);
450 if (!
ifc.mainTLBEnable)
460 e.pa = tr.
addr &
e.vaMask;
466 if (
ifc.prefetchEnable &&
ifc.prefetchReserveLastWay)
473 "RESPONSE Interface upd vaddr=%#x amask=%#x paddr=%#x sid=%#x "
474 "ssid=%#x\n",
e.va,
e.vaMask,
e.pa,
e.sid,
e.ssid);
476 ifc.mainTLB->store(
e, alloc);
496 e.pa = tr.
addr &
e.vaMask;
502 "SMMU TLB upd vaddr=%#x amask=%#x paddr=%#x asid=%#x vmid=%#x\n",
503 e.va,
e.vaMask,
e.pa,
e.asid,
e.vmid);
513 if (!
smmu.configCacheEnable)
529 DPRINTF(
SMMUv3,
"Config hit sid=%#x ssid=%#x ttb=%#08x asid=%#x\n",
554 if (!
smmu.configCacheEnable)
577 smmu.configCache.store(
e);
611 panic(
"Bad or unimplemented STE config %d\n",
624 tc.
httb = 0xdeadbeef;
642 tc.
ttb0 = 0xcafebabe;
643 tc.
ttb1 = 0xcafed00d;
657 unsigned stage,
unsigned level)
659 const char *indent = stage==2 ?
" " :
"";
662 const auto tg = stage == 1 ?
668 unsigned walkCacheLevels =
669 smmu.walkCacheEnable ?
670 (stage == 1 ?
smmu.walkCacheS1Levels :
smmu.walkCacheS2Levels) :
673 if ((1 <<
level) & walkCacheLevels) {
677 walkEntry =
smmu.walkCache.lookup(
addr, pt_ops->walkMask(
level),
682 "base=%#x (S%d, L%d)\n",
697 unsigned stage,
unsigned level,
698 bool leaf, uint8_t permissions)
700 unsigned walkCacheLevels =
701 stage == 1 ?
smmu.walkCacheS1Levels :
smmu.walkCacheS2Levels;
703 if (
smmu.walkCacheEnable && ((1<<
level) & walkCacheLevels)) {
708 e.asid = stage==1 ?
context.asid : 0;
714 e.permissions = permissions;
718 DPRINTF(
SMMUv3,
"%sWalkCache upd va=%#x mask=%#x asid=%#x vmid=%#x "
719 "tpa=%#x leaf=%s (S%d, L%d)\n",
720 e.stage==2 ?
" " :
"",
721 e.va,
e.vaMask,
e.asid,
e.vmid,
722 e.pa,
e.leaf,
e.stage,
e.level);
724 smmu.walkCache.store(
e);
756 level, pte, pte_addr);
773 if (valid && leaf &&
request.isWrite &&
803 tr.
addr = walkPtr + (
addr & ~tr.addrMask);
843 level, pte, pte_addr);
860 if (valid && leaf &&
request.isWrite &&
872 if (final_tr ||
smmu.walkCacheNonfinalEnable)
883 tr.
addr = walkPtr + (
addr & ~tr.addrMask);
900 for (
level = pt_ops->lastLevel() + 1;
918 tr.
addr = walk_ep->
pa + (
addr & ~walk_ep->vaMask);
932 table_addr = s2tr.
addr;
936 pt_ops->firstLevel(
context.t0sz),
953 if (
smmu.ipaCacheEnable) {
963 tr.
addr = ipa_ep->
pa + (
addr & ~ipa_ep->ipaMask);
971 }
else if (
smmu.ipaCacheEnable) {
979 if (final_tr ||
smmu.walkCacheNonfinalEnable) {
982 for (
level = pt_ops->lastLevel() + 1;
1001 tr.
addr = walk_ep->
pa + (
addr & ~walk_ep->vaMask);
1010 pt_ops->firstLevel(
context.s2t0sz),
1018 if (
smmu.ipaCacheEnable) {
1022 e.ipa =
addr &
e.ipaMask;
1028 smmu.ipaCache.store(
e);
1058 for (
auto it =
ifc.duplicateReqs.begin();
1059 it !=
ifc.duplicateReqs.end();
1062 Addr other4k = (*it)->request.addr & ~0xfffULL;
1063 if (addr4k == other4k)
1073 DPRINTF(SMMUv3Hazard,
"4kReg: p=%p a4k=%#x\n",
1074 this,
request.addr & ~0xfffULL);
1076 ifc.duplicateReqs.push_back(
this);
1087 found_hazard =
false;
1089 for (
auto it =
ifc.duplicateReqs.begin();
1090 it!=
ifc.duplicateReqs.end() && *it!=
this;
1093 Addr other4k = (*it)->request.addr & ~0xfffULL;
1095 DPRINTF(SMMUv3Hazard,
"4kHold: p=%p a4k=%#x Q: p=%p a4k=%#x\n",
1096 this, addr4k, *it, other4k);
1098 if (addr4k == other4k) {
1100 "4kHold: p=%p a4k=%#x WAIT on p=%p a4k=%#x\n",
1101 this, addr4k, *it, other4k);
1105 DPRINTF(SMMUv3Hazard,
"4kHold: p=%p a4k=%#x RESUME\n",
1110 found_hazard =
true;
1114 }
while (found_hazard);
1120 DPRINTF(SMMUv3Hazard,
"4kRel: p=%p a4k=%#x\n",
1121 this,
request.addr & ~0xfffULL);
1125 for (it =
ifc.duplicateReqs.begin(); it !=
ifc.duplicateReqs.end(); ++it)
1129 if (it ==
ifc.duplicateReqs.end())
1130 panic(
"hazard4kRelease: request not found");
1132 ifc.duplicateReqs.erase(it);
1142 DPRINTF(SMMUv3Hazard,
"IdReg: p=%p oid=%d\n",
this, orderId);
1148 ifc.dependentWrites[orderId] :
ifc.dependentReads[orderId];
1149 depReqs.push_back(
this);
1157 DPRINTF(SMMUv3Hazard,
"IdHold: p=%p oid=%d\n",
this, orderId);
1161 ifc.dependentWrites[orderId] :
ifc.dependentReads[orderId];
1167 found_hazard =
false;
1169 for (
auto it = depReqs.begin(); it!=depReqs.end() && *it!=
this; ++it) {
1170 DPRINTF(SMMUv3Hazard,
"IdHold: p=%p oid=%d Q: %p\n",
1171 this, orderId, *it);
1174 DPRINTF(SMMUv3Hazard,
"IdHold: p=%p oid=%d WAIT on=%p\n",
1175 this, orderId, *it);
1179 DPRINTF(SMMUv3Hazard,
"IdHold: p=%p oid=%d RESUME\n",
1184 found_hazard =
true;
1188 }
while (found_hazard);
1196 DPRINTF(SMMUv3Hazard,
"IdRel: p=%p oid=%d\n",
this, orderId);
1200 ifc.dependentWrites[orderId] :
ifc.dependentReads[orderId];
1203 for (it = depReqs.begin(); it != depReqs.end(); ++it) {
1208 if (it == depReqs.end())
1209 panic(
"hazardIdRelease: request not found");
1219 if (!
smmu.system.isTimingMode())
1222 if (!
ifc.prefetchEnable ||
ifc.xlateSlotsRemaining == 0)
1238 DPRINTF(
SMMUv3,
"Translation Fault (addr=%#x, size=%#x, sid=%d, ssid=%d, "
1239 "isWrite=%d, isPrefetch=%d, isAtsRequest=%d)\n",
1252 ifc.xlateSlotsRemaining++;
1253 smmu.scheduleDeviceRetries();
1255 if (
smmu.system.isAtomicMode()) {
1256 request.pkt->makeAtomicResponse();
1257 }
else if (
smmu.system.isTimingMode()) {
1258 request.pkt->makeTimingResponse();
1260 panic(
"Not in atomic or timing mode");
1280 unsigned numRequestorBeats =
request.isWrite ?
1282 /
smmu.requestPortWidth :
1291 ifc.xlateSlotsRemaining++;
1293 ifc.wrBufSlotsRemaining +=
1296 smmu.scheduleDeviceRetries();
1304 if (
smmu.system.isAtomicMode()) {
1305 request.pkt->makeAtomicResponse();
1306 }
else if (
smmu.system.isTimingMode()) {
1307 request.pkt->makeTimingResponse();
1309 panic(
"Not in atomic or timing mode");
1319 a.pkt->setAddr(tr.
addr);
1320 a.pkt->req->setPaddr(tr.
addr);
1339 ifc.xlateSlotsRemaining++;
1356 event.data.dw0.streamId =
request.sid;
1357 event.data.dw0.substreamId =
request.ssid;
1358 event.data.dw1.rnw = !
request.isWrite;
1359 event.data.dw2.inputAddr =
request.addr;
1363 event.data.dw1.nsipa =
true;
1380 if (((
smmu.regs.eventq_prod+1) & sizeMask) ==
1381 (
smmu.regs.eventq_cons & sizeMask))
1382 panic(
"Event queue full - aborting\n");
1386 (
smmu.regs.eventq_prod & sizeMask) *
sizeof(ev.
data);
1388 DPRINTF(
SMMUv3,
"Sending event to addr=%#08x (pos=%d): %s\n",
1389 event_addr,
smmu.regs.eventq_prod, ev.
print());
1391 bool empty_queue = (
smmu.regs.eventq_prod & sizeMask) ==
1392 (
smmu.regs.eventq_cons & sizeMask);
1395 smmu.regs.eventq_prod = (
smmu.regs.eventq_prod + 1) & sizeMask;
1401 if (IRQCtrl irq_ctrl =
smmu.regs.irq_ctrl;
1402 irq_ctrl.eventqIrqEn && empty_queue) {
1416 if (IDR0 idr0 =
smmu.regs.idr0; idr0.msi && msi_addr != 0) {
1419 &
smmu.regs.eventq_irq_cfg1,
sizeof(
smmu.regs.eventq_irq_cfg1));
1421 if (
smmu.eventqInterrupt) {
1423 smmu.eventqInterrupt->raise();
1434 panic(
"SID %#x out of range, max=%#x", sid, max_sid);
1442 if (split!= 7 && split!=8 && split!=16)
1443 panic(
"Invalid stream table split %d", split);
1448 bits(sid, 32, split) *
sizeof(l2_ptr);
1452 doReadConfig(yield, l2_addr, &l2_ptr,
sizeof(l2_ptr), sid, 0);
1454 DPRINTF(
SMMUv3,
"Got L1STE L1 at %#x: 0x%016x\n", l2_addr, l2_ptr);
1458 panic(
"Invalid level 1 stream table descriptor");
1462 panic(
"StreamID %d out of level 1 descriptor range %d",
1467 smmu.stats.steL1Fetches++;
1473 panic(
"Invalid stream table format");
1478 doReadConfig(yield, ste_addr, &ste,
sizeof(ste), sid, 0);
1480 DPRINTF(
SMMUv3,
"Got STE at %#x [0]: 0x%016x\n", ste_addr, ste.dw0);
1481 DPRINTF(
SMMUv3,
" STE at %#x [1]: 0x%016x\n", ste_addr, ste.dw1);
1482 DPRINTF(
SMMUv3,
" STE at %#x [2]: 0x%016x\n", ste_addr, ste.dw2);
1483 DPRINTF(
SMMUv3,
" STE at %#x [3]: 0x%016x\n", ste_addr, ste.dw3);
1490 panic(
"STE @ %#x not valid\n", ste_addr);
1492 smmu.stats.steFetches++;
1499 uint32_t sid, uint32_t ssid)
1507 unsigned max_ssid = 1 << ste.dw0.
s1cdmax;
1508 if (ssid >= max_ssid)
1509 panic(
"SSID %#x out of range, max=%#x", ssid, max_ssid);
1518 bits(ssid, 24, split) *
sizeof(l2_ptr);
1532 doReadConfig(yield, l2_addr, &l2_ptr,
sizeof(l2_ptr), sid, ssid);
1534 DPRINTF(
SMMUv3,
"Got L1CD at %#x: 0x%016x\n", l2_addr, l2_ptr);
1536 cd_addr = l2_ptr +
bits(ssid, split-1, 0) *
sizeof(
cd);
1538 smmu.stats.cdL1Fetches++;
1569 panic(
"CD @ %#x not valid\n", cd_addr);
1571 smmu.stats.cdFetches++;
1577 void *ptr,
size_t size,
1578 uint32_t sid, uint32_t ssid)
1585 void *ptr,
unsigned stage,
Base class for ARM GIC implementations.
Cycles is a wrapper class for representing cycle counts, i.e.
void setAddr(Addr _addr)
Update the address of this packet mid-transaction.
const std::string name() const
void doWrite(Yield &yield, Addr addr, const void *ptr, size_t size)
Coroutine::CallerType Yield
void doDelay(Yield &yield, Cycles cycles)
void doSemaphoreUp(SMMUSemaphore &sem)
SMMUProcess(const std::string &name, SMMUv3 &_smmu)
void scheduleWakeup(Tick when)
void doBroadcastSignal(SMMUSignal &sig)
void doSemaphoreDown(Yield &yield, SMMUSemaphore &sem)
void doWaitForSignal(Yield &yield, SMMUSignal &sig)
void doRead(Yield &yield, Addr addr, void *ptr, size_t size)
bool ifcTLBLookup(Yield &yield, TranslResult &tr, bool &wasPrefetched)
void configCacheUpdate(Yield &yield, const TranslContext &tc)
TranslResult translateStage1And2(Yield &yield, Addr addr)
void smmuTLBUpdate(Yield &yield, const TranslResult &tr)
SMMUTranslationProcess(const std::string &name, SMMUv3 &_smmu, SMMUv3DeviceInterface &_ifc)
TranslResult smmuTranslation(Yield &yield)
SMMUTranslRequest request
TranslResult bypass(Addr addr) const
void beginTransaction(const SMMUTranslRequest &req)
bool findConfig(Yield &yield, TranslContext &tc, TranslResult &tr)
void walkCacheLookup(Yield &yield, const WalkCache::Entry *&walkEntry, Addr addr, uint16_t asid, uint16_t vmid, unsigned stage, unsigned level)
bool smmuTLBLookup(Yield &yield, TranslResult &tr)
virtual void main(Yield &yield)
void abortTransaction(Yield &yield, const TranslResult &tr)
SMMUEvent generateEvent(const TranslResult &tr)
virtual ~SMMUTranslationProcess()
void hazardIdRegister()
Used to force ordering on transactions with the same orderId.
TranslResult walkStage2(Yield &yield, Addr addr, bool final_tr, const ArmISA::PageTableOps *pt_ops, unsigned level, Addr walkPtr)
TranslResult translateStage2(Yield &yield, Addr addr, bool final_tr)
void doReadConfig(Yield &yield, Addr addr, void *ptr, size_t size, uint32_t sid, uint32_t ssid)
void hazard4kHold(Yield &yield)
void doReadSTE(Yield &yield, StreamTableEntry &ste, uint32_t sid)
void hazardIdHold(Yield &yield)
void issuePrefetch(Addr addr)
SMMUv3DeviceInterface & ifc
bool microTLBLookup(Yield &yield, TranslResult &tr)
bool configCacheLookup(Yield &yield, TranslContext &tc)
TranslResult doReadCD(Yield &yield, ContextDescriptor &cd, const StreamTableEntry &ste, uint32_t sid, uint32_t ssid)
bool hazard4kCheck()
Used to force ordering on transactions with same (SID, SSID, 4k page) to avoid multiple identical pag...
void ifcTLBUpdate(Yield &yield, const TranslResult &tr)
TranslResult walkStage1And2(Yield &yield, Addr addr, const ArmISA::PageTableOps *pt_ops, unsigned level, Addr walkPtr)
void sendEvent(Yield &yield, const SMMUEvent &ev)
void microTLBUpdate(Yield &yield, const TranslResult &tr)
void doReadPTE(Yield &yield, Addr va, Addr addr, void *ptr, unsigned stage, unsigned level)
void walkCacheUpdate(Yield &yield, Addr va, Addr vaMask, Addr pa, unsigned stage, unsigned level, bool leaf, uint8_t permissions)
void completePrefetch(Yield &yield)
GEM5_CLASS_VAR_USED Tick faultTick
TranslResult combineTranslations(const TranslResult &s1tr, const TranslResult &s2tr) const
void completeTransaction(Yield &yield, const TranslResult &tr)
void sendEventInterrupt(Yield &yield)
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define panic(...)
This implements a cprintf based panic() function.
static OrderID orderId(PacketPtr pkt)
const PageTableOps * getPageTableOps(GrainSize trans_granule)
const GrainSize GrainMap_tg0[]
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< FaultBase > Fault
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
@ STE_CONFIG_STAGE1_AND_2
std::string csprintf(const char *format, const Args &...args)
This is an implementation of the SMMUv3 architecture.
virtual bool isWritable(pte_t pte, unsigned level, bool stage2) const =0
Addr walkMask(unsigned level) const
virtual LookupLevel lastLevel() const =0
virtual Addr nextLevelPointer(pte_t pte, unsigned level) const =0
virtual bool isValid(pte_t pte, unsigned level) const =0
virtual Addr pageMask(pte_t pte, unsigned level) const =0
virtual Addr index(Addr va, unsigned level, int tsz) const =0
virtual bool isLeaf(pte_t pte, unsigned level) const =0
struct gem5::SMMUEvent::Data data
std::string print() const
static SMMUTranslRequest fromPacket(PacketPtr pkt, bool ats=false)
static SMMUTranslRequest prefetch(Addr addr, uint32_t sid, uint32_t ssid)
uint8_t stage1TranslGranule
uint8_t stage2TranslGranule
Bitfield< 51, 6 > s1ctxptr
Bitfield< 37, 32 > s2t0sz
Bitfield< 63, 59 > s1cdmax