implement vtophys and 32bit gdb support
authorAli Saidi <saidi@eecs.umich.edu>
Mon, 19 Feb 2007 00:57:46 +0000 (19:57 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Mon, 19 Feb 2007 00:57:46 +0000 (19:57 -0500)
src/arch/alpha/vtophys.cc:
src/arch/alpha/vtophys.hh:
src/arch/sparc/arguments.hh:
    move Copy* to vport since it's generic for all the ISAs
src/arch/sparc/isa_traits.hh:
    the Solaris kernel sets up a virtual-> real mapping for all memory starting at SegKPMBase
src/arch/sparc/pagetable.hh:
    add a class for getting bits out of the TteTag
src/arch/sparc/remote_gdb.cc:
    add 32bit support kinda.... If its 32 bit
src/arch/sparc/remote_gdb.hh:
    Add 32bit register offsets too.
src/arch/sparc/tlb.cc:
    cleanup generation of tsb pointers
src/arch/sparc/tlb.hh:
    add function to return tsb pointers for an address
    make lookup public so vtophys can use it
src/arch/sparc/vtophys.cc:
src/arch/sparc/vtophys.hh:
    write vtophys for sparc
src/base/bitfield.hh:
    return a mask of bits first->last
src/mem/vport.cc:
src/mem/vport.hh:
    move Copy* here since it's ISA generic

--HG--
extra : convert_revision : c42c331e396c0d51a2789029d8e232fe66995d0f

14 files changed:
src/arch/alpha/vtophys.cc
src/arch/alpha/vtophys.hh
src/arch/sparc/arguments.hh
src/arch/sparc/isa_traits.hh
src/arch/sparc/pagetable.hh
src/arch/sparc/remote_gdb.cc
src/arch/sparc/remote_gdb.hh
src/arch/sparc/tlb.cc
src/arch/sparc/tlb.hh
src/arch/sparc/vtophys.cc
src/arch/sparc/vtophys.hh
src/base/bitfield.hh
src/mem/vport.cc
src/mem/vport.hh

index fd8f781e41c78b474d77aa36ce4e00c47ee19989..1a3147bccedfd4b58b446a8ed704643236ae7a6a 100644 (file)
@@ -113,54 +113,3 @@ AlphaISA::vtophys(ThreadContext *tc, Addr addr)
     return paddr;
 }
 
-
-void
-AlphaISA::CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
-{
-    uint8_t *dst = (uint8_t *)dest;
-    VirtualPort *vp = tc->getVirtPort(tc);
-
-    vp->readBlob(src, dst, cplen);
-
-    tc->delVirtPort(vp);
-
-}
-
-void
-AlphaISA::CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
-{
-    uint8_t *src = (uint8_t *)source;
-    VirtualPort *vp = tc->getVirtPort(tc);
-
-    vp->writeBlob(dest, src, cplen);
-
-    tc->delVirtPort(vp);
-}
-
-void
-AlphaISA::CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
-{
-    int len = 0;
-    char *start = dst;
-    VirtualPort *vp = tc->getVirtPort(tc);
-
-    do {
-        vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
-    } while (len < maxlen && start[len++] != 0 );
-
-    tc->delVirtPort(vp);
-    dst[len] = 0;
-}
-
-void
-AlphaISA::CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
-{
-    VirtualPort *vp = tc->getVirtPort(tc);
-    for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done();
-            gen.next())
-    {
-        vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size());
-        src += gen.size();
-    }
-    tc->delVirtPort(vp);
-}
index 32b999c37c3e7ef379cbb51992b45975b79bf0b6..bd2ee84686268445e2c3509c70f6a5ba15e1c59f 100644 (file)
@@ -47,11 +47,6 @@ namespace AlphaISA {
     Addr vtophys(Addr vaddr);
     Addr vtophys(ThreadContext *tc, Addr vaddr);
 
-    void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len);
-    void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len);
-    void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
-    void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
-
 };
 #endif // __ARCH_ALPHA_VTOPHYS_H__
 
index 8f925dd25277b48663dd878757d23102c75b0b99..5596f7408f75582df0fa64a2e7c3c1617d995e22 100644 (file)
@@ -33,9 +33,9 @@
 
 #include <assert.h>
 
