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;
219 DPRINTF(PageTableWalker,
"Squashing table walk for address %#x\n",
220 currState->
req->getVaddr());
225 std::make_shared<UnimpFault>(
"Squashed Inst"),
226 currState->
req, currState->
tc, currState->
mode);
250 currState->
mode,
e->pte);
270 setupWalk(req->getVaddr());
278 walker->port.sendAtomic(read);
280 fault = stepWalk(write);
281 assert(fault ==
NoFault || read == NULL);
285 walker->port.sendAtomic(write);
302 walker->port.sendFunctional(read);
306 fault = stepWalk(write);
307 assert(fault ==
NoFault || read == NULL);
311 logBytes = entry.logBytes;
323 PTESv39 pte = read->
getLE<uint64_t>();
325 bool doWrite =
false;
326 bool doTLBInsert =
false;
327 bool doEndWalk =
false;
329 DPRINTF(PageTableWalker,
"Got level%d PTE: %#x\n",
level, pte);
340 fault = walker->pma->check(read->req,
BaseMMU::Read, entry.vaddr);
345 if (!pte.v || (!pte.r && pte.w)) {
347 DPRINTF(PageTableWalker,
"PTE invalid, raising PF\n");
348 fault = pageFault(pte.v);
352 if (pte.r || pte.x) {
355 fault = walker->tlb->checkPermissions(
status, pmode,
356 entry.vaddr,
mode, pte);
360 if (
level >= 1 && pte.ppn0 != 0) {
362 "PTE has misaligned PPN, raising PF\n");
363 fault = pageFault(
true);
365 else if (
level == 2 && pte.ppn1 != 0) {
367 "PTE has misaligned PPN, raising PF\n");
368 fault = pageFault(
true);
389 fault = walker->pmp->pmpCheck(read->req,
393 fault = walker->pma->check(read->req,
401 "#0 leaf node at level %d, with vpn %#x\n",
406 entry.paddr = pte.ppn;
407 entry.vaddr &= ~((1 << entry.logBytes) - 1);
418 walker->pagewalkerstats.num_2mb_walks++;
421 walker->pagewalkerstats.num_4kb_walks++;
424 "#1 leaf node at level %d, with vpn %#x\n",
431 DPRINTF(PageTableWalker,
"No leaf PTE found,"
434 fault = pageFault(
true);
438 nextRead = (pte.ppn <<
PageShift) + (idx *
sizeof(pte));
439 nextState = Translate;
452 if (!functional && doWrite) {
453 DPRINTF(PageTableWalker,
"Writing level%d PTE to %#x: %#x\n",
456 write->
setLE<uint64_t>(pte);
465 walker->tlb->insert(entry.vaddr, entry);
467 DPRINTF(PageTableWalker,
"Translated %#x -> %#x\n",
469 (entry.vaddr &
mask(entry.logBytes)));
476 RequestPtr request = std::make_shared<Request>(
477 nextRead, oldRead->
getSize(),
flags, walker->requestorId);
486 "Loading level%d PTE from %#x\n",
level, nextRead);
507 Addr topAddr = (satp.ppn <<
PageShift) + (idx *
sizeof(PTESv39));
510 DPRINTF(PageTableWalker,
"Performing table walk for address %#x\n",
vaddr);
511 DPRINTF(PageTableWalker,
"Loading level%d PTE from %#x\n",
level, topAddr);
516 entry.asid = satp.asid;
519 RequestPtr request = std::make_shared<Request>(
520 topAddr,
sizeof(PTESv39),
flags, walker->requestorId);
531 assert(
state == Waiting);
536 return (inflight == 0);
549 timingFault = stepWalk(write);
551 assert(timingFault ==
NoFault || read == NULL);
553 writes.push_back(write);
561 if (inflight == 0 && read == NULL && writes.size() == 0) {
574 Addr paddr = walker->tlb->translateWithTLB(
vaddr, satp.asid,
mode);
575 req->setPaddr(paddr);
580 timingFault = walker->pmp->pmpCheck(req,
mode, pmode, tc);
583 timingFault = walker->pma->check(req,
mode);
587 translation->finish(timingFault, req, tc,
mode);
590 translation->finish(timingFault, req, tc,
mode);
610 if (!walker->sendTiming(
this, pkt)) {
618 while (writes.size()) {
622 if (!walker->sendTiming(
this, write)) {
624 writes.push_back(write);
671 DPRINTF(PageTableWalker,
"Raising page fault.\n");
672 return walker->tlb->createPagefault(entry.vaddr,
mode);
676 : statistics::
Group(parent),
677 ADD_STAT(num_4kb_walks, statistics::units::Count::get(),
678 "Completed page walks with 4KB pages"),
679 ADD_STAT(num_2mb_walks, statistics::units::Count::get(),
680 "Completed page walks with 2MB pages")
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
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.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setLE(T v)
Set the value in the data pointer to v as little endian.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
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...
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
RequestPtr req
A pointer to the original request.
MemCmd cmd
The command field of the packet.
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Ports are used to interface objects to each other.
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
@ PHYSICAL
The virtual address is also the physical address.
void translateTiming(const RequestPtr &req, ThreadContext *tc, BaseMMU::Translation *translation, BaseMMU::Mode mode) override
TlbEntry * lookup(Addr vpn, uint16_t asid, BaseMMU::Mode mode, bool hidden)
Fault checkPermissions(STATUS status, PrivilegeMode pmode, Addr vaddr, BaseMMU::Mode mode, PTESv39 pte)
void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Fault startFunctional(Addr &addr, unsigned &logBytes)
bool recvPacket(PacketPtr pkt)
void setupWalk(Addr vaddr)
Fault stepWalk(PacketPtr &write)
BaseMMU::Translation * translation
Fault pageFault(bool present)
unsigned numInflight() const
void initState(ThreadContext *_tc, BaseMMU::Mode _mode, bool _isTiming=false)
Fault startFunctional(ThreadContext *_tc, Addr &addr, unsigned &logBytes, BaseMMU::Mode mode)
EventFunctionWrapper startWalkWrapperEvent
Event used to call startWalkWrapper.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
bool sendTiming(WalkerState *sendingState, PacketPtr pkt)
bool recvTimingResp(PacketPtr pkt)
std::list< WalkerState * > currStates
Fault start(ThreadContext *_tc, BaseMMU::Translation *translation, const RequestPtr &req, BaseMMU::Mode mode)
bool isTimingMode() const
Is the system in timing mode?
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
bool scheduled() const
Determine if the current event is scheduled.
void schedule(Event &event, Tick when)
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
std::shared_ptr< FaultBase > Fault
std::shared_ptr< Request > RequestPtr
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.
constexpr decltype(nullptr) NoFault
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
PagewalkerStats(statistics::Group *parent)