Go to the documentation of this file.
52 #include "debug/GPUPrefetch.hh"
53 #include "debug/GPUTLB.hh"
69 exitEvent([
this]{ exitCallback(); },
name()), stats(
this)
83 for (
int set = 0; set <
numSets; ++set) {
84 for (
int way = 0; way <
assoc; ++way) {
107 cprintf(
"Forcing maxCoalescedReqs to %d (TLB assoc.) \n",
assoc);
116 for (
size_t i = 0;
i <
p.port_cpu_side_ports_connection_count; ++
i) {
122 for (
size_t i = 0;
i <
p.port_mem_side_ports_connection_count; ++
i) {
138 if (if_name ==
"cpu_side_ports") {
140 panic(
"TLBCoalescer::getPort: unknown index %d\n", idx);
144 }
else if (if_name ==
"mem_side_ports") {
146 panic(
"TLBCoalescer::getPort: unknown index %d\n", idx);
153 panic(
"TLBCoalescer::getPort: unknown port %s\n", if_name);
177 newEntry->
vaddr = vpn;
183 GpuTLB::EntryList::iterator
193 for (; entry !=
entryList[set].end(); ++entry) {
194 int page_size = (*entry)->size();
196 if ((*entry)->vaddr <=
va && (*entry)->vaddr + page_size >
va) {
197 DPRINTF(GPUTLB,
"Matched vaddr %#x to entry starting at %#x "
198 "with size %#x.\n",
va, (*entry)->vaddr, page_size);
229 DPRINTF(GPUTLB,
"Invalidating all entries.\n");
249 DPRINTF(GPUTLB,
"Invalidating all non global entries.\n");
254 if (!(*entryIt)->global) {
302 DPRINTF(GPUTLB,
"Addresses references internal memory.\n");
307 panic(
"CPUID memory space not yet implemented!\n");
313 return std::make_shared<GeneralProtection>(0);
315 req->setLocalAccessor(
318 return localMiscRegAccess(read, regNum, tc, pkt);
330 assert(!(IOPort & ~0xFFFF));
331 if (IOPort == 0xCF8 && req->getSize() == 4) {
332 req->setLocalAccessor(
335 return localMiscRegAccess(
339 }
else if ((IOPort & ~
mask(2)) == 0xCFC) {
356 panic(
"Access to unrecognized internal address space %#x.\n",
372 bool tlb_hit =
false;
374 uint32_t flags = req->getFlags();
384 DPRINTF(GPUTLB,
"In protected mode.\n");
386 assert(m5Reg.mode == LongMode);
390 DPRINTF(GPUTLB,
"Paging enabled.\n");
420 bool &delayedResponse,
bool timing,
int &latency)
422 uint32_t flags = req->getFlags();
432 delayedResponse =
false;
440 DPRINTF(GPUTLB,
"In protected mode.\n");
442 if (m5Reg.mode != LongMode) {
443 DPRINTF(GPUTLB,
"Not in long mode. Checking segment "
450 return std::make_shared<GeneralProtection>(0);
459 return std::make_shared<GeneralProtection>(0);
462 return std::make_shared<GeneralProtection>(0);
476 if ((csAttr.defaultSize && sizeOverride) ||
477 (!csAttr.defaultSize && !sizeOverride)) {
485 DPRINTF(GPUTLB,
"Checking an expand down segment.\n");
486 warn_once(
"Expand down segments are untested.\n");
489 return std::make_shared<GeneralProtection>(0);
492 return std::make_shared<GeneralProtection>(0);
498 DPRINTF(GPUTLB,
"Paging enabled.\n");
510 fatal(
"GpuTLB doesn't support full-system mode\n");
512 DPRINTF(GPUTLB,
"Handling a TLB miss for address %#x "
513 "at pc %#x.\n",
vaddr,
526 pte =
p->pTable->lookup(
vaddr);
530 return std::make_shared<PageFault>(
vaddr,
true,
534 Addr alignedVaddr =
p->pTable->pageAlign(
vaddr);
536 DPRINTF(GPUTLB,
"Mapping %#x to %#x\n",
537 alignedVaddr, pte->
paddr);
539 TlbEntry gpuEntry(
p->pid(), alignedVaddr,
540 pte->
paddr,
false,
false);
541 entry =
insert(alignedVaddr, gpuEntry);
544 DPRINTF(GPUTLB,
"Miss was serviced.\n");
555 bool inUser = (m5Reg.cpl == 3 &&
559 bool badWrite = (!entry->
writable && (inUser || cr0.wp));
566 return std::make_shared<PageFault>(
vaddr,
true,
mode,
570 if (storeCheck && badWrite) {
573 return std::make_shared<PageFault>(
vaddr,
true,
579 DPRINTF(GPUTLB,
"Entry found with paddr %#x, doing protection "
580 "checks.\n", entry->
paddr);
582 int page_size = entry->
size();
584 DPRINTF(GPUTLB,
"Translated %#x -> %#x.\n",
vaddr, paddr);
585 req->setPaddr(paddr);
591 DPRINTF(GPUTLB,
"Paging disabled.\n");
593 req->setPaddr(
vaddr);
597 DPRINTF(GPUTLB,
"In real mode.\n");
599 req->setPaddr(
vaddr);
604 LocalApicBase localApicBase =
608 Addr paddr = req->getPaddr();
610 if (baseAddr <= paddr && baseAddr + PageBytes > paddr) {
625 bool delayedResponse;
635 bool delayedResponse;
639 delayedResponse,
true, latency);
641 if (!delayedResponse)
679 bool update_stats = !sender_state->
isPrefetch;
682 DPRINTF(GPUTLB,
"Translation req. for virt. page addr %#x\n",
685 int req_cnt = sender_state->
reqCnt.back();
698 bool success =
tlbLookup(tmp_req, tmp_tc, update_stats);
732 new TLBEvent(
this, virt_page_addr, lookup_outcome, pkt);
735 panic(
"Virtual Page Address %#x already has a return event\n",
742 DPRINTF(GPUTLB,
"schedule translationReturnEvent @ curTick %d\n",
750 :
Event(CPU_Tick_Pri),
tlb(_tlb), virtPageAddr(_addr),
751 outcome(tlb_outcome), pkt(_pkt)
764 uint32_t flags = pkt->
req->getFlags();
772 bool badWrite = (!tlb_entry->
writable && (inUser || cr0.wp));
774 if ((inUser && !tlb_entry->
user) ||
779 panic(
"Page fault detected");
782 if (storeCheck && badWrite) {
785 panic(
"Page fault detected");
810 DPRINTF(GPUTLB,
"Translation Done - TLB Hit for addr %#x\n",
812 local_entry = sender_state->
tlbEntry;
814 DPRINTF(GPUTLB,
"Translation Done - TLB Miss for addr %#x\n",
824 local_entry = new_entry;
827 DPRINTF(GPUTLB,
"allocating entry w/ addr %#x\n",
830 local_entry =
insert(virt_page_addr, *new_entry);
841 DPRINTF(GPUTLB,
"Entry found with vaddr %#x, doing protection checks "
842 "while paddr was %#x.\n", local_entry->
vaddr,
846 int page_size = local_entry->
size();
848 DPRINTF(GPUTLB,
"Translated %#x -> %#x.\n",
vaddr, paddr);
856 pkt->
req->setPaddr(paddr);
885 DPRINTF(GPUTLB,
"Triggered TLBEvent for addr %#x\n", virtPageAddr);
893 int req_cnt = tmp_sender_state->
reqCnt.back();
894 bool update_stats = !tmp_sender_state->
isPrefetch;
907 DPRINTF(GPUTLB,
"This is a TLB miss\n");
928 DPRINTF(GPUTLB,
"Failed sending translation request to "
929 "lower level TLB for addr %#x\n", virtPageAddr);
933 DPRINTF(GPUTLB,
"Sent translation request to lower level "
934 "TLB for addr %#x\n", virtPageAddr);
938 DPRINTF(GPUTLB,
"Last level TLB - start a page walk for "
939 "addr %#x\n", virtPageAddr);
955 DPRINTF(GPUTLB,
"Doing a page walk for address %#x\n",
964 Addr alignedVaddr =
p->pTable->pageAlign(
vaddr);
965 assert(alignedVaddr == virtPageAddr);
970 pte =
p->pTable->lookup(
vaddr);
974 DPRINTF(GPUTLB,
"Mapping %#x to %#x\n", alignedVaddr,
991 panic(
"Unexpected TLB outcome %d", outcome);
998 tlb->translationReturn(virtPageAddr, outcome, pkt);
1004 return "trigger translationDoneEvent";
1016 return virtPageAddr;
1028 if (
tlb->outstandingReqs <
tlb->maxCoalescedReqs) {
1029 tlb->issueTLBLookup(pkt);
1031 tlb->outstandingReqs++;
1034 DPRINTF(GPUTLB,
"Reached maxCoalescedReqs number %d\n",
1035 tlb->outstandingReqs);
1061 DPRINTF(GPUTLB,
"Functional Translation Done - TLB hit for addr "
1064 local_entry = sender_state->
tlbEntry;
1066 DPRINTF(GPUTLB,
"Functional Translation Done - TLB miss for addr "
1074 new_entry = sender_state->
tlbEntry;
1076 local_entry = new_entry;
1081 DPRINTF(GPUTLB,
"allocating entry w/ addr %#x\n",
1084 local_entry =
insert(virt_page_addr, *new_entry);
1087 assert(local_entry);
1090 DPRINTF(GPUTLB,
"Entry found with vaddr %#x, doing protection checks "
1091 "while paddr was %#x.\n", local_entry->
vaddr,
1092 local_entry->
paddr);
1108 int page_size = local_entry->
size();
1110 DPRINTF(GPUTLB,
"Translated %#x -> %#x.\n",
vaddr, paddr);
1112 pkt->
req->setPaddr(paddr);
1127 bool update_stats = !sender_state->
isPrefetch;
1133 tlb->updatePageFootprint(virt_page_addr);
1136 bool success =
tlb->tlbLookup(pkt->
req, tc, update_stats);
1142 tlb->stats.globalNumTLBAccesses++;
1146 tlb->stats.globalNumTLBHits++;
1152 tlb->stats.globalNumTLBMisses++;
1153 if (
tlb->hasMemSidePort) {
1155 tlb->memSidePort[0]->sendFunctional(pkt);
1161 DPRINTF(GPUTLB,
"Doing a page walk for address %#x\n",
1168 Addr alignedVaddr =
p->pTable->pageAlign(
vaddr);
1169 assert(alignedVaddr == virt_page_addr);
1172 p->pTable->lookup(
vaddr);
1175 pte =
p->pTable->lookup(
vaddr);
1183 DPRINTF(GPUTLB,
"Mapping %#x to %#x\n", alignedVaddr,
1188 pte->
paddr,
false,
false);
1195 DPRINTF(GPUTLB,
"Mapping %#x to %#x\n", alignedVaddr,
1200 pte->
paddr,
false,
false);
1202 DPRINTF(GPUPrefetch,
"Prefetch failed %#x\n",
1212 DPRINTF(GPUPrefetch,
"Functional Hit for vaddr %#x\n",
1213 tlb->lookup(pkt->
req->getVaddr()));
1229 tlb->handleFuncTranslationReturn(pkt, tlb_outcome);
1237 panic(
"recvReqRetry called");
1260 DPRINTF(GPUTLB,
"MemSidePort recvTiming for virt_page_addr %#x\n",
1263 TLBEvent *tlb_event =
tlb->translationReturnEvent[virt_page_addr];
1278 panic(
"recvReqRetry called");
1290 delete old_tlb_event;
1319 AccessPatternTable::value_type(virt_page_addr, tmp_access_info));
1321 bool first_page_access = ret.second;
1323 if (first_page_access) {
1326 int accessed_before;
1327 accessed_before =
curTick() - ret.first->second.lastTimeAccessed;
1328 ret.first->second.totalReuseDistance += accessed_before;
1331 ret.first->second.accessesPerPage++;
1332 ret.first->second.lastTimeAccessed =
curTick();
1335 ret.first->second.localTLBAccesses
1343 std::ostream *page_stat_file =
nullptr;
1354 <<
"page,max_access_distance,mean_access_distance, "
1355 <<
"stddev_distance" << std::endl;
1359 unsigned int sum_avg_reuse_distance_per_page = 0;
1363 sum_avg_reuse_distance_per_page += iter.second.totalReuseDistance /
1364 iter.second.accessesPerPage;
1367 unsigned int tmp = iter.second.localTLBAccesses[0];
1368 unsigned int prev = tmp;
1370 for (
int i = 0;
i < iter.second.localTLBAccesses.size(); ++
i) {
1375 prev = iter.second.localTLBAccesses[
i];
1378 iter.second.localTLBAccesses[
i] -= tmp;
1381 iter.second.sumDistance +=
1382 iter.second.localTLBAccesses[
i];
1385 iter.second.meanDistance =
1386 iter.second.sumDistance / iter.second.accessesPerPage;
1390 unsigned int max_distance = 0;
1391 unsigned int stddev_distance = 0;
1393 for (
int i = 0;
i < iter.second.localTLBAccesses.size(); ++
i) {
1394 unsigned int tmp_access_distance =
1395 iter.second.localTLBAccesses[
i];
1397 if (tmp_access_distance > max_distance) {
1398 max_distance = tmp_access_distance;
1402 tmp_access_distance - iter.second.meanDistance;
1403 stddev_distance += pow(diff, 2);
1408 sqrt(stddev_distance/iter.second.accessesPerPage);
1410 if (page_stat_file) {
1411 *page_stat_file << std::hex << iter.first <<
",";
1412 *page_stat_file << std::dec << max_distance <<
",";
1413 *page_stat_file << std::dec << iter.second.meanDistance
1415 *page_stat_file << std::dec << stddev_distance;
1416 *page_stat_file << std::endl;
1420 iter.second.localTLBAccesses.clear();
1434 : statistics::
Group(parent),
1435 ADD_STAT(localNumTLBAccesses,
"Number of TLB accesses"),
1436 ADD_STAT(localNumTLBHits,
"Number of TLB hits"),
1437 ADD_STAT(localNumTLBMisses,
"Number of TLB misses"),
1438 ADD_STAT(localTLBMissRate,
"TLB miss rate"),
1439 ADD_STAT(globalNumTLBAccesses,
"Number of TLB accesses"),
1440 ADD_STAT(globalNumTLBHits,
"Number of TLB hits"),
1441 ADD_STAT(globalNumTLBMisses,
"Number of TLB misses"),
1442 ADD_STAT(globalTLBMissRate,
"TLB miss rate"),
1443 ADD_STAT(accessCycles,
"Cycles spent accessing this TLB level"),
1444 ADD_STAT(pageTableCycles,
"Cycles spent accessing the page table"),
1445 ADD_STAT(numUniquePages,
"Number of unique pages touched"),
1446 ADD_STAT(localCycles,
"Number of cycles spent in queue for all "
1448 ADD_STAT(localLatency,
"Avg. latency over incoming coalesced reqs"),
1449 ADD_STAT(avgReuseDistance,
"avg. reuse distance over all pages (in "
Tick curTick()
The universal simulation clock.
#define fatal(...)
This implements a cprintf based fatal() function.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
statistics::Scalar numUniquePages
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
static MiscRegIndex MISCREG_SEG_SEL(int index)
constexpr decltype(nullptr) NoFault
GpuTLBStats(statistics::Group *parent)
statistics::Scalar accessCycles
void cprintf(const char *format, const Args &...args)
virtual void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
void translationReturn(Addr virtPageAddr, tlbOutcome outcome, PacketPtr pkt)
A TLBEvent is scheduled after the TLB lookup and helps us take the appropriate actions: (e....
gem5::X86ISA::GpuTLB::GpuTLBStats stats
std::vector< MemSidePort * > memSidePort
statistics::Scalar avgReuseDistance
static Addr x86LocalAPICAddress(const uint8_t id, const uint16_t addr)
const Addr IntAddrPrefixMSR
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
statistics::Scalar localNumTLBAccesses
static MiscRegIndex MISCREG_SEG_LIMIT(int index)
RequestPtr req
A pointer to the original request.
const Request::FlagsType SegmentFlagMask
virtual const PCStateBase & pcState() const =0
static MiscRegIndex MISCREG_SEG_ATTR(int index)
unsigned int totalReuseDistance
statistics::Formula localTLBMissRate
virtual ContextID contextId() const =0
void schedule(Event &event, Tick when)
OutputStream * create(const std::string &name, bool binary=false, bool no_gz=false)
Creates a file in this directory (optionally compressed).
TlbEntry * lookup(Addr va, bool update_lru=true)
std::string csprintf(const char *format, const Args &...args)
BitfieldType< SegDescriptorLimit > limit
statistics::Formula globalTLBMissRate
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
bool FA
true if this is a fully-associative TLB
TlbEntry * insert(Addr vpn, TlbEntry &entry)
statistics::Scalar globalNumTLBAccesses
EntryList::iterator lookupIt(Addr va, bool update_lru=true)
unsigned int lastTimeAccessed
bool allocationPolicy
Allocation Policy: true if we always allocate on a hit, false otherwise.
void setConfigAddress(uint32_t addr)
virtual void finish(Fault fault, const RequestPtr &req, ThreadContext *tc, Mode mode)=0
The memory for this object may be dynamically allocated, and it may be responsible for cleaning itsle...
bool hasMemSidePort
if true, then this is not the last level TLB
statistics::Formula localLatency
std::queue< Addr > cleanupQueue
Cycles is a wrapper class for representing cycle counts, i.e.
virtual AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
Fault translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode, int &latency)
virtual void serialize(CheckpointOut &cp) const override
Serialize an object.
TLB TranslationState: this currently is a somewhat bastardization of the usage of SenderState,...
std::ostream * stream() const
Get the output underlying output stream.
Fault translate(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode, bool &delayedResponse, bool timing, int &latency)
bool accessDistance
Print out accessDistance stats.
virtual void unserialize(CheckpointIn &cp) override
Unserialize an object.
void handleFuncTranslationReturn(PacketPtr pkt, tlbOutcome outcome)
handleFuncTranslationReturn is called on a TLB hit, when a TLB miss returns or when a page fault retu...
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual std::string name() const
void issueTLBLookup(PacketPtr pkt)
Do the TLB lookup for this coalesced request and schedule another event <TLB access latency> cycles l...
std::shared_ptr< FaultBase > Fault
Tick cyclesToTicks(Cycles c) const
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void updatePageFootprint(Addr virt_page_addr)
static const Priority Maximum_Pri
Maximum priority.
Fault translateInt(bool read, const RequestPtr &req, ThreadContext *tc)
std::shared_ptr< Request > RequestPtr
const Addr IntAddrPrefixMask
bool tlbLookup(const RequestPtr &req, ThreadContext *tc, bool update_stats)
TLB_lookup will only perform a TLB lookup returning true on a TLB hit and false on a TLB miss.
@ MISCREG_PCI_CONFIG_ADDRESS
unsigned int accessesPerPage
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
const Addr IntAddrPrefixCPUID
static MiscRegIndex MISCREG_SEG_BASE(int index)
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
statistics::Scalar globalNumTLBMisses
std::unordered_map< Addr, TLBEvent * > translationReturnEvent
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
statistics::Scalar pageTableCycles
virtual void recvReqRetry()
std::vector< EntryList > freeList
const Addr PhysAddrPrefixPciConfig
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
SenderState * senderState
This packet's sender state.
statistics::Scalar localNumTLBHits
bool msrAddrToIndex(MiscRegIndex ®Num, Addr addr)
Find and return the misc reg corresponding to an MSR address.
std::vector< CpuSidePort * > cpuSidePort
void invalidateNonGlobal()
const std::string & name()
Bitfield< 14 > expandDown
statistics::Scalar localCycles
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
AccessPatternTable TLBFootprint
std::vector< EntryList > entryList
An entryList per set is the equivalent of an LRU stack; it's used to guide replacement decisions.
virtual bool recvTimingResp(PacketPtr pkt)
MemSidePort receives the packet back.
virtual Process * getProcessPtr()=0
@ READ_MODIFY_WRITE
This request is a read which will be followed by a write.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
const char * description() const
Return a C string describing the event.
void makeTimingResponse()
@ STRICT_ORDER
The request is required to be strictly ordered by CPU models and is non-speculative.
TLBEvent(GpuTLB *_tlb, Addr _addr, tlbOutcome outcome, PacketPtr _pkt)
void updateOutcome(tlbOutcome _outcome)
Ports are used to interface objects to each other.
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
void pagingProtectionChecks(ThreadContext *tc, PacketPtr pkt, TlbEntry *tlb_entry, Mode mode)
Do Paging protection checks.
@ UNCACHEABLE
The request is to an uncacheable address.
unsigned int meanDistance
std::ostream CheckpointOut
const Addr IntAddrPrefixIO
This hash map will use the virtual page address as a key and will keep track of total number of acces...
std::vector< TlbEntry > tlb
statistics::Scalar globalNumTLBHits
virtual bool recvTimingReq(PacketPtr pkt)
recvTiming receives a coalesced timing request from a TLBCoalescer and it calls issueTLBLookup() It o...
void translateTiming(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode, int &latency)
void handleTranslationReturn(Addr addr, tlbOutcome outcome, PacketPtr pkt)
handleTranslationReturn is called on a TLB hit, when a TLB miss returns or when a page fault returns.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
virtual void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
std::vector< int > reqCnt
void demapPage(Addr va, uint64_t asn)
statistics::Scalar localNumTLBMisses
const Addr PhysAddrPrefixIO
bool scheduled() const
Determine if the current event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
EventFunctionWrapper cleanupEvent
Counter value() const
Return the current value of this stat as its base type.
Generated on Wed May 4 2022 12:13:35 for gem5 by doxygen 1.8.17