tarch, mem: Abstract the data stored in the SE page tables.
authorGabe Black <gabeblack@google.com>
Tue, 9 Jan 2018 07:37:57 +0000 (23:37 -0800)
committerGabe Black <gabeblack@google.com>
Tue, 23 Jan 2018 20:39:17 +0000 (20:39 +0000)
Rather than store the actual TLB entry that corresponds to a mapping,
we can just store some abstracted information (address, a few flags)
and then let the caller turn that into the appropriate entry. There
could potentially be some small amount of overhead from creating
entries vs. storing them and just installing them, but it's likely
pretty minimal since that only happens on a TLB miss (ideally rare),
and, if it is problematic, there could be some preallocated TLB
entries which are just minimally filled in as necessary.

This has the nice effect of finally making the page tables ISA
agnostic.

Change-Id: I11e630f60682f0a0029b0683eb8ff0135fbd4317
Reviewed-on: https://gem5-review.googlesource.com/7350
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/arch/alpha/faults.cc
src/arch/sparc/faults.cc
src/arch/x86/tlb.cc
src/gpu-compute/gpu_tlb.cc
src/mem/page_table.cc
src/mem/page_table.hh
src/sim/syscall_emul.hh

index 89b0ecea8b95b03b1073d9a843eec6c592f62c0e..3433844c1cd2dcc2b7b7eec4fccfd52aacf4bca4 100644 (file)
@@ -196,11 +196,14 @@ ItbPageFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
     }
 
     Process *p = tc->getProcessPtr();
-    TlbEntry *entry = p->pTable->lookup(pc);
-    panic_if(!entry, "Tried to execute unmapped address %#x.\n", pc);
+    const EmulationPageTable::Entry *pte = p->pTable->lookup(pc);
+    panic_if(!pte, "Tried to execute unmapped address %#x.\n", pc);
 
     VAddr vaddr(pc);
-    dynamic_cast<TLB *>(tc->getITBPtr())->insert(vaddr.page(), *entry);
+    TlbEntry entry(p->pTable->pid(), vaddr.page(), pte->paddr,
+                   pte->flags & EmulationPageTable::Uncacheable,
+                   pte->flags & EmulationPageTable::ReadOnly);
+    dynamic_cast<TLB *>(tc->getITBPtr())->insert(vaddr.page(), entry);
 }
 
 void
@@ -212,11 +215,14 @@ NDtbMissFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
     }
 
     Process *p = tc->getProcessPtr();
-    TlbEntry *entry = p->pTable->lookup(vaddr);
-    if (!entry && p->fixupStackFault(vaddr))
-        entry = p->pTable->lookup(vaddr);
-    panic_if(!entry, "Tried to access unmapped address %#x.\n", (Addr)vaddr);
-    dynamic_cast<TLB *>(tc->getDTBPtr())->insert(vaddr.page(), *entry);
+    const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
+    if (!pte && p->fixupStackFault(vaddr))
+        pte = p->pTable->lookup(vaddr);
+    panic_if(!pte, "Tried to access unmapped address %#x.\n", (Addr)vaddr);
+    TlbEntry entry(p->pTable->pid(), vaddr.page(), pte->paddr,
+                   pte->flags & EmulationPageTable::Uncacheable,
+                   pte->flags & EmulationPageTable::ReadOnly);
+    dynamic_cast<TLB *>(tc->getDTBPtr())->insert(vaddr.page(), entry);
 }
 
 } // namespace AlphaISA
index 0b6a289272f42018d7140a6bd61ead68c5c29a3f..0f042b4ae3e61d13e0d30f9740604be27e372564 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "arch/sparc/isa_traits.hh"
 #include "arch/sparc/process.hh"
+#include "arch/sparc/tlb.hh"
 #include "arch/sparc/types.hh"
 #include "base/bitfield.hh"
 #include "base/trace.hh"
@@ -629,8 +630,8 @@ FastInstructionAccessMMUMiss::invoke(ThreadContext *tc,
     }
 
     Process *p = tc->getProcessPtr();