-#include "arch/sparc/vtophys.hh"
 #include "base/refcnt.hh"
 #include "sim/host.hh"
+#include "mem/vport.hh"
 
 class ThreadContext;
 
index 64ae6abd8ecf1e9fc201269b7451d6195d137dc6..1fbdd160d5f0ef253e0025904cdcd83bfa3995b7 100644 (file)
@@ -87,6 +87,11 @@ namespace SparcISA
     const int LogVMPageSize = 13;
     const int VMPageSize = (1 << LogVMPageSize);
 
+    // real address virtual mapping
+    // sort of like alpha super page, but less frequently used
+    const Addr SegKPMEnd  = ULL(0xfffffffc00000000);
+    const Addr SegKPMBase = ULL(0xfffffac000000000);
+
     //Why does both the previous set of constants and this one exist?
     const int PageShift = 13;
     const int PageBytes = 1ULL << PageShift;
index fc01e82da459a2216a4bab156605a72470020a09..9802250529c6c20c3e96b18fd0e5d4f381b33b79 100644 (file)
@@ -45,6 +45,22 @@ struct VAddr
     VAddr(Addr a) { panic("not implemented yet."); }
 };
 
+class TteTag
+{
+  private:
+    uint64_t entry;
+    bool populated;
+
+  public:
+    TteTag() : entry(0), populated(false) {}
+    TteTag(uint64_t e) : entry(e), populated(true) {}
+    const TteTag &operator=(uint64_t e) { populated = true;
+                                          entry = e; return *this; }
+    bool valid() const {assert(populated); return !bits(entry,62,62); }
+    Addr va()    const {assert(populated); return bits(entry,41,0); }
+};
+
+
 class PageTableEntry
 {
   public:
@@ -110,13 +126,14 @@ class PageTableEntry
                                                   entry4u = e; return *this; }
 
     const PageTableEntry &operator=(const PageTableEntry &e)
-    { populated = true; entry4u = e.entry4u; return *this; }
+    { populated = true; entry4u = e.entry4u; type = e.type; return *this; }
 
     bool    valid()    const { return bits(entry4u,63,63) && populated; }
     uint8_t _size()     const { assert(populated);
                                return bits(entry4u, 62,61) |
                                       bits(entry4u, 48,48) << 2; }
     Addr    size()     const { assert(_size() < 6); return pageSizes[_size()]; }
+    Addr    sizeMask() const { assert(_size() < 6); return pageSizes[_size()]-1;}
     bool    ie()       const { return bits(entry4u, 59,59); }
     Addr    pfn()      const { assert(populated); return bits(entry4u,39,13); }
     Addr    paddr()    const { assert(populated); return mbits(entry4u, 39,13);}
@@ -127,6 +144,8 @@ class PageTableEntry
     bool    writable() const { assert(populated); return bits(entry4u,1,1); }
     bool    nofault()  const { assert(populated); return bits(entry4u,60,60); }
     bool    sideffect() const { assert(populated); return bits(entry4u,3,3); }
+    Addr    paddrMask() const { assert(populated);
+                                return mbits(entry4u, 39,13) & ~sizeMask(); }
 };
 
 struct TlbRange {
index 2221576a36aa5945e0e28fa5fbbfa33437d7c185..e2ea7a84d42ec224d9edc722fe8c706952757c01 100644 (file)
@@ -152,7 +152,9 @@ RemoteGDB::acc(Addr va, size_t len)
     //@Todo In NetBSD, this function checks if all addresses
     //from va to va + len have valid page mape entries. Not
     //sure how this will work for other OSes or in general.
-    return true;
+    if (va)
+        return true;
+    return false;
 }
 
 ///////////////////////////////////////////////////////////
