changeset a9f05ab40763 in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=a9f05ab40763
description:
        x86: Timing support for pagetable walker

        Move page table walker state to its own object type, and make the
        walker instantiate state for each outstanding walk. By storing the
        states in a queue, the walker is able to handle multiple outstanding
        timing requests. Note that functional walks use separate state
        elements.

diffstat:

 src/arch/x86/pagetable_walker.cc |  922 ++++++++++++++++++++++----------------
 src/arch/x86/pagetable_walker.hh |  181 ++++---
 src/arch/x86/tlb.cc              |    6 +
 src/arch/x86/tlb.hh              |    2 +
 4 files changed, 647 insertions(+), 464 deletions(-)

diffs (truncated from 1247 to 300 lines):

diff -r 267e1e16e51b -r a9f05ab40763 src/arch/x86/pagetable_walker.cc
--- a/src/arch/x86/pagetable_walker.cc  Sun Feb 06 22:14:18 2011 -0800
+++ b/src/arch/x86/pagetable_walker.cc  Sun Feb 06 22:14:18 2011 -0800
@@ -40,6 +40,7 @@
 #include "arch/x86/pagetable.hh"
 #include "arch/x86/pagetable_walker.hh"
 #include "arch/x86/tlb.hh"
+#include "arch/x86/vtophys.hh"
 #include "base/bitfield.hh"
 #include "cpu/thread_context.hh"
 #include "cpu/base.hh"
@@ -67,328 +68,36 @@
 EndBitUnion(PageTableEntry)
 
 Fault