-    TlbEntry *entry = p->pTable->lookup(vaddr);
-    panic_if(!entry, "Tried to execute unmapped address %#x.\n", vaddr);
+    const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
+    panic_if(!pte, "Tried to execute unmapped address %#x.\n", vaddr);
 
     Addr alignedvaddr = p->pTable->pageAlign(vaddr);
 
@@ -662,13 +663,17 @@ FastInstructionAccessMMUMiss::invoke(ThreadContext *tc,
     // the logic works out to the following for the context.
     int context_id = (is_real_address || trapped) ? 0 : primary_context;
 
+    TlbEntry entry(p->pTable->pid(), alignedvaddr, pte->paddr,
+                   pte->flags & EmulationPageTable::Uncacheable,
+                   pte->flags & EmulationPageTable::ReadOnly);
+
     // Insert the TLB entry.
     // The entry specifying whether the address is "real" is set to
     // false for syscall emulation mode regardless of whether the
     // address is real in preceding code. Not sure sure that this is
     // correct, but also not sure if it matters at all.
     dynamic_cast<TLB *>(tc->getITBPtr())->
-        insert(alignedvaddr, partition_id, context_id, false, entry->pte);
+        insert(alignedvaddr, partition_id, context_id, false, entry.pte);
 }
 
 void
@@ -680,10 +685,10 @@ FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
     }
 
     Process *p = tc->getProcessPtr();
-    TlbEntry *entry = p->pTable->lookup(vaddr);
-    if (!entry && p->fixupStackFault(vaddr))
-        entry = p->pTable->lookup(vaddr);
-    panic_if(!entry, "Tried to access unmapped address %#x.\n", vaddr);
+    const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
+    if (!pte && p->fixupStackFault(vaddr))
+        pte = p->pTable->lookup(vaddr);
+    panic_if(!pte, "Tried to access unmapped address %#x.\n", vaddr);
 
     Addr alignedvaddr = p->pTable->pageAlign(vaddr);
 
@@ -745,13 +750,17 @@ FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
     // The partition id distinguishes between virtualized environments.
     int const partition_id = 0;
 
+    TlbEntry entry(p->pTable->pid(), alignedvaddr, pte->paddr,
+                   pte->flags & EmulationPageTable::Uncacheable,
+                   pte->flags & EmulationPageTable::ReadOnly);
+
     // Insert the TLB entry.
     // The entry specifying whether the address is "real" is set to
     // false for syscall emulation mode regardless of whether the
     // address is real in preceding code. Not sure sure that this is
     // correct, but also not sure if it matters at all.
     dynamic_cast<TLB *>(tc->getDTBPtr())->
-        insert(alignedvaddr, partition_id, context_id, false, entry->pte);
+        insert(alignedvaddr, partition_id, context_id, false, entry.pte);
 }
 
 void
index 93369494d3b85762a9a82b88d59668464a82f72d..a3aec16765a11f79d88f7bf70f874f4338be1b38 100644 (file)
@@ -357,22 +357,26 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
                     assert(entry);
                 } else {
                     Process *p = tc->getProcessPtr();
-                    TlbEntry *newEntry = p->pTable->lookup(vaddr);
-                    if (!newEntry && mode != Execute) {
+                    const EmulationPageTable::Entry *pte =
+                        p->pTable->lookup(vaddr);
+                    if (!pte && mode != Execute) {
                         // Check if we just need to grow the stack.
                         if (p->fixupStackFault(vaddr)) {
                             // If we did, lookup the entry for the new page.
-                            newEntry = p->pTable->lookup(vaddr);
+                            pte = p->pTable->lookup(vaddr);
                         }
                     }
-                    if (!newEntry) {
+                    if (!pte) {
                         return std::make_shared<PageFault>(vaddr, true, mode,
                                                            true, false);
                     } else {
                         Addr alignedVaddr = p->pTable->pageAlign(vaddr);
                         DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
-                                newEntry->pageStart());
-                        entry = insert(alignedVaddr, *newEntry);
+                                pte->paddr);
+                        entry = insert(alignedVaddr, TlbEntry(
+                                p->pTable->pid(), alignedVaddr, pte->paddr,
+                                pte->flags & EmulationPageTable::Uncacheable,
+                                pte->flags & EmulationPageTable::ReadOnly));
                     }
                     DPRINTF(TLB, "Miss was serviced.\n");
                 }
