64 #include "debug/PageTableWalker.hh" 106 return walker->recvTimingResp(pkt);
115 bool walkComplete = senderWalk->
recvPacket(pkt);
121 if (walkerState == senderWalk) {
140 walker->recvReqRetry();
150 walkerState->
retry();
174 if (if_name ==
"port")
184 assert(state == Ready);
194 unsigned num_squashed = 0;
201 DPRINTF(PageTableWalker,
"Squashing table walk for address %#x\n",
202 currState->
req->getVaddr());
206 std::make_shared<UnimpFault>(
"Squashed Inst"),
207 currState->
req, currState->
tc, currState->
mode);
234 setupWalk(req->getVaddr());
242 walker->port.sendAtomic(read);
244 fault = stepWalk(write);
245 assert(fault ==
NoFault || read == NULL);
249 walker->port.sendAtomic(write);
266 walker->port.sendFunctional(read);
270 fault = stepWalk(write);
271 assert(fault ==
NoFault || read == NULL);
275 logBytes = entry.logBytes;
284 assert(state != Ready && state != Waiting);
289 pte = read->
getLE<uint64_t>();
291 pte = read->getLE<uint32_t>();
292 VAddr
vaddr = entry.vaddr;
293 bool uncacheable = pte.pcd;
295 bool doWrite =
false;
296 bool doTLBInsert =
false;
297 bool doEndWalk =
false;
302 "Got long mode PML4 entry %#016x.\n", (uint64_t)pte);
303 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.longl3 * dataSize;
306 entry.writable = pte.w;
308 if (badNX || !pte.p) {
310 fault = pageFault(pte.p);
313 entry.noExec = pte.nx;
318 "Got long mode PDP entry %#016x.\n", (uint64_t)pte);
319 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.longl2 * dataSize;
322 entry.writable = entry.writable && pte.w;
323 entry.user = entry.user && pte.u;
324 if (badNX || !pte.p) {
326 fault = pageFault(pte.p);
333 "Got long mode PD entry %#016x.\n", (uint64_t)pte);
336 entry.writable = entry.writable && pte.w;
337 entry.user = entry.user && pte.u;
338 if (badNX || !pte.p) {
340 fault = pageFault(pte.p);
347 ((uint64_t)pte & (
mask(40) << 12)) + vaddr.longl1 * dataSize;
353 entry.paddr = (uint64_t)pte & (
mask(31) << 21);
354 entry.uncacheable = uncacheable;
355 entry.global = pte.g;
356 entry.patBit =
bits(pte, 12);
357 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
364 "Got long mode PTE entry %#016x.\n", (uint64_t)pte);
367 entry.writable = entry.writable && pte.w;
368 entry.user = entry.user && pte.u;
369 if (badNX || !pte.p) {
371 fault = pageFault(pte.p);
374 entry.paddr = (uint64_t)pte & (
mask(40) << 12);
375 entry.uncacheable = uncacheable;
376 entry.global = pte.g;
377 entry.patBit =
bits(pte, 12);
378 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
384 "Got legacy mode PAE PDP entry %#08x.\n", (uint32_t)pte);
385 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.pael2 * dataSize;
388 fault = pageFault(pte.p);
395 "Got legacy mode PAE PD entry %#08x.\n", (uint32_t)pte);
398 entry.writable = pte.w;
400 if (badNX || !pte.p) {
402 fault = pageFault(pte.p);
408 nextRead = ((uint64_t)pte & (
mask(40) << 12)) + vaddr.pael1 * dataSize;
414 entry.paddr = (uint64_t)pte & (
mask(31) << 21);
415 entry.uncacheable = uncacheable;
416 entry.global = pte.g;
417 entry.patBit =
bits(pte, 12);
418 entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
425 "Got legacy mode PAE PTE entry %#08x.\n", (uint32_t)pte);
428 entry.writable = entry.writable && pte.w;
429 entry.user = entry.user && pte.u;
430 if (badNX || !pte.p) {
432 fault = pageFault(pte.p);
435 entry.paddr = (uint64_t)pte & (
mask(40) << 12);
436 entry.uncacheable = uncacheable;
437 entry.global = pte.g;
438 entry.patBit =
bits(pte, 7);
439 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
445 "Got legacy mode PSE PD entry %#08x.\n", (uint32_t)pte);
448 entry.writable = pte.w;
452 fault = pageFault(pte.p);
459 ((uint64_t)pte & (
mask(20) << 12)) + vaddr.norml2 * dataSize;
465 entry.paddr =
bits(pte, 20, 13) << 32 |
bits(pte, 31, 22) << 22;
466 entry.uncacheable = uncacheable;
467 entry.global = pte.g;
468 entry.patBit =
bits(pte, 12);
469 entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1);
476 "Got legacy mode PD entry %#08x.\n", (uint32_t)pte);
479 entry.writable = pte.w;
483 fault = pageFault(pte.p);
488 nextRead = ((uint64_t)pte & (
mask(20) << 12)) + vaddr.norml2 * dataSize;
493 "Got legacy mode PTE entry %#08x.\n", (uint32_t)pte);
496 entry.writable = pte.w;
500 fault = pageFault(pte.p);
503 entry.paddr = (uint64_t)pte & (
mask(20) << 12);
504 entry.uncacheable = uncacheable;
505 entry.global = pte.g;
506 entry.patBit =
bits(pte, 7);
507 entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
512 panic(
"Unknown page table walker state %d!\n");
517 walker->tlb->insert(entry.vaddr, entry);
524 RequestPtr request = std::make_shared<Request>(
525 nextRead, oldRead->
getSize(), flags, walker->masterId);
532 write->
setLE<uint64_t>(pte);
562 topAddr = (cr3.longPdtb << 12) + addr.longl4 * dataSize;
570 topAddr = (cr3.paePdtb << 5) + addr.pael3 * dataSize;
574 topAddr = (cr3.pdtb << 12) + addr.norml2 * dataSize;
593 RequestPtr request = std::make_shared<Request>(
594 topAddr, dataSize, flags, walker->masterId);
605 assert(state == Waiting);
610 return (inflight == 0);
623 timingFault = stepWalk(write);
625 assert(timingFault ==
NoFault || read == NULL);
627 writes.push_back(write);
633 if (inflight == 0 && read == NULL && writes.size() == 0) {
644 bool delayedResponse;
645 Fault fault = walker->tlb->translate(req, tc, NULL,
mode,
646 delayedResponse,
true);
647 assert(!delayedResponse);
649 translation->finish(fault, req, tc,
mode);
652 translation->finish(timingFault, req, tc,
mode);
672 if (!walker->sendTiming(
this, pkt)) {
680 while (writes.size()) {
684 if (!walker->sendTiming(
this, write)) {
686 writes.push_back(write);
733 DPRINTF(PageTableWalker,
"Raising page fault.\n");
737 return std::make_shared<PageFault>(entry.vaddr,
present,
mode,
738 m5reg.cpl == 3,
false);
744 X86PagetableWalkerParams::create()
void setupWalk(Addr vaddr)
#define panic(...)
This implements a cprintf based panic() function.
The request is to an uncacheable address.
Ports are used to interface objects to each other.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
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.
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)
bool scheduled() const
Determine if the current event is scheduled.
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)
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)
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
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.
void schedule(Event &event, Tick when)
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...
The virtual address is also the physical address.
Fault pageFault(bool present)
std::shared_ptr< FaultBase > Fault
ProbePointArg< PacketInfo > Packet
Packet probe point.
bool recvTimingResp(PacketPtr pkt)