@@ -166,23 +168,33 @@ RemoteGDB::getregs()
     memset(gdbregs.regs, 0, gdbregs.size);
 
     if (context->readMiscRegWithEffect(MISCREG_PSTATE) &
-           PSTATE::am)
-        panic("In 32bit mode\n");
-
-    gdbregs.regs[RegPc] = htobe(context->readPC());
-    gdbregs.regs[RegNpc] = htobe(context->readNextPC());
-    for(int x = RegG0; x <= RegI0 + 7; x++)
-        gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0));
-
-    gdbregs.regs[RegFsr] = htobe(context->readMiscRegWithEffect(MISCREG_FSR));
-    gdbregs.regs[RegFprs] = htobe(context->readMiscRegWithEffect(MISCREG_FPRS));
-    gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1));
-    gdbregs.regs[RegState] = htobe(
-        context->readMiscRegWithEffect(MISCREG_CWP) |
-        context->readMiscRegWithEffect(MISCREG_PSTATE) << 8 |
-        context->readMiscRegWithEffect(MISCREG_ASI) << 24 |
-        context->readIntReg(NumIntArchRegs + 2) << 32);
-
+           PSTATE::am) {
+        uint32_t *regs;
+        regs = (uint32_t*)gdbregs.regs;
+        regs[Reg32Pc] = htobe((uint32_t)context->readPC());
+        regs[Reg32Npc] = htobe((uint32_t)context->readNextPC());
+        for(int x = RegG0; x <= RegI0 + 7; x++)
+            regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0));
+
+        regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1));
+        regs[Reg32Psr] = htobe((uint32_t)context->readMiscRegWithEffect(MISCREG_PSTATE));
+        regs[Reg32Fsr] = htobe((uint32_t)context->readMiscRegWithEffect(MISCREG_FSR));
+        regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2));
+    } else {
+        gdbregs.regs[RegPc] = htobe(context->readPC());
+        gdbregs.regs[RegNpc] = htobe(context->readNextPC());
+        for(int x = RegG0; x <= RegI0 + 7; x++)
+            gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0));
+
+        gdbregs.regs[RegFsr] = htobe(context->readMiscRegWithEffect(MISCREG_FSR));
+        gdbregs.regs[RegFprs] = htobe(context->readMiscRegWithEffect(MISCREG_FPRS));
+        gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1));
+        gdbregs.regs[RegState] = htobe(
+            context->readMiscRegWithEffect(MISCREG_CWP) |
+            context->readMiscRegWithEffect(MISCREG_PSTATE) << 8 |
+            context->readMiscRegWithEffect(MISCREG_ASI) << 24 |
+            context->readIntReg(NumIntArchRegs + 2) << 32);
+    }
 
     DPRINTF(GDBRead, "PC=%#x\n", gdbregs.regs[RegPc]);
 
index 17ad7a8e65516ff383cfe446dc6aee8c174c8dc3..b97961a34a2efa84b7ea797f23e6ab9b9f426537 100644 (file)
@@ -53,7 +53,9 @@ namespace SparcISA
             RegF0 = 32,
             RegPc = 64, RegNpc, RegState, RegFsr, RegFprs, RegY,
             /*RegState contains data in same format as tstate */
-            NumGDBRegs
+            Reg32Y = 64, Reg32Psr = 65, Reg32Tbr = 66, Reg32Pc = 67,
+            Reg32Npc = 68, Reg32Fsr = 69, Reg32Csr = 70,
+            NumGDBRegs = RegY
         };
 
       public:
index 293f667d66e4654b15e7a2c4c335d915b50b4f76..82b1ed175de378bd069de06aee49ec05c9397cc9 100644 (file)
@@ -204,7 +204,8 @@ insertAllLocked:
 
 
 TlbEntry*
-TLB::lookup(Addr va, int partition_id, bool real, int context_id)
+TLB::lookup(Addr va, int partition_id, bool real, int context_id, bool
+        update_used)
 {
     MapIter i;
     TlbRange tr;
@@ -230,7 +231,10 @@ TLB::lookup(Addr va, int partition_id, bool real, int context_id)
     t = i->second;
     DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(),
             t->pte.size());