index 9cbf3e8faaeaf6da847a9424cb085300ce1a0fa9..05d22dad658169d4832ab46d6225abf04ab9a2a9 100644 (file)
@@ -808,18 +808,19 @@ namespace X86ISA
                                 "at pc %#x.\n", vaddr, tc->instAddr());
 
                         Process *p = tc->getProcessPtr();
-                        TlbEntry *newEntry = p->pTable->lookup(vaddr);
+                        const EmulationPageTable::Entry *pte =
+                            p->pTable->lookup(vaddr);
 
-                        if (!newEntry && mode != BaseTLB::Execute) {
+                        if (!pte && mode != BaseTLB::Execute) {
                             // penalize a "page fault" more
                             if (timing)
                                 latency += missLatency2;
 
                             if (p->fixupStackFault(vaddr))
-                                newEntry = p->pTable->lookup(vaddr);
+                                pte = p->pTable->lookup(vaddr);
                         }
 
-                        if (!newEntry) {
+                        if (!pte) {
                             return std::make_shared<PageFault>(vaddr, true,
                                                                mode, true,
                                                                false);
@@ -827,11 +828,11 @@ namespace X86ISA
                             Addr alignedVaddr = p->pTable->pageAlign(vaddr);
 
                             DPRINTF(GPUTLB, "Mapping %#x to %#x\n",
-                                    alignedVaddr, newEntry->pageStart());
+                                    alignedVaddr, pte->paddr);
 
-                            GpuTlbEntry gpuEntry;
-                            *(TlbEntry *)&gpuEntry = *newEntry;
-                            gpuEntry.valid = true;
+                            GpuTlbEntry gpuEntry(
+                                p->pTable->pid(), alignedVaddr,
+                                pte->paddr, true);
                             entry = insert(alignedVaddr, gpuEntry);
                         }
 
@@ -1335,18 +1336,18 @@ namespace X86ISA
             Addr alignedVaddr = p->pTable->pageAlign(vaddr);
             assert(alignedVaddr == virtPageAddr);
     #endif
-            TlbEntry *newEntry = p->pTable->lookup(vaddr);
-            if (!newEntry && sender_state->tlbMode != BaseTLB::Execute &&
+            const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
+            if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
                     p->fixupStackFault(vaddr)) {
-                newEntry = p->pTable->lookup(vaddr);
+                pte = p->pTable->lookup(vaddr);
             }
 
-            if (newEntry) {
+            if (pte) {
                 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
-                        newEntry->pageStart());
+                        pte->paddr);
 
                 sender_state->tlbEntry =
-                    new GpuTlbEntry(0, newEntry->vaddr, newEntry->paddr, true);
+                    new GpuTlbEntry(0, virtPageAddr, pte->paddr, true);
             } else {
                 sender_state->tlbEntry =
                     new GpuTlbEntry(0, 0, 0, false);
@@ -1533,10 +1534,11 @@ namespace X86ISA
                 assert(alignedVaddr == virt_page_addr);
     #endif
 
-                TlbEntry *newEntry = p->pTable->lookup(vaddr);
-                if (!newEntry && sender_state->tlbMode != BaseTLB::Execute &&
+                const EmulationPageTable::Entry *pte =
+                        p->pTable->lookup(vaddr);
+                if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
                         p->fixupStackFault(vaddr)) {
-                    newEntry = p->pTable->lookup(vaddr);
+                    pte = p->pTable->lookup(vaddr);
                 }
 
                 if (!sender_state->prefetch) {
@@ -1545,23 +1547,23 @@ namespace X86ISA
                     assert(success);
 
                     DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
-                           newEntry->pageStart());
+                            pte->paddr);
 
                     sender_state->tlbEntry =
