sim: Include some required headers in the syscall debug macros header.
[gem5.git] / src / gpu-compute / gpu_tlb.cc
index b5411f82c01a3a0571408f652f245820384604ab..cfde2ccc31bd26969fec349c0ae98531ac2b38ac 100644 (file)
@@ -45,6 +45,7 @@
 #include "arch/x86/regs/misc.hh"
 #include "arch/x86/x86_traits.hh"
 #include "base/bitfield.hh"
+#include "base/logging.hh"
 #include "base/output.hh"
 #include "base/trace.hh"
 #include "cpu/base.hh"
@@ -60,7 +61,7 @@ namespace X86ISA
 {
 
     GpuTLB::GpuTLB(const Params *p)
-        : MemObject(p), configAddress(0), size(p->size),
+        : ClockedObject(p), configAddress(0), size(p->size),
           cleanupEvent([this]{ cleanup(); }, name(), false,
                        Event::Maximum_Pri),
           exitEvent([this]{ exitCallback(); }, name())
@@ -73,7 +74,7 @@ namespace X86ISA
         accessDistance = p->accessDistance;
         clock = p->clk_domain->clockPeriod();
 
-        tlb.assign(size, GpuTlbEntry());
+        tlb.assign(size, TlbEntry());
 
         freeList.resize(numSets);
         entryList.resize(numSets);
@@ -97,12 +98,6 @@ namespace X86ISA
          */
         setMask = numSets - 1;
 
-    #if 0
-        // GpuTLB doesn't yet support full system
-        walker = p->walker;
-        walker->setTLB(this);
-    #endif
-
         maxCoalescedReqs = p->maxOutstandingReqs;
 
         // Do not allow maxCoalescedReqs to be more than the TLB associativity
@@ -136,40 +131,32 @@ namespace X86ISA
         assert(translationReturnEvent.empty());
     }
 
-    BaseSlavePort&
-    GpuTLB::getSlavePort(const std::string &if_name, PortID idx)
+    Port &
+    GpuTLB::getPort(const std::string &if_name, PortID idx)
     {
         if (if_name == "slave") {
             if (idx >= static_cast<PortID>(cpuSidePort.size())) {
-                panic("TLBCoalescer::getSlavePort: unknown index %d\n", idx);
+                panic("TLBCoalescer::getPort: unknown index %d\n", idx);
             }
 
             return *cpuSidePort[idx];
-        } else {
-            panic("TLBCoalescer::getSlavePort: unknown port %s\n", if_name);
-        }
-    }
-
-    BaseMasterPort&
-    GpuTLB::getMasterPort(const std::string &if_name, PortID idx)
-    {
-        if (if_name == "master") {
+        } else if (if_name == "master") {
             if (idx >= static_cast<PortID>(memSidePort.size())) {
-                panic("TLBCoalescer::getMasterPort: unknown index %d\n", idx);
+                panic("TLBCoalescer::getPort: unknown index %d\n", idx);
             }
 
             hasMemSidePort = true;
 
             return *memSidePort[idx];
         } else {
-            panic("TLBCoalescer::getMasterPort: unknown port %s\n", if_name);
+            panic("TLBCoalescer::getPort: unknown port %s\n", if_name);
         }
     }
 