-Walker::doNext(PacketPtr &write)
+Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
+              RequestPtr _req, BaseTLB::Mode _mode)
 {
-    assert(state != Ready && state != Waiting);
-    write = NULL;
-    PageTableEntry pte;
-    if (size == 8)
-        pte = read->get<uint64_t>();
-    else
-        pte = read->get<uint32_t>();
-    VAddr vaddr = entry.vaddr;
-    bool uncacheable = pte.pcd;
-    Addr nextRead = 0;
-    bool doWrite = false;
-    bool badNX = pte.nx && mode == BaseTLB::Execute && enableNX;
-    switch(state) {
-      case LongPML4:
-        DPRINTF(PageTableWalker,
-                "Got long mode PML4 entry %#016x.\n", (uint64_t)pte);
-        nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl3 * size;
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = pte.w;
-        entry.user = pte.u;
-        if (badNX || !pte.p) {
-            stop();
-            return pageFault(pte.p);
+    // TODO: in timing mode, instead of blocking when there are other
+    // outstanding requests, see if this request can be coalesced with
+    // another one (i.e. either coalesce or start walk)
+    WalkerState * newState = new WalkerState(this, _translation, _req);
+    newState->initState(_tc, _mode, sys->getMemoryMode() == Enums::timing);
+    if (currStates.size()) {
+        assert(newState->isTiming());
+        DPRINTF(PageTableWalker, "Walks in progress: %d\n", currStates.size());
+        currStates.push_back(newState);
+        return NoFault;
+    } else {
+        currStates.push_back(newState);
+        Fault fault = newState->startWalk();
+        if (!newState->isTiming()) {
+            currStates.pop_front();
+            delete newState;
         }
-        entry.noExec = pte.nx;
-        nextState = LongPDP;
-        break;
-      case LongPDP:
-        DPRINTF(PageTableWalker,
-                "Got long mode PDP entry %#016x.\n", (uint64_t)pte);
-        nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl2 * size;
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = entry.writable && pte.w;
-        entry.user = entry.user && pte.u;
-        if (badNX || !pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        nextState = LongPD;
-        break;
-      case LongPD:
-        DPRINTF(PageTableWalker,
-                "Got long mode PD entry %#016x.\n", (uint64_t)pte);
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = entry.writable && pte.w;
-        entry.user = entry.user && pte.u;
-        if (badNX || !pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        if (!pte.ps) {
-            // 4 KB page
-            entry.size = 4 * (1 << 10);
-            nextRead =
-                ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl1 * size;
-            nextState = LongPTE;
-            break;
-        } else {
-            // 2 MB page
-            entry.size = 2 * (1 << 20);
-            entry.paddr = (uint64_t)pte & (mask(31) << 21);
-            entry.uncacheable = uncacheable;
-            entry.global = pte.g;
-            entry.patBit = bits(pte, 12);
-            entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
-            tlb->insert(entry.vaddr, entry);
-            stop();
-            return NoFault;
-        }
-      case LongPTE:
-        DPRINTF(PageTableWalker,
-                "Got long mode PTE entry %#016x.\n", (uint64_t)pte);
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = entry.writable && pte.w;
-        entry.user = entry.user && pte.u;
-        if (badNX || !pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        entry.paddr = (uint64_t)pte & (mask(40) << 12);
-        entry.uncacheable = uncacheable;
-        entry.global = pte.g;
-        entry.patBit = bits(pte, 12);
-        entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
-        tlb->insert(entry.vaddr, entry);
-        stop();
-        return NoFault;
-      case PAEPDP:
-        DPRINTF(PageTableWalker,
-                "Got legacy mode PAE PDP entry %#08x.\n", (uint32_t)pte);
-        nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size;
-        if (!pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        nextState = PAEPD;
-        break;
-      case PAEPD:
-        DPRINTF(PageTableWalker,
-                "Got legacy mode PAE PD entry %#08x.\n", (uint32_t)pte);
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = pte.w;
-        entry.user = pte.u;
-        if (badNX || !pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        if (!pte.ps) {
-            // 4 KB page
-            entry.size = 4 * (1 << 10);
-            nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael1 * size;
-            nextState = PAEPTE;
-            break;
-        } else {
-            // 2 MB page
-            entry.size = 2 * (1 << 20);
-            entry.paddr = (uint64_t)pte & (mask(31) << 21);
-            entry.uncacheable = uncacheable;
-            entry.global = pte.g;
-            entry.patBit = bits(pte, 12);
-            entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
-            tlb->insert(entry.vaddr, entry);
-            stop();
-            return NoFault;
-        }
-      case PAEPTE:
-        DPRINTF(PageTableWalker,
-                "Got legacy mode PAE PTE entry %#08x.\n", (uint32_t)pte);
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = entry.writable && pte.w;
-        entry.user = entry.user && pte.u;
-        if (badNX || !pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        entry.paddr = (uint64_t)pte & (mask(40) << 12);
-        entry.uncacheable = uncacheable;
-        entry.global = pte.g;
-        entry.patBit = bits(pte, 7);
-        entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
-        tlb->insert(entry.vaddr, entry);
-        stop();
-        return NoFault;
-      case PSEPD:
-        DPRINTF(PageTableWalker,
-                "Got legacy mode PSE PD entry %#08x.\n", (uint32_t)pte);
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = pte.w;
-        entry.user = pte.u;
-        if (!pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        if (!pte.ps) {
-            // 4 KB page
-            entry.size = 4 * (1 << 10);
-            nextRead =
-                ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
-            nextState = PTE;
-            break;
-        } else {
-            // 4 MB page
-            entry.size = 4 * (1 << 20);
-            entry.paddr = bits(pte, 20, 13) << 32 | bits(pte, 31, 22) << 22;
-            entry.uncacheable = uncacheable;
-            entry.global = pte.g;
-            entry.patBit = bits(pte, 12);
-            entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1);
-            tlb->insert(entry.vaddr, entry);
-            stop();
-            return NoFault;
-        }
-      case PD:
-        DPRINTF(PageTableWalker,
-                "Got legacy mode PD entry %#08x.\n", (uint32_t)pte);
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = pte.w;
-        entry.user = pte.u;
-        if (!pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        // 4 KB page
-        entry.size = 4 * (1 << 10);
-        nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
-        nextState = PTE;
-        break;
-      case PTE:
-        DPRINTF(PageTableWalker,
-                "Got legacy mode PTE entry %#08x.\n", (uint32_t)pte);
-        doWrite = !pte.a;
-        pte.a = 1;
-        entry.writable = pte.w;
-        entry.user = pte.u;
-        if (!pte.p) {
-            stop();
-            return pageFault(pte.p);
-        }
-        entry.paddr = (uint64_t)pte & (mask(20) << 12);
-        entry.uncacheable = uncacheable;
-        entry.global = pte.g;
-        entry.patBit = bits(pte, 7);
-        entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
-        tlb->insert(entry.vaddr, entry);
-        stop();
-        return NoFault;
-      default:
-        panic("Unknown page table walker state %d!\n");
+        return fault;
     }
-    PacketPtr oldRead = read;
-    //If we didn't return, we're setting up another read.
-    Request::Flags flags = oldRead->req->getFlags();
-    flags.set(Request::UNCACHEABLE, uncacheable);
-    RequestPtr request =
-        new Request(nextRead, oldRead->getSize(), flags);
-    read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast);
-    read->allocate();
-    //If we need to write, adjust the read packet to write the modified value
-    //back to memory.
-    if (doWrite) {
-        write = oldRead;
-        write->set<uint64_t>(pte);
-        write->cmd = MemCmd::WriteReq;
-        write->setDest(Packet::Broadcast);
-    } else {
-        write = NULL;
-        delete oldRead->req;
-        delete oldRead;
-    }
-    return NoFault;
 }
 
 Fault
-Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
-              RequestPtr _req, BaseTLB::Mode _mode)
+Walker::startFunctional(ThreadContext * _tc, Addr &addr, Addr &pageSize,
+              BaseTLB::Mode _mode)
 {
-    assert(state == Ready);
-    tc = _tc;
-    req = _req;
-    Addr vaddr = req->getVaddr();
-    mode = _mode;
-    translation = _translation;
-
-    VAddr addr = vaddr;
-
-    //Figure out what we're doing.
-    CR3 cr3 = tc->readMiscRegNoEffect(MISCREG_CR3);
-    Addr top = 0;
-    // Check if we're in long mode or not
-    Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
-    size = 8;
-    if (efer.lma) {
-        // Do long mode.
-        state = LongPML4;
_______________________________________________
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to