-                        new GpuTlbEntry(0, newEntry->vaddr,
-                                        newEntry->paddr, success);
+                        new GpuTlbEntry(0, virt_page_addr,
+                                        pte->paddr, success);
                 } 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 (newEntry) {
+                    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);
+                            new GpuTlbEntry(0, virt_page_addr,
+                                            pte->paddr, success);
                     } else {
                         DPRINTF(GPUPrefetch, "Prefetch failed %#x\n",
                                 alignedVaddr);
index ee504196af1b53bc2b922f133888fd68ae81fc60..8a11ada76040b94b9043d58237d057d68a96b7ca 100644 (file)
 #include <string>
 
 #include "base/trace.hh"
-#include "config/the_isa.hh"
 #include "debug/MMU.hh"
 #include "sim/faults.hh"
 #include "sim/serialize.hh"
 
 using namespace std;
-using namespace TheISA;
-
-EmulationPageTable::~EmulationPageTable()
-{
-    for (auto &iter : pTable)
-        delete iter.second;
-}
 
 void
 EmulationPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
@@ -66,20 +58,15 @@ EmulationPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
     while (size > 0) {
         auto it = pTable.find(vaddr);
         if (it != pTable.end()) {
-            if (clobber) {
-                delete it->second;
-            } else {
-                // already mapped
-                panic("EmulationPageTable::allocate: addr %#x already mapped",
-                      vaddr);
-            }
+            // already mapped
+            panic_if(!clobber,
+                     "EmulationPageTable::allocate: addr %#x already mapped",
+                     vaddr);
+            it->second = Entry(paddr, flags);
         } else {
-            it = pTable.emplace(vaddr, nullptr).first;
+            pTable.emplace(vaddr, Entry(paddr, flags));
         }
 
-        it->second = new TheISA::TlbEntry(pid, vaddr, paddr,
-                                         flags & Uncacheable,
-                                         flags & ReadOnly);
         size -= pageSize;
         vaddr += pageSize;
         paddr += pageSize;
@@ -102,7 +89,6 @@ EmulationPageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
 
         new_it->second = old_it->second;
         pTable.erase(old_it);
-        new_it->second->updateVaddr(new_vaddr);
         size -= pageSize;
         vaddr += pageSize;
         new_vaddr += pageSize;
@@ -113,7 +99,7 @@ void
 EmulationPageTable::getMappings(std::vector<std::pair<Addr, Addr>> *addr_maps)
 {
     for (auto &iter : pTable)
-        addr_maps->push_back(make_pair(iter.first, iter.second->pageStart()));
+        addr_maps->push_back(make_pair(iter.first, iter.second.paddr));
 }
 
 void
@@ -121,12 +107,11 @@ EmulationPageTable::unmap(Addr vaddr, int64_t size)
 {
     assert(pageOffset(vaddr) == 0);
 
-    DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr+ size);
+    DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr + size);
 
     while (size > 0) {
         auto it = pTable.find(vaddr);
         assert(it != pTable.end());
-        delete it->second;
         pTable.erase(it);
         size -= pageSize;
         vaddr += pageSize;
@@ -146,25 +131,25 @@ EmulationPageTable::isUnmapped(Addr vaddr, int64_t size)
     return true;
 }
 
-TheISA::TlbEntry *
+const EmulationPageTable::Entry *
 EmulationPageTable::lookup(Addr vaddr)
 {
     Addr page_addr = pageAlign(vaddr);
     PTableItr iter = pTable.find(page_addr);
     if (iter == pTable.end())
         return nullptr;
-    return iter->second;
+    return &(iter->second);
 }
 
 bool
 EmulationPageTable::translate(Addr vaddr, Addr &paddr)
 {
-    TheISA::TlbEntry *entry = lookup(vaddr);
+    const Entry *entry = lookup(vaddr);
     if (!entry) {
         DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr);
         return false;
     }
-    paddr = pageOffset(vaddr) + entry->pageStart();
+    paddr = pageOffset(vaddr) + entry->paddr;
     DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr);
     return true;
 }
