61 #include "debug/PageTableWalker.hh" 103 return walker->recvTimingResp(pkt);
112 bool walkComplete = senderWalk->
recvPacket(pkt);
118 if (walkerState == senderWalk) {
137 walker->recvReqRetry();
147 walkerState->
retry();
171 if (if_name ==
"port")
181 assert(state == Ready);
191 unsigned num_squashed = 0;
198 DPRINTF(PageTableWalker,
"Squashing table walk for address %#x\n",
199 currState->
req->getVaddr());
203 std::make_shared<UnimpFault>(
"Squashed Inst"),
204 currState->
req, currState->
tc, currState->
mode);
231 setupWalk(req->getVaddr());
239 walker->port.sendAtomic(read);
241 fault = stepWalk(write);
242 assert(fault ==
NoFault || read == NULL);
246 walker->port.sendAtomic(write);
263 walker->port.sendFunctional(read);
267 fault = stepWalk(write);
268 assert(fault ==
NoFault || read == NULL);
272 logBytes = entry.logBytes;
281 assert(state != Ready && state != Waiting);
286 pte = read->
getLE<uint64_t>();
288 pte = read->getLE<uint32_t>();
289 VAddr
vaddr = entry.vaddr;
290 bool uncacheable = pte.pcd;
292 bool doWrite =
false;
293 bool doTLBInsert =
false;
294 bool doEndWalk =
false;
299 "Got long mode PML4 entry %#016x.\n", (uint64_t)pte);
300 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.longl3 * dataSize;
303 entry.writable = pte.w;
305 if (badNX || !pte.p) {
307 fault = pageFault(pte.p);
310 entry.noExec = pte.nx;
315 "Got long mode PDP entry %#016x.\n", (uint64_t)pte);
316 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.longl2 * dataSize;
319 entry.writable = entry.writable && pte.w;
320 entry.user = entry.user && pte.u;
321 if (badNX || !pte.p) {
323 fault = pageFault(pte.p);
330 "Got long mode PD entry %#016x.\n", (uint64_t)pte);
333 entry.writable = entry.writable && pte.w;
334 entry.user = entry.user && pte.u;
335 if (badNX || !pte.p) {
337 fault = pageFault(pte.p);
344 ((uint64_t)pte & (
mask(40) << 12)) + vaddr.longl1 * dataSize;
350 entry.paddr = (uint64_t)pte & (
mask(31) << 21);
351 entry.uncacheable = uncacheable;
352 entry.global = pte.g;
353 entry.patBit =
bits(pte, 12);
354 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
361 "Got long mode PTE entry %#016x.\n", (uint64_t)pte);
364 entry.writable = entry.writable && pte.w;
365 entry.user = entry.user && pte.u;
366 if (badNX || !pte.p) {
368 fault = pageFault(pte.p);
371 entry.paddr = (uint64_t)pte & (
mask(40) << 12);
372 entry.uncacheable = uncacheable;
373 entry.global = pte.g;
374 entry.patBit =
bits(pte, 12);
375 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
381 "Got legacy mode PAE PDP entry %#08x.\n", (uint32_t)pte);
382 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.pael2 * dataSize;
385 fault = pageFault(pte.p);
392 "Got legacy mode PAE PD entry %#08x.\n", (uint32_t)pte);
395 entry.writable = pte.w;
397 if (badNX || !pte.p) {
399 fault = pageFault(pte.p);
405 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.pael1 * dataSize;
411 entry.paddr = (uint64_t)pte & (
mask(31) << 21);
412 entry.uncacheable = uncacheable;
413 entry.global = pte.g;
414 entry.patBit =
bits(pte, 12);
415 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
422 "Got legacy mode PAE PTE entry %#08x.\n", (uint32_t)pte);
425 entry.writable = entry.writable && pte.w;
426 entry.user = entry.user && pte.u;
427 if (badNX || !pte.p) {
429 fault = pageFault(pte.p);
432 entry.paddr = (uint64_t)pte & (
mask(40) << 12);
433 entry.uncacheable = uncacheable;
434 entry.global = pte.g;
435 entry.patBit =
bits(pte, 7);
436 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
442 "Got legacy mode PSE PD entry %#08x.\n", (uint32_t)pte);
445 entry.writable = pte.w;
449 fault = pageFault(pte.p);
456 ((uint64_t)pte & (
mask(20) << 12)) + vaddr.norml2 * dataSize;
462 entry.paddr =
bits(pte, 20, 13) << 32 |
bits(pte, 31, 22) << 22;
463 entry.uncacheable = uncacheable;
464 entry.global = pte.g;
465 entry.patBit =
bits(pte, 12);
466 entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1);
473 "Got legacy mode PD entry %#08x.\n", (uint32_t)pte);
476 entry.writable = pte.w;
480 fault = pageFault(pte.p);
485 nextRead = ((uint64_t)pte & (
mask(20) << 12)) + vaddr.norml2 * dataSize;
490 "Got legacy mode PTE entry %#08x.\n", (uint32_t)pte);
493 entry.writable = pte.w;
497 fault = pageFault(pte.p);
500 entry.paddr = (uint64_t)pte & (
mask(20) << 12);
501 entry.uncacheable = uncacheable;
502 entry.global = pte.g;
503 entry.patBit =
bits(pte, 7);
504 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
509 panic(
"Unknown page table walker state %d!\n");
514 walker->tlb->insert(entry.vaddr, entry);
521 RequestPtr request = std::make_shared<Request>(
522 nextRead, oldRead->
getSize(), flags, walker->masterId);
529 write->
setLE<uint64_t>(pte);
559 topAddr = (cr3.longPdtb << 12) + addr.longl4 * dataSize;
567 topAddr = (cr3.paePdtb << 5) + addr.pael3 * dataSize;
571 topAddr = (cr3.pdtb << 12) + addr.norml2 * dataSize;
590 RequestPtr request = std::make_shared<Request>(
591 topAddr, dataSize, flags, walker->masterId);
602 assert(state == Waiting);
607 return (inflight == 0);
620 timingFault = stepWalk(write);
622 assert(timingFault ==
NoFault || read == NULL);
624 writes.push_back(write);
630 if (inflight == 0 && read == NULL && writes.size() == 0) {
641 bool delayedResponse;
642 Fault fault = walker->tlb->translate(req, tc, NULL,
mode,
643 delayedResponse,
true);
644 assert(!delayedResponse);
646 translation->finish(fault, req, tc,
mode);
649 translation->finish(timingFault, req, tc,
mode);
669 if (!walker->sendTiming(
this, pkt)) {
677 while (writes.size()) {
681 if (!walker->sendTiming(
this, write)) {
683 writes.push_back(write);
730 DPRINTF(PageTableWalker,
"Raising page fault.\n");
734 return std::make_shared<PageFault>(entry.vaddr,
present,
mode,
735 m5reg.cpl == 3,
false);
741 X86PagetableWalkerParams::create()
void setupWalk(Addr vaddr)
#define panic(...)
This implements a cprintf based panic() function.
Ports are used to interface objects to each other.
bool sendTiming(WalkerState *sendingState, PacketPtr pkt)
decltype(nullptr) constexpr NoFault
void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
bool recvPacket(PacketPtr pkt)
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
std::shared_ptr< Request > RequestPtr
Fault start(ThreadContext *_tc, BaseTLB::Translation *translation, const RequestPtr &req, BaseTLB::Mode mode)
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
TLB::Translation * translation
ThreadContext is the external interface to all thread state for anything outside of the CPU...
EventFunctionWrapper startWalkWrapperEvent
Event used to call startWalkWrapper.
The request is to an uncacheable address.
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
void initState(ThreadContext *_tc, BaseTLB::Mode _mode, bool _isTiming=false)
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
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 startFunctional(ThreadContext *_tc, Addr &addr, unsigned &logBytes, BaseTLB::Mode mode)
The virtual address is also the physical address.
virtual bool squashed() const
This function is used by the page table walker to determine if it should translate the a pending requ...
Fault startFunctional(Addr &addr, unsigned &logBytes)
void schedule(Event &event, Tick when)
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, Mode mode)=0
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
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...
unsigned numInflight() const
bool scheduled() const
Determine if the current event is scheduled.
This is exposed globally, independent of the ISA.
Fault stepWalk(PacketPtr &write)
MemCmd cmd
The command field of the packet.
std::list< WalkerState * > currStates
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
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.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
bool isTimingMode() const
Is the system in timing mode?
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
Fault pageFault(bool present)
std::shared_ptr< FaultBase > Fault
ProbePointArg< PacketInfo > Packet
Packet probe point.
bool recvTimingResp(PacketPtr pkt)