-    if (!t->used) {
+
+    // Update the used bits only if this is a real access (not a fake one from
+    // virttophys()
+    if (!t->used && update_used) {
         t->used = true;
         usedEntries++;
         if (usedEntries == size) {
@@ -797,13 +801,11 @@ handleQueueRegAccess:
 
 handleSparcErrorRegAccess:
     if (!hpriv) {
-        if (priv) {
-            writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+        writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+        if (priv)
             return new DataAccessException;
-        } else {
-            writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+         else
             return new PrivilegedAction;
-        }
     }
     goto regAccessOk;
 
@@ -821,8 +823,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
 {
     Addr va = pkt->getAddr();
     ASI asi = (ASI)pkt->req->getAsi();
-    uint64_t temp, data;
-    uint64_t tsbtemp, cnftemp;
+    uint64_t temp;
 
     DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
          (uint32_t)pkt->req->getAsi(), pkt->getAddr());
@@ -942,64 +943,36 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
         }
         break;
       case ASI_DMMU_TSB_PS0_PTR_REG:
-        temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
-        if (bits(temp,12,0) == 0) {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG);
-        } else {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG);
-        }
-        data = mbits(tsbtemp,63,13);
-        data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
-            mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
-        pkt->set(data);
+        pkt->set(MakeTsbPtr(Ps0,
+            tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS),
+            tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0),
+            tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+            tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0),
+            tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)));
         break;
       case ASI_DMMU_TSB_PS1_PTR_REG:
-        temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
-        if (bits(temp,12,0) == 0) {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG);
-        } else {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG);
-        }
-        data = mbits(tsbtemp,63,13);
-        if (bits(tsbtemp,12,12))
-            data |= ULL(1) << (13+bits(tsbtemp,3,0));
-        data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
-            mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
-        pkt->set(data);
+        pkt->set(MakeTsbPtr(Ps1,
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)));
         break;
       case ASI_IMMU_TSB_PS0_PTR_REG:
-        temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
-        if (bits(temp,12,0) == 0) {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
-        } else {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
-        }
-        data = mbits(tsbtemp,63,13);
-        data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
-            mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
-        pkt->set(data);
+          pkt->set(MakeTsbPtr(Ps0,
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)));
         break;
       case ASI_IMMU_TSB_PS1_PTR_REG:
-        temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
-        if (bits(temp,12,0) == 0) {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
-        } else {
-            tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1);
-            cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
-        }
-        data = mbits(tsbtemp,63,13);
-        if (bits(tsbtemp,12,12))
-            data |= ULL(1) << (13+bits(tsbtemp,3,0));
-        data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
-            mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
-        pkt->set(data);
+          pkt->set(MakeTsbPtr(Ps1,
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)));
         break;
 
       default:
@@ -1244,6 +1217,64 @@ doMmuWriteError:
     return tc->getCpuPtr()->cycles(1);
 }
 
+void
+DTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs)
+{
+    uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0);
+    ptrs[0] = MakeTsbPtr(Ps0, tag_access,
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
+    ptrs[1] = MakeTsbPtr(Ps1, tag_access,
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
+    ptrs[2] = MakeTsbPtr(Ps0, tag_access,
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
+    ptrs[3] = MakeTsbPtr(Ps1, tag_access,
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1),
+                tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
+}
+
+
+
+
+
+uint64_t
+DTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb,
+        uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config)
+{
+    uint64_t tsb;
+    uint64_t config;
+
+    if (bits(tag_access, 12,0) == 0) {
+        tsb = c0_tsb;
+        config = c0_config;
+    } else {
+        tsb = cX_tsb;
+        config = cX_config;
+    }
+
+    uint64_t ptr = mbits(tsb,63,13);
+    bool split = bits(tsb,12,12);
+    int tsb_size = bits(tsb,3,0);
+    int page_size = (ps == Ps0) ? bits(config, 2,0) : bits(config,10,8);
+
+    if (ps == Ps1  && split)
+        ptr |= ULL(1) << (13 + tsb_size);
+    ptr |= (tag_access >> (9 + page_size * 3)) & mask(12+tsb_size, 4);
+
+    return ptr;
+}
+
+
 void
 TLB::serialize(std::ostream &os)
 {
index 34e5f5feb877163fbcf1f964be2c37e1cf62729f..b5f02c62e94872cfc7c7f6f72029c7afe7d77fe0 100644 (file)
@@ -78,17 +78,25 @@ class TLB : public SimObject
         Nucleus = 2
     };
 
-
+    enum TsbPageSize {
+        Ps0,
+        Ps1
+    };
+  public:
     /** lookup an entry in the TLB based on the partition id, and real bit if
      * real is true or the partition id, and context id if real is false.
      * @param va the virtual address not shifted (e.g. bottom 13 bits are 0)
      * @param paritition_id partition this entry is for
      * @param real is this a real->phys or virt->phys translation
      * @param context_id if this is virt->phys what context
+     * @param update_used should ew update the used bits in the entries on not
+     * useful if we are trying to do a va->pa without mucking with any state for
+     * a debug read for example.
      * @return A pointer to a tlb entry
      */
-    TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0);
-
+    TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0,
+            bool update_used = true);
+  protected:
     /** Insert a PTE into the TLB. */
     void insert(Addr vpn, int partition_id, int context_id, bool real,
             const PageTableEntry& PTE, int entry = -1);