-    GpuTlbEntry*
-    GpuTLB::insert(Addr vpn, GpuTlbEntry &entry)
+    TlbEntry*
+    GpuTLB::insert(Addr vpn, TlbEntry &entry)
     {
-        GpuTlbEntry *newEntry = nullptr;
+        TlbEntry *newEntry = nullptr;
 
         /**
          * vpn holds the virtual page address
@@ -222,7 +209,7 @@ namespace X86ISA
         return entry;
     }
 
-    GpuTlbEntry*
+    TlbEntry*
     GpuTLB::lookup(Addr va, bool update_lru)
     {
         int set = (va >> TheISA::PageShift) & setMask;
@@ -242,7 +229,7 @@ namespace X86ISA
 
         for (int i = 0; i < numSets; ++i) {
             while (!entryList[i].empty()) {
-                GpuTlbEntry *entry = entryList[i].front();
+                TlbEntry *entry = entryList[i].front();
                 entryList[i].pop_front();
                 freeList[i].push_back(entry);
             }
@@ -287,7 +274,7 @@ namespace X86ISA
     }
 
     Fault
-    GpuTLB::translateInt(RequestPtr req, ThreadContext *tc)
+    GpuTLB::translateInt(const RequestPtr &req, ThreadContext *tc)
     {
         DPRINTF(GPUTLB, "Addresses references internal memory.\n");
         Addr vaddr = req->getVaddr();
@@ -616,7 +603,7 @@ namespace X86ISA
             //The index is multiplied by the size of a MiscReg so that
             //any memory dependence calculations will not see these as
             //overlapping.
-            req->setPaddr(regNum * sizeof(MiscReg));
+            req->setPaddr(regNum * sizeof(RegVal));
             return NoFault;
         } else if (prefix == IntAddrPrefixIO) {
             // TODO If CPL > IOPL or in virtual mode, check the I/O permission
@@ -629,7 +616,7 @@ namespace X86ISA
 
             if (IOPort == 0xCF8 && req->getSize() == 4) {
                 req->setFlags(Request::MMAPPED_IPR);
-                req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(MiscReg));
+                req->setPaddr(MISCREG_PCI_CONFIG_ADDRESS * sizeof(RegVal));
             } else if ((IOPort & ~mask(2)) == 0xCFC) {
                 req->setFlags(Request::UNCACHEABLE);
 
@@ -662,7 +649,8 @@ namespace X86ISA
      * On a hit it will update the LRU stack.
      */
     bool
-    GpuTLB::tlbLookup(RequestPtr req, ThreadContext *tc, bool update_stats)
+    GpuTLB::tlbLookup(const RequestPtr &req,
+                      ThreadContext *tc, bool update_stats)
     {
         bool tlb_hit = false;
     #ifndef NDEBUG
@@ -684,7 +672,7 @@ namespace X86ISA
             if (m5Reg.paging) {
                 DPRINTF(GPUTLB, "Paging enabled.\n");
                 //update LRU stack on a hit
-                GpuTlbEntry *entry = lookup(vaddr, true);
+                TlbEntry *entry = lookup(vaddr, true);
 
                 if (entry)
                     tlb_hit = true;
@@ -710,7 +698,7 @@ namespace X86ISA
     }
 
     Fault
-    GpuTLB::translate(RequestPtr req, ThreadContext *tc,
+    GpuTLB::translate(const RequestPtr &req, ThreadContext *tc,
                       Translation *translation, Mode mode,
                       bool &delayedResponse, bool timing, int &latency)
     {
@@ -792,7 +780,7 @@ namespace X86ISA
             if (m5Reg.paging) {
                 DPRINTF(GPUTLB, "Paging enabled.\n");
                 // The vaddr already has the segment base applied.
-                GpuTlbEntry *entry = lookup(vaddr);
+                TlbEntry *entry = lookup(vaddr);
                 localNumTLBAccesses++;
 
                 if (!entry) {
@@ -808,31 +796,31 @@ namespace X86ISA
                                 "at pc %#x.\n", vaddr, tc->instAddr());
 
                         Process *p = tc->getProcessPtr();
-                        GpuTlbEntry newEntry;
-                        bool success = p->pTable->lookup(vaddr, newEntry);
+                        const EmulationPageTable::Entry *pte =
+                            p->pTable->lookup(vaddr);
 
-                        if (!success && mode != BaseTLB::Execute) {
+                        if (!pte && mode != BaseTLB::Execute) {
                             // penalize a "page fault" more
-                            if (timing) {
+                            if (timing)
                                 latency += missLatency2;
-                            }
 
                             if (p->fixupStackFault(vaddr))
-                                success = p->pTable->lookup(vaddr, newEntry);
+                                pte = p->pTable->lookup(vaddr);
                         }
 
-                        if (!success) {
+                        if (!pte) {
                             return std::make_shared<PageFault>(vaddr, true,
                                                                mode, true,
                                                                false);
                         } else {
-                            newEntry.valid = success;
                             Addr alignedVaddr = p->pTable->pageAlign(vaddr);
 
                             DPRINTF(GPUTLB, "Mapping %#x to %#x\n",
-                                    alignedVaddr, newEntry.pageStart());
+                                    alignedVaddr, pte->paddr);
 
-                            entry = insert(alignedVaddr, newEntry);
+                            TlbEntry gpuEntry(p->pid(), alignedVaddr,
+                                              pte->paddr, false, false);
+                            entry = insert(alignedVaddr, gpuEntry);
                         }
 
                         DPRINTF(GPUTLB, "Miss was serviced.\n");
@@ -913,8 +901,8 @@ namespace X86ISA
     };
 
     Fault
-    GpuTLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode,
-                            int &latency)
+    GpuTLB::translateAtomic(const RequestPtr &req, ThreadContext *tc,
+                            Mode mode, int &latency)
     {
         bool delayedResponse;
 
@@ -923,7 +911,7 @@ namespace X86ISA
     }
 
     void
-    GpuTLB::translateTiming(RequestPtr req, ThreadContext *tc,
+    GpuTLB::translateTiming(const RequestPtr &req, ThreadContext *tc,
             Translation *translation, Mode mode, int &latency)
     {
         bool delayedResponse;
@@ -956,7 +944,7 @@ namespace X86ISA
     void
     GpuTLB::regStats()
     {
-        MemObject::regStats();
+        ClockedObject::regStats();
 
         localNumTLBAccesses
             .name(name() + ".local_TLB_accesses")
@@ -1069,7 +1057,7 @@ namespace X86ISA
         }
 
         tlbOutcome lookup_outcome = TLB_MISS;
-        RequestPtr tmp_req = pkt->req;
+        const RequestPtr &tmp_req = pkt->req;
 
         // Access the TLB and figure out if it's a hit or a miss.
         bool success = tlbLookup(tmp_req, tmp_tc, update_stats);
@@ -1077,11 +1065,13 @@ namespace X86ISA
         if (success) {
             lookup_outcome = TLB_HIT;
             // Put the entry in SenderState
-            GpuTlbEntry *entry = lookup(tmp_req->getVaddr(), false);
+            TlbEntry *entry = lookup(tmp_req->getVaddr(), false);
             assert(entry);
 
+            auto p = sender_state->tc->getProcessPtr();
             sender_state->tlbEntry =
-                new GpuTlbEntry(0, entry->vaddr, entry->paddr, entry->valid);
+                new TlbEntry(p->pid(), entry->vaddr, entry->paddr,
+                             false, false);
 
             if (update_stats) {
                 // the reqCnt has an entry per level, so its size tells us
@@ -1133,7 +1123,7 @@ namespace X86ISA
      */
     void
     GpuTLB::pagingProtectionChecks(ThreadContext *tc, PacketPtr pkt,
-            GpuTlbEntry * tlb_entry, Mode mode)
+            TlbEntry * tlb_entry, Mode mode)
     {
         HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
         uint32_t flags = pkt->req->getFlags();
@@ -1147,16 +1137,16 @@ namespace X86ISA
 
         if ((inUser && !tlb_entry->user) ||
             (mode == BaseTLB::Write && badWrite)) {
-           // The page must have been present to get into the TLB in
-           // the first place. We'll assume the reserved bits are
-           // fine even though we're not checking them.
-           assert(false);
+            // The page must have been present to get into the TLB in
+            // the first place. We'll assume the reserved bits are
+            // fine even though we're not checking them.
+            panic("Page fault detected");
         }
 
         if (storeCheck && badWrite) {
-           // This would fault if this were a write, so return a page
-           // fault that reflects that happening.
-           assert(false);
+            // This would fault if this were a write, so return a page
+            // fault that reflects that happening.
+            panic("Page fault detected");
         }
     }
 
@@ -1179,7 +1169,7 @@ namespace X86ISA
         ThreadContext *tc = sender_state->tc;
         Mode mode = sender_state->tlbMode;
 
-        GpuTlbEntry *local_entry, *new_entry;
+        TlbEntry *local_entry, *new_entry;
 
         if (tlb_outcome == TLB_HIT) {
             DPRINTF(GPUTLB, "Translation Done - TLB Hit for addr %#x\n", vaddr);
@@ -1330,25 +1320,27 @@ namespace X86ISA
                 safe_cast<TranslationState*>(pkt->senderState);
 
             Process *p = sender_state->tc->getProcessPtr();
-            TlbEntry newEntry;
             Addr vaddr = pkt->req->getVaddr();
     #ifndef NDEBUG
             Addr alignedVaddr = p->pTable->pageAlign(vaddr);
             assert(alignedVaddr == virtPageAddr);
     #endif
-            bool success;
-            success = p->pTable->lookup(vaddr, newEntry);
-            if (!success && sender_state->tlbMode != BaseTLB::Execute) {
-                if (p->fixupStackFault(vaddr)) {
-                    success = p->pTable->lookup(vaddr, newEntry);
-                }
+            const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
+            if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
+                    p->fixupStackFault(vaddr)) {
+                pte = p->pTable->lookup(vaddr);
             }
 
-            DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
-                    newEntry.pageStart());
+            if (pte) {
+                DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
+                        pte->paddr);
 
-            sender_state->tlbEntry =
-                new GpuTlbEntry(0, newEntry.vaddr, newEntry.paddr, success);
+                sender_state->tlbEntry =
+                    new TlbEntry(p->pid(), virtPageAddr, pte->paddr, false,
+                                 false);
+            } else {
+                sender_state->tlbEntry = nullptr;
+            }
 
             handleTranslationReturn(virtPageAddr, TLB_MISS, pkt);
         } else if (outcome == MISS_RETURN) {
@@ -1357,7 +1349,7 @@ namespace X86ISA
              */
             handleTranslationReturn(virtPageAddr, TLB_MISS, pkt);
         } else {
-            assert(false);
+            panic("Unexpected TLB outcome %d", outcome);
         }
     }
 
@@ -1424,7 +1416,7 @@ namespace X86ISA
         Mode mode = sender_state->tlbMode;
         Addr vaddr = pkt->req->getVaddr();
 
-        GpuTlbEntry *local_entry, *new_entry;
+        TlbEntry *local_entry, *new_entry;
 
         if (tlb_outcome == TLB_HIT) {
             DPRINTF(GPUTLB, "Functional Translation Done - TLB hit for addr "
@@ -1458,13 +1450,18 @@ namespace X86ISA
                 "while paddr was %#x.\n", local_entry->vaddr,
                 local_entry->paddr);
 
-        // Do paging checks if it's a normal functional access.  If it's for a
-        // prefetch, then sometimes you can try to prefetch something that won't
-        // pass protection. We don't actually want to fault becuase there is no
-        // demand access to deem this a violation.  Just put it in the TLB and
-        // it will fault if indeed a future demand access touches it in
-        // violation.
-        if (!sender_state->prefetch && sender_state->tlbEntry->valid)
+        /**
+         * Do paging checks if it's a normal functional access.  If it's for a
+         * prefetch, then sometimes you can try to prefetch something that
+         * won't pass protection. We don't actually want to fault becuase there
+         * is no demand access to deem this a violation.  Just put it in the
+         * TLB and it will fault if indeed a future demand access touches it in
+         * violation.
+         *
+         * This feature could be used to explore security issues around
+         * speculative memory accesses.
+         */
+        if (!sender_state->prefetch && sender_state->tlbEntry)
             pagingProtectionChecks(tc, pkt, local_entry, mode);
 
         int page_size = local_entry->size();
@@ -1524,7 +1521,6 @@ namespace X86ISA
                         virt_page_addr);
 
                 Process *p = tc->getProcessPtr();
-                TlbEntry newEntry;
 
                 Addr vaddr = pkt->req->getVaddr();
     #ifndef NDEBUG
@@ -1532,41 +1528,41 @@ namespace X86ISA
                 assert(alignedVaddr == virt_page_addr);
     #endif
 
-                bool success = p->pTable->lookup(vaddr, newEntry);
-                if (!success && sender_state->tlbMode != BaseTLB::Execute) {
-                    if (p->fixupStackFault(vaddr))
-                        success = p->pTable->lookup(vaddr, newEntry);
+                const EmulationPageTable::Entry *pte =
+                        p->pTable->lookup(vaddr);
+                if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
+                        p->fixupStackFault(vaddr)) {
+                    pte = p->pTable->lookup(vaddr);
                 }
 
                 if (!sender_state->prefetch) {
                     // no PageFaults are permitted after
                     // the second page table lookup
-                    assert(success);
+                    assert(pte);
 
                     DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
-                           newEntry.pageStart());
+                            pte->paddr);
 
-                    sender_state->tlbEntry = new GpuTlbEntry(0, newEntry.vaddr,
-                                                             newEntry.paddr,
-                                                             success);
+                    sender_state->tlbEntry =
+                        new TlbEntry(p->pid(), virt_page_addr,
+                                     pte->paddr, false, false);
                 } else {
                     // If this was a prefetch, then do the normal thing if it
                     // was a successful translation.  Otherwise, send an empty
                     // TLB entry back so that it can be figured out as empty and
                     // handled accordingly.
-                    if (success) {
+                    if (pte) {
                         DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
-                               newEntry.pageStart());
+                                pte->paddr);
 
-                        sender_state->tlbEntry = new GpuTlbEntry(0,
-                                                                 newEntry.vaddr,
-                                                                 newEntry.paddr,
-                                                                 success);
+                        sender_state->tlbEntry =
+                            new TlbEntry(p->pid(), virt_page_addr,
+                                         pte->paddr, false, false);
                     } else {
                         DPRINTF(GPUPrefetch, "Prefetch failed %#x\n",
                                 alignedVaddr);
 
-                        sender_state->tlbEntry = new GpuTlbEntry();
+                        sender_state->tlbEntry = nullptr;
 
                         return;
                     }
@@ -1576,13 +1572,15 @@ namespace X86ISA
             DPRINTF(GPUPrefetch, "Functional Hit for vaddr %#x\n",
                     tlb->lookup(pkt->req->getVaddr()));
 
-            GpuTlbEntry *entry = tlb->lookup(pkt->req->getVaddr(),
+            TlbEntry *entry = tlb->lookup(pkt->req->getVaddr(),
                                              update_stats);
 
             assert(entry);
 
+            auto p = sender_state->tc->getProcessPtr();
             sender_state->tlbEntry =
-                new GpuTlbEntry(0, entry->vaddr, entry->paddr, entry->valid);
+                new TlbEntry(p->pid(), entry->vaddr, entry->paddr,
+                             false, false);
         }
         // This is the function that would populate pkt->req with the paddr of
         // the translation. But if no translation happens (i.e Prefetch fails)
@@ -1596,7 +1594,7 @@ namespace X86ISA
     {
         // The CPUSidePort never sends anything but replies. No retries
         // expected.
-        assert(false);
+        panic("recvReqRetry called");
     }
 
     AddrRangeList
@@ -1637,7 +1635,7 @@ namespace X86ISA
     {
         // No retries should reach the TLB. The retries
         // should only reach the TLBCoalescer.
-        assert(false);
+        panic("recvReqRetry called");
     }
 
     void