Go to the documentation of this file.
63 #include "debug/PageTableWalker.hh"
117 bool walkComplete = senderWalk->
recvPacket(pkt);
123 if (walkerState == senderWalk) {
142 walker->recvReqRetry();
152 walkerState->
retry();
176 if (if_name ==
"port")
186 assert(state == Ready);
193 pmode = walker->tlb->getMemPriv(tc,
mode);
195 assert(satp.mode == AddrXlateMode::SV39);
201 unsigned num_squashed = 0;
208 DPRINTF(PageTableWalker,
"Squashing table walk for address %#x\n",
209 currState->
req->getVaddr());
213 std::make_shared<UnimpFault>(
"Squashed Inst"),
214 currState->
req, currState->
tc, currState->
mode);
241 setupWalk(req->getVaddr());
249 walker->port.sendAtomic(read);
251 fault = stepWalk(write);
252 assert(fault ==
NoFault || read == NULL);
256 walker->port.sendAtomic(write);
273 walker->port.sendFunctional(read);
277 fault = stepWalk(write);
278 assert(fault ==
NoFault || read == NULL);
282 logBytes = entry.logBytes;
291 assert(state != Ready && state != Waiting);
294 PTESv39 pte = read->
getLE<uint64_t>();
296 bool doWrite =
false;
297 bool doTLBInsert =
false;
298 bool doEndWalk =
false;
300 DPRINTF(PageTableWalker,
"Got level%d PTE: %#x\n",
level, pte);
305 walker->pma->check(read->req);
308 fault = walker->pmp->pmpCheck(read->req,
mode,
313 if (!pte.v || (!pte.r && pte.w)) {
315 DPRINTF(PageTableWalker,
"PTE invalid, raising PF\n");
316 fault = pageFault(pte.v);
320 if (pte.r || pte.x) {
323 fault = walker->tlb->checkPermissions(
status, pmode,
324 entry.vaddr,
mode, pte);
328 if (
level >= 1 && pte.ppn0 != 0) {
330 "PTE has misaligned PPN, raising PF\n");
331 fault = pageFault(
true);
333 else if (
level == 2 && pte.ppn1 != 0) {
335 "PTE has misaligned PPN, raising PF\n");
336 fault = pageFault(
true);
357 walker->pma->check(read->req);
359 fault = walker->pmp->pmpCheck(read->req,
360 mode, pmode, tc, entry.vaddr);
368 entry.paddr = pte.ppn;
369 entry.vaddr &= ~((1 << entry.logBytes) - 1);
382 DPRINTF(PageTableWalker,
"No leaf PTE found,"
385 fault = pageFault(
true);
389 nextRead = (pte.ppn <<
PageShift) + (idx *
sizeof(pte));
390 nextState = Translate;
403 if (!functional && doWrite) {
404 DPRINTF(PageTableWalker,
"Writing level%d PTE to %#x: %#x\n",
407 write->
setLE<uint64_t>(pte);
416 walker->tlb->insert(entry.vaddr, entry);
418 DPRINTF(PageTableWalker,
"Translated %#x -> %#x\n",
420 (entry.vaddr &
mask(entry.logBytes)));
427 RequestPtr request = std::make_shared<Request>(
428 nextRead, oldRead->
getSize(), flags, walker->requestorId);
433 "Loading level%d PTE from %#x\n",
level, nextRead);
454 Addr topAddr = (satp.ppn <<
PageShift) + (idx *
sizeof(PTESv39));
457 DPRINTF(PageTableWalker,
"Performing table walk for address %#x\n",
vaddr);
458 DPRINTF(PageTableWalker,
"Loading level%d PTE from %#x\n",
level, topAddr);
463 entry.asid = satp.asid;
466 RequestPtr request = std::make_shared<Request>(
467 topAddr,
sizeof(PTESv39), flags, walker->requestorId);
478 assert(state == Waiting);
483 return (inflight == 0);
496 timingFault = stepWalk(write);
498 assert(timingFault ==
NoFault || read == NULL);
500 writes.push_back(write);
506 if (inflight == 0 && read == NULL && writes.size() == 0) {
519 Addr paddr = walker->tlb->translateWithTLB(
vaddr, satp.asid,
mode);
520 req->setPaddr(paddr);
521 walker->pma->check(req);
526 timingFault = walker->pmp->pmpCheck(req,
mode, pmode, tc);
529 translation->finish(timingFault, req, tc,
mode);
532 translation->finish(timingFault, req, tc,
mode);
552 if (!walker->sendTiming(
this, pkt)) {
560 while (writes.size()) {
564 if (!walker->sendTiming(
this, write)) {
566 writes.push_back(write);
613 DPRINTF(PageTableWalker,
"Raising page fault.\n");
614 return walker->tlb->createPagefault(entry.vaddr,
mode);
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
virtual bool squashed() const
This function is used by the page table walker to determine if it should translate the a pending requ...
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
constexpr decltype(nullptr) NoFault
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
void setupWalk(Addr vaddr)
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
RequestPtr req
A pointer to the original request.
Fault startFunctional(ThreadContext *_tc, Addr &addr, unsigned &logBytes, BaseMMU::Mode mode)
Fault startFunctional(Addr &addr, unsigned &logBytes)
void schedule(Event &event, Tick when)
bool recvPacket(PacketPtr pkt)
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Fault start(ThreadContext *_tc, BaseMMU::Translation *translation, const RequestPtr &req, BaseMMU::Mode mode)
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
BaseMMU::Translation * translation
Fault pageFault(bool present)
ThreadContext is the external interface to all thread state for anything outside of the CPU.
std::shared_ptr< FaultBase > Fault
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
ProbePointArg< PacketInfo > Packet
Packet probe point.
std::shared_ptr< Request > RequestPtr
EventFunctionWrapper startWalkWrapperEvent
Event used to call startWalkWrapper.
bool isTimingMode() const
Is the system in timing mode?
MemCmd cmd
The command field of the packet.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
unsigned numInflight() const
void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Fault stepWalk(PacketPtr &write)
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...
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Ports are used to interface objects to each other.
bool recvTimingResp(PacketPtr pkt)
bool sendTiming(WalkerState *sendingState, PacketPtr pkt)
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void setLE(T v)
Set the value in the data pointer to v as little endian.
std::list< WalkerState * > currStates
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode)=0
void initState(ThreadContext *_tc, BaseMMU::Mode _mode, bool _isTiming=false)
bool scheduled() const
Determine if the current event is scheduled.
@ PHYSICAL
The virtual address is also the physical address.
Generated on Wed May 4 2022 12:13:50 for gem5 by doxygen 1.8.17