summaryrefslogtreecommitdiff
path: root/src/arch/sparc
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2007-02-18 19:57:46 -0500
committerAli Saidi <saidi@eecs.umich.edu>2007-02-18 19:57:46 -0500
commitbd367d4825e26ab3f8e01f3b4bdb914bb0ef756a (patch)
treed7969c7a0dc5eb9097280ad1e56cca8048a6b0ed /src/arch/sparc
parentb2fd2a813d75815ed2ceaa447590986a29ee99b8 (diff)
downloadgem5-bd367d4825e26ab3f8e01f3b4bdb914bb0ef756a.tar.xz
implement vtophys and 32bit gdb support
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
Diffstat (limited to 'src/arch/sparc')
-rw-r--r--src/arch/sparc/arguments.hh2
-rw-r--r--src/arch/sparc/isa_traits.hh5
-rw-r--r--src/arch/sparc/pagetable.hh21
-rw-r--r--src/arch/sparc/remote_gdb.cc48
-rw-r--r--src/arch/sparc/remote_gdb.hh4
-rw-r--r--src/arch/sparc/tlb.cc153
-rw-r--r--src/arch/sparc/tlb.hh19
-rw-r--r--src/arch/sparc/vtophys.cc94
-rw-r--r--src/arch/sparc/vtophys.hh5
9 files changed, 237 insertions, 114 deletions
diff --git a/src/arch/sparc/arguments.hh b/src/arch/sparc/arguments.hh
index 8f925dd25..5596f7408 100644
--- a/src/arch/sparc/arguments.hh
+++ b/src/arch/sparc/arguments.hh
@@ -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;
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
index 64ae6abd8..1fbdd160d 100644
--- a/src/arch/sparc/isa_traits.hh
+++ b/src/arch/sparc/isa_traits.hh
@@ -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;
diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh
index fc01e82da..980225052 100644
--- a/src/arch/sparc/pagetable.hh
+++ b/src/arch/sparc/pagetable.hh
@@ -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 {
diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc
index 2221576a3..e2ea7a84d 100644
--- a/src/arch/sparc/remote_gdb.cc
+++ b/src/arch/sparc/remote_gdb.cc
@@ -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]);
diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh
index 17ad7a8e6..b97961a34 100644
--- a/src/arch/sparc/remote_gdb.hh
+++ b/src/arch/sparc/remote_gdb.hh
@@ -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:
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index 293f667d6..82b1ed175 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -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:
@@ -1245,6 +1218,64 @@ doMmuWriteError:
}
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)
{
SERIALIZE_SCALAR(size);
diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh
index 34e5f5feb..b5f02c62e 100644
--- a/src/arch/sparc/tlb.hh
+++ b/src/arch/sparc/tlb.hh
@@ -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];
};
diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc
index 429126b70..cb545185a 100644
--- a/src/arch/sparc/vtophys.cc
+++ b/src/arch/sparc/vtophys.cc
@@ -25,14 +25,14 @@
* (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();
}
}
diff --git a/src/arch/sparc/vtophys.hh b/src/arch/sparc/vtophys.hh
index 66679a565..f55967b53 100644
--- a/src/arch/sparc/vtophys.hh
+++ b/src/arch/sparc/vtophys.hh
@@ -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__