@@ -195,7 +180,8 @@ EmulationPageTable::serialize(CheckpointOut &cp) const
         ScopedCheckpointSection sec(cp, csprintf("Entry%d", count++));
 
         paramOut(cp, "vaddr", pte.first);
-        pte.second->serialize(cp);
+        paramOut(cp, "paddr", pte.second.paddr);
+        paramOut(cp, "flags", pte.second.flags);
     }
     assert(count == pTable.size());
 }
@@ -209,13 +195,14 @@ EmulationPageTable::unserialize(CheckpointIn &cp)
     for (int i = 0; i < count; ++i) {
         ScopedCheckpointSection sec(cp, csprintf("Entry%d", i));
 
-        TheISA::TlbEntry *entry = new TheISA::TlbEntry();
-        entry->unserialize(cp);
-
         Addr vaddr;
-        paramIn(cp, "vaddr", vaddr);
+        UNSERIALIZE_SCALAR(vaddr);
+        Addr paddr;
+        uint64_t flags;
+        UNSERIALIZE_SCALAR(paddr);
+        UNSERIALIZE_SCALAR(flags);
 
-        pTable[vaddr] = entry;
+        pTable.emplace(vaddr, Entry(paddr, flags));
     }
 }
 
index 733cdd2e34298cfa9bdb8569631bc8cd1b594e4b..fc0c0923e2353cb4d9a0094c0573a51c6931c531 100644 (file)
 #include <string>
 #include <unordered_map>
 
-#include "arch/isa_traits.hh"
-#include "arch/tlb.hh"
 #include "base/intmath.hh"
 #include "base/types.hh"
-#include "config/the_isa.hh"
 #include "mem/request.hh"
 #include "sim/serialize.hh"
 
@@ -52,15 +49,25 @@ class ThreadContext;
 
 class EmulationPageTable : public Serializable
 {
+  public:
+    struct Entry
+    {
+        Addr paddr;
+        uint64_t flags;
+
+        Entry(Addr paddr, uint64_t flags) : paddr(paddr), flags(flags) {}
+        Entry() {}
+    };
+
   protected:
-    typedef std::unordered_map<Addr, TheISA::TlbEntry *> PTable;
+    typedef std::unordered_map<Addr, Entry> PTable;
     typedef PTable::iterator PTableItr;
     PTable pTable;
 
     const Addr pageSize;
     const Addr offsetMask;
 
-    const uint64_t pid;
+    const uint64_t _pid;
     const std::string _name;
 
   public:
@@ -68,12 +75,14 @@ class EmulationPageTable : public Serializable
     EmulationPageTable(
             const std::string &__name, uint64_t _pid, Addr _pageSize) :
             pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))),
-            pid(_pid), _name(__name)
+            _pid(_pid), _name(__name)
     {
         assert(isPowerOf2(pageSize));
     }
 
-    virtual ~EmulationPageTable();
+    uint64_t pid() const { return _pid; };
+
+    virtual ~EmulationPageTable() {};
 
     /* generic page table mapping flags
      *              unset | set
@@ -120,7 +129,7 @@ class EmulationPageTable : public Serializable
      * @param vaddr The virtual address.
      * @return The page table entry corresponding to vaddr.
      */
-    virtual TheISA::TlbEntry *lookup(Addr vaddr);
+    const Entry *lookup(Addr vaddr);
 
     /**
      * Translate function
index ef61299a03bb5f3c5b2db6d9da0fd770ff0b8ad9..eaa5e542cced7573d1505c5ae54d4f19f4bb7a50 100644 (file)
@@ -93,6 +93,7 @@
 #include <memory>
 #include <string>
 
+#include "arch/generic/tlb.hh"
 #include "arch/utility.hh"
 #include "base/intmath.hh"
 #include "base/loader/object_file.hh"