@@ -163,12 +171,17 @@ class DTB : public TLB
     Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
     Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
     Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
+    void GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs);
 
   private:
     void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
             bool se, FaultTypes ft, int asi);
     void writeTagAccess(ThreadContext *tc, Addr va, int context);
 
+    uint64_t MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb,
+        uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config);
+
+
     TlbEntry *cacheEntry[2];
     ASI cacheAsi[2];
 };
index 429126b70fa6c04c4f8d399d3ced4be2c9aca5ff..cb545185a7797775cacaa68ad801b95cf2cf26dc 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Authors: Nathan Binkert
- *          Steve Reinhardt
- *          Ali Saidi
+ * Authors: Ali Saidi
  */
 
 #include <string>
 
 #include "arch/sparc/vtophys.hh"
+#include "arch/sparc/tlb.hh"
+#include "base/compiler.hh"
 #include "base/chunk_generator.hh"
 #include "base/trace.hh"
 #include "cpu/thread_context.hh"
@@ -42,37 +42,83 @@ using namespace std;
 
 namespace SparcISA
 {
-    PageTableEntry kernel_pte_lookup(FunctionalPort *mem,
-            Addr ptbr, VAddr vaddr)
-    {
-        PageTableEntry pte(4);
-        return pte;
-    }
-
     Addr vtophys(Addr vaddr)
     {
-        return vaddr;
+        // In SPARC it's almost always impossible to turn a VA->PA w/o a context
+        // The only times we can kinda do it are if we have a SegKPM mapping
+        // and can find the real address in the tlb or we have a physical
+        // adddress already (beacuse we are looking at the hypervisor)
+        // Either case is rare, so we'll just panic.
+
+        panic("vtophys() without context on SPARC largly worthless\n");
+        M5_DUMMY_RETURN
     }
 
     Addr vtophys(ThreadContext *tc, Addr addr)
     {
-        return addr;
-    }
+        // Here we have many options and are really implementing something like
+        // a fill handler to find the address since there isn't a multilevel
+        // table for us to walk around.
+        //
+        // 1. We are currently hyperpriv, return the address unmodified
+        // 2. The mmu is off return(ra->pa)
+        // 3. We are currently priv, use ctx0* tsbs to find the page
+        // 4. We are not priv, use ctxN0* tsbs to find the page
+        // For all accesses we check the tlbs first since it's possible that
+        // long standing pages (e.g. locked kernel mappings) won't be in the tsb
+        uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
 
+        bool hpriv = bits(tlbdata,0,0);
+        //bool priv = bits(tlbdata,2,2);
+        bool addr_mask = bits(tlbdata,3,3);
+        bool data_real = !bits(tlbdata,5,5);
+        bool inst_real = !bits(tlbdata,4,4);
+        bool ctx_zero  = bits(tlbdata,18,16) > 0;
+        int part_id = bits(tlbdata,15,8);
+        int pri_context = bits(tlbdata,47,32);
+        //int sec_context = bits(tlbdata,63,48);
 
-    void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
-    {
-    }
+        FunctionalPort *mem = tc->getPhysPort();
+        ITB* itb = tc->getITBPtr();
+        DTB* dtb = tc->getDTBPtr();
+        TlbEntry* tbe;
+        PageTableEntry pte;
+        Addr tsbs[4];
+        Addr va_tag;
+        TteTag ttetag;
 
-    void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
-    {
-    }
+        if (hpriv)
+            return addr;
 
-    void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
-    {
-    }
+        if (addr_mask)
+            addr = addr & VAddrAMask;
 
-    void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
-    {
+        tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , false);
+        if (tbe) goto foundtbe;
+
+        tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, false);
+        if (tbe) goto foundtbe;
+
+        // We didn't find it in the tlbs, so lets look at the TSBs
+        dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs);
+        va_tag = bits(addr, 63, 22);
+        for (int x = 0; x < 4; x++) {
+            ttetag = betoh(mem->read<uint64_t>(tsbs[x]));
+            if (ttetag.valid() && ttetag.va() == va_tag) {
+                pte.populate(betoh(mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t)),
+                        PageTableEntry::sun4v); // I think it's sun4v at least!
+                DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", addr,
+                        pte.paddrMask() | addr & pte.sizeMask());
+                goto foundpte;
+            }
+        }
+        panic("couldn't translate %#x\n", addr);
+
+foundtbe:
+        pte = tbe->pte;
+        DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr,
+                pte.paddrMask() | addr & pte.sizeMask());
+foundpte:
+        return pte.paddrMask() | addr & pte.sizeMask();
     }
 }
