Merge zizzer:/bk/newmem
into zeep.pool:/z/saidi/work/m5.newmem --HG-- extra : convert_revision : 10d4dc08411c7a433a7194e94f69ca1d639a1ce7
This commit is contained in:
commit
9062525c23
14 changed files with 300 additions and 168 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
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));
|
||||
|
||||
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);
|
||||
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]);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
Loading…
Reference in a new issue