index 66679a565797d77a822252b78153082bf96b3c0d..f55967b538b706e37da90c04569c4834913a15ca 100644 (file)
@@ -46,11 +46,6 @@ kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, SparcISA::VAddr vaddr);
 Addr vtophys(Addr vaddr);
 Addr vtophys(ThreadContext *tc, Addr vaddr);
 
-void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len);
-void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len);
-void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
-void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
-
 };
 #endif // __ARCH_SPARC_VTOPHYS_H__
 
index 1fc0bad5d7dd72a1232fdb3d0c1297556dfbbcd9..0f1233677998af7b3d72b51e11c03b119e02b3cf 100644 (file)
@@ -44,6 +44,7 @@ mask(int nbits)
 }
 
 
+
 /**
  * Extract the bitfield from position 'first' to 'last' (inclusive)
  * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
@@ -69,6 +70,12 @@ mbits(T val, int first, int last)
     return val & (mask(first+1) & ~mask(last));
 }
 
+inline uint64_t
+mask(int first, int last)
+{
+    return mbits((uint64_t)-1LL, first, last);
+}
+
 /**
  * Sign-extend an N-bit value to 64 bits.
  */
index 8030c5a15a63c050e0add74e9b5152a3bafca89c..6cc4d9ca9edff80c51386a584b284aae54b48d2b 100644 (file)
@@ -34,6 +34,7 @@
  */
 
 #include "base/chunk_generator.hh"
+#include "cpu/thread_context.hh"
 #include "mem/vport.hh"
 
 void
@@ -70,3 +71,53 @@ VirtualPort::writeBlob(Addr addr, uint8_t *p, int size)
     }
 }
 
+void
+CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
+{
+    uint8_t *dst = (uint8_t *)dest;
+    VirtualPort *vp = tc->getVirtPort(tc);
+
+    vp->readBlob(src, dst, cplen);
+
+    tc->delVirtPort(vp);
+
+}
+
+void
+CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
+{
+    uint8_t *src = (uint8_t *)source;
+    VirtualPort *vp = tc->getVirtPort(tc);
+
+    vp->writeBlob(dest, src, cplen);
+
+    tc->delVirtPort(vp);
+}
+
+void
+CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
+{
+    int len = 0;
+    char *start = dst;
+    VirtualPort *vp = tc->getVirtPort(tc);
+
+    do {
+        vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
+    } while (len < maxlen && start[len++] != 0 );
+
+    tc->delVirtPort(vp);
+    dst[len] = 0;
+}
+
+void
+CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
+{
+    VirtualPort *vp = tc->getVirtPort(tc);
+    for (ChunkGenerator gen(vaddr, strlen(src), TheISA::PageBytes); !gen.done();
+            gen.next())
+    {
+        vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size());
+        src += gen.size();
+    }
+    tc->delVirtPort(vp);
+}
index c838362588dafc1c76a742c1665c2a0efce1e6ae..a8ceaa9fca2319536269ccfaf66dcfae9eb87fb5 100644 (file)
@@ -49,6 +49,7 @@
  * simple address masking operation (such as alpha super page accesses).
  */
 
+
 class VirtualPort  : public FunctionalPort
 {
   private:
@@ -75,5 +76,11 @@ class VirtualPort  : public FunctionalPort
     virtual void writeBlob(Addr addr, uint8_t *p, int size);
 };
 
+
+void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen);
+void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen);
+void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
+void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
+
 #endif //__MEM_VPORT_HH__