Optimized the TLB translations with some caching
--HG-- extra : convert_revision : f79f863393f918ff9363b2c261f8c0dfec64312e
This commit is contained in:
parent
fa4293af33
commit
5e70511bff
2 changed files with 106 additions and 32 deletions
|
@ -45,7 +45,7 @@ namespace SparcISA
|
||||||
{
|
{
|
||||||
|
|
||||||
TLB::TLB(const std::string &name, int s)
|
TLB::TLB(const std::string &name, int s)
|
||||||
: SimObject(name), size(s)
|
: SimObject(name), size(s), usedEntries(0), cacheValid(false)
|
||||||
{
|
{
|
||||||
// To make this work you'll have to change the hypervisor and OS
|
// To make this work you'll have to change the hypervisor and OS
|
||||||
if (size > 64)
|
if (size > 64)
|
||||||
|
@ -79,6 +79,8 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
|
||||||
TlbEntry *new_entry = NULL;
|
TlbEntry *new_entry = NULL;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
|
cacheValid = false;
|
||||||
|
|
||||||
DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n",
|
DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n",
|
||||||
va, PTE.paddr(), partition_id, context_id, (int)real);
|
va, PTE.paddr(), partition_id, context_id, (int)real);
|
||||||
|
|
||||||
|
@ -194,6 +196,8 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id)
|
||||||
TlbRange tr;
|
TlbRange tr;
|
||||||
MapIter i;
|
MapIter i;
|
||||||
|
|
||||||
|
cacheValid = false;
|
||||||
|
|
||||||
// Assemble full address structure
|
// Assemble full address structure
|
||||||
tr.va = va;
|
tr.va = va;
|
||||||
tr.size = va + MachineBytes;
|
tr.size = va + MachineBytes;
|
||||||
|
@ -217,6 +221,7 @@ void
|
||||||
TLB::demapContext(int partition_id, int context_id)
|
TLB::demapContext(int partition_id, int context_id)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
cacheValid = false;
|
||||||
for (x = 0; x < size; x++) {
|
for (x = 0; x < size; x++) {
|
||||||
if (tlb[x].range.contextId == context_id &&
|
if (tlb[x].range.contextId == context_id &&
|
||||||
tlb[x].range.partitionId == partition_id) {
|
tlb[x].range.partitionId == partition_id) {
|
||||||
|
@ -234,6 +239,7 @@ void
|
||||||
TLB::demapAll(int partition_id)
|
TLB::demapAll(int partition_id)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
cacheValid = false;
|
||||||
for (x = 0; x < size; x++) {
|
for (x = 0; x < size; x++) {
|
||||||
if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
|
if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
|
||||||
tlb[x].valid = false;
|
tlb[x].valid = false;
|
||||||
|
@ -250,6 +256,8 @@ void
|
||||||
TLB::invalidateAll()
|
TLB::invalidateAll()
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
cacheValid = false;
|
||||||
|
|
||||||
for (x = 0; x < size; x++) {
|
for (x = 0; x < size; x++) {
|
||||||
tlb[x].valid = false;
|
tlb[x].valid = false;
|
||||||
}
|
}
|
||||||
|
@ -337,7 +345,7 @@ DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
|
||||||
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a);
|
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DTB::writeTagAccess(ThreadContext *tc, Addr va, int context)
|
DTB::writeTagAccess(ThreadContext *tc, Addr va, int context)
|
||||||
{
|
{
|
||||||
TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context);
|
TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context);
|
||||||
|
@ -350,6 +358,29 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
|
||||||
{
|
{
|
||||||
uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
|
uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
|
||||||
|
|
||||||
|
Addr vaddr = req->getVaddr();
|
||||||
|
TlbEntry *e;
|
||||||
|
|
||||||
|
assert(req->getAsi() == ASI_IMPLICIT);
|
||||||
|
|
||||||
|
DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
|
||||||
|
vaddr, req->getSize());
|
||||||
|
|
||||||
|
// Be fast if we can!
|
||||||
|
if (cacheValid && cacheState == tlbdata) {
|
||||||
|
if (cacheEntry) {
|
||||||
|
if (cacheEntry->range.va < vaddr + sizeof(MachInst) &&
|
||||||
|
cacheEntry->range.va + cacheEntry->range.size >= vaddr) {
|
||||||
|
req->setPaddr(cacheEntry->pte.paddr() & ~(cacheEntry->pte.size()-1) |
|
||||||
|
vaddr & cacheEntry->pte.size()-1 );
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req->setPaddr(vaddr & PAddrImplMask);
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool hpriv = bits(tlbdata,0,0);
|
bool hpriv = bits(tlbdata,0,0);
|
||||||
bool red = bits(tlbdata,1,1);
|
bool red = bits(tlbdata,1,1);
|
||||||
bool priv = bits(tlbdata,2,2);
|
bool priv = bits(tlbdata,2,2);
|
||||||
|
@ -359,21 +390,14 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
|
||||||
int part_id = bits(tlbdata,15,8);
|
int part_id = bits(tlbdata,15,8);
|
||||||
int tl = bits(tlbdata,18,16);
|
int tl = bits(tlbdata,18,16);
|
||||||
int pri_context = bits(tlbdata,47,32);
|
int pri_context = bits(tlbdata,47,32);
|
||||||
|
|
||||||
Addr vaddr = req->getVaddr();
|
|
||||||
int context;
|
int context;
|
||||||
ContextType ct;
|
ContextType ct;
|
||||||
int asi;
|
int asi;
|
||||||
bool real = false;
|
bool real = false;
|
||||||
TlbEntry *e;
|
|
||||||
|
|
||||||
DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
|
|
||||||
vaddr, req->getSize());
|
|
||||||
DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n",
|
DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n",
|
||||||
priv, hpriv, red, lsu_im, part_id);
|
priv, hpriv, red, lsu_im, part_id);
|
||||||
|
|
||||||
assert(req->getAsi() == ASI_IMPLICIT);
|
|
||||||
|
|
||||||
if (tl > 0) {
|
if (tl > 0) {
|
||||||
asi = ASI_N;
|
asi = ASI_N;
|
||||||
ct = Nucleus;
|
ct = Nucleus;
|
||||||
|
@ -385,12 +409,15 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( hpriv || red ) {
|
if ( hpriv || red ) {
|
||||||
req->setPaddr(req->getVaddr() & PAddrImplMask);
|
cacheValid = true;
|
||||||
|
cacheState = tlbdata;
|
||||||
|
cacheEntry = NULL;
|
||||||
|
req->setPaddr(vaddr & PAddrImplMask);
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the asi is unaligned trap
|
// If the access is unaligned trap
|
||||||
if (vaddr & req->getSize()-1) {
|
if (vaddr & 0x3) {
|
||||||
writeSfsr(tc, false, ct, false, OtherFault, asi);
|
writeSfsr(tc, false, ct, false, OtherFault, asi);
|
||||||
return new MemAddressNotAligned;
|
return new MemAddressNotAligned;
|
||||||
}
|
}
|
||||||
|
@ -404,7 +431,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lsu_im) {
|
if (!lsu_im) {
|
||||||
e = lookup(req->getVaddr(), part_id, true);
|
e = lookup(vaddr, part_id, true);
|
||||||
real = true;
|
real = true;
|
||||||
context = 0;
|
context = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -426,9 +453,14 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
|
||||||
return new InstructionAccessException;
|
return new InstructionAccessException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cache translation date for next translation
|
||||||
|
cacheValid = true;
|
||||||
|
cacheState = tlbdata;
|
||||||
|
cacheEntry = e;
|
||||||
|
|
||||||
req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
|
req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
|
||||||
req->getVaddr() & e->pte.size()-1 );
|
vaddr & e->pte.size()-1 );
|
||||||
DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
|
DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,8 +471,40 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
|
||||||
{
|
{
|
||||||
/* @todo this could really use some profiling and fixing to make it faster! */
|
/* @todo this could really use some profiling and fixing to make it faster! */
|
||||||
uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
|
uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
|
||||||
|
Addr vaddr = req->getVaddr();
|
||||||
|
Addr size = req->getSize();
|
||||||
|
ASI asi;
|
||||||
|
asi = (ASI)req->getAsi();
|
||||||
|
bool implicit = false;
|
||||||
bool hpriv = bits(tlbdata,0,0);
|
bool hpriv = bits(tlbdata,0,0);
|
||||||
|
|
||||||
|
DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
|
||||||
|
vaddr, size, asi);
|
||||||
|
|
||||||
|
if (asi == ASI_IMPLICIT)
|
||||||
|
implicit = true;
|
||||||
|
|
||||||
|
if (hpriv && implicit) {
|
||||||
|
req->setPaddr(vaddr & PAddrImplMask);
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Be fast if we can!
|
||||||
|
if (cacheValid && cacheState == tlbdata) {
|
||||||
|
if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size &&
|
||||||
|
cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) {
|
||||||
|
req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) |
|
||||||
|
vaddr & cacheEntry[0]->pte.size()-1 );
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size &&
|
||||||
|
cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) {
|
||||||
|
req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) |
|
||||||
|
vaddr & cacheEntry[1]->pte.size()-1 );
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool red = bits(tlbdata,1,1);
|
bool red = bits(tlbdata,1,1);
|
||||||
bool priv = bits(tlbdata,2,2);
|
bool priv = bits(tlbdata,2,2);
|
||||||
bool addr_mask = bits(tlbdata,3,3);
|
bool addr_mask = bits(tlbdata,3,3);
|
||||||
|
@ -451,23 +515,14 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
|
||||||
int pri_context = bits(tlbdata,47,32);
|
int pri_context = bits(tlbdata,47,32);
|
||||||
int sec_context = bits(tlbdata,47,32);
|
int sec_context = bits(tlbdata,47,32);
|
||||||
|
|
||||||
bool implicit = false;
|
|
||||||
bool real = false;
|
bool real = false;
|
||||||
Addr vaddr = req->getVaddr();
|
|
||||||
Addr size = req->getSize();
|
|
||||||
ContextType ct = Primary;
|
ContextType ct = Primary;
|
||||||
int context = 0;
|
int context = 0;
|
||||||
ASI asi;
|
|
||||||
|
|
||||||
TlbEntry *e;
|
TlbEntry *e;
|
||||||
|
|
||||||
asi = (ASI)req->getAsi();
|
|
||||||
DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
|
|
||||||
vaddr, size, asi);
|
|
||||||
DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n",
|
DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n",
|
||||||
priv, hpriv, red, lsu_dm, part_id);
|
priv, hpriv, red, lsu_dm, part_id);
|
||||||
if (asi == ASI_IMPLICIT)
|
|
||||||
implicit = true;
|
|
||||||
|
|
||||||
if (implicit) {
|
if (implicit) {
|
||||||
if (tl > 0) {
|
if (tl > 0) {
|
||||||
|
@ -562,11 +617,11 @@ continueDtbFlow:
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
|
if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
|
||||||
req->setPaddr(req->getVaddr() & PAddrImplMask);
|
req->setPaddr(vaddr & PAddrImplMask);
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = lookup(req->getVaddr(), part_id, real, context);
|
e = lookup(vaddr, part_id, real, context);
|
||||||
|
|
||||||
if (e == NULL || !e->valid) {
|
if (e == NULL || !e->valid) {
|
||||||
tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
|
tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
|
||||||
|
@ -599,9 +654,21 @@ continueDtbFlow:
|
||||||
return new DataAccessException;
|
return new DataAccessException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cache translation date for next translation
|
||||||
|
cacheValid = true;
|
||||||
|
cacheState = tlbdata;
|
||||||
|
if (cacheEntry[0] != e && cacheEntry[1] != e) {
|
||||||
|
cacheEntry[1] = cacheEntry[0];
|
||||||
|
cacheEntry[0] = e;
|
||||||
|
cacheAsi[1] = cacheAsi[0];
|
||||||
|
cacheAsi[0] = asi;
|
||||||
|
if (implicit)
|
||||||
|
cacheAsi[0] = (ASI)0;
|
||||||
|
}
|
||||||
|
|
||||||
req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
|
req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
|
||||||
req->getVaddr() & e->pte.size()-1);
|
vaddr & e->pte.size()-1);
|
||||||
DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
|
DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
|
||||||
return NoFault;
|
return NoFault;
|
||||||
/** Normal flow ends here. */
|
/** Normal flow ends here. */
|
||||||
|
|
||||||
|
@ -773,8 +840,6 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
|
||||||
data = mbits(tsbtemp,63,13);
|
data = mbits(tsbtemp,63,13);
|
||||||
data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
|
data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
|
||||||
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
|
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
|
||||||
warn("base addr: %#X tag access: %#X page size: %#X tsb size: %#X\n",
|
|
||||||
bits(tsbtemp,63,13), temp, bits(cnftemp,2,0), bits(tsbtemp,3,0));
|
|
||||||
pkt->set(data);
|
pkt->set(data);
|
||||||
break;
|
break;
|
||||||
case ASI_DMMU_TSB_PS1_PTR_REG:
|
case ASI_DMMU_TSB_PS1_PTR_REG:
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#ifndef __ARCH_SPARC_TLB_HH__
|
#ifndef __ARCH_SPARC_TLB_HH__
|
||||||
#define __ARCH_SPARC_TLB_HH__
|
#define __ARCH_SPARC_TLB_HH__
|
||||||
|
|
||||||
|
#include "arch/sparc/asi.hh"
|
||||||
#include "arch/sparc/tlb_map.hh"
|
#include "arch/sparc/tlb_map.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "mem/request.hh"
|
#include "mem/request.hh"
|
||||||
|
@ -54,6 +55,9 @@ class TLB : public SimObject
|
||||||
int size;
|
int size;
|
||||||
int usedEntries;
|
int usedEntries;
|
||||||
|
|
||||||
|
uint64_t cacheState;
|
||||||
|
bool cacheValid;
|
||||||
|
|
||||||
enum FaultTypes {
|
enum FaultTypes {
|
||||||
OtherFault = 0,
|
OtherFault = 0,
|
||||||
PrivViolation = 0x1,
|
PrivViolation = 0x1,
|
||||||
|
@ -131,6 +135,7 @@ class ITB : public TLB
|
||||||
public:
|
public:
|
||||||
ITB(const std::string &name, int size) : TLB(name, size)
|
ITB(const std::string &name, int size) : TLB(name, size)
|
||||||
{
|
{
|
||||||
|
cacheEntry = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault translate(RequestPtr &req, ThreadContext *tc);
|
Fault translate(RequestPtr &req, ThreadContext *tc);
|
||||||
|
@ -138,6 +143,7 @@ class ITB : public TLB
|
||||||
void writeSfsr(ThreadContext *tc, bool write, ContextType ct,
|
void writeSfsr(ThreadContext *tc, bool write, ContextType ct,
|
||||||
bool se, FaultTypes ft, int asi);
|
bool se, FaultTypes ft, int asi);
|
||||||
void writeTagAccess(ThreadContext *tc, Addr va, int context);
|
void writeTagAccess(ThreadContext *tc, Addr va, int context);
|
||||||
|
TlbEntry *cacheEntry;
|
||||||
friend class DTB;
|
friend class DTB;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,6 +152,8 @@ class DTB : public TLB
|
||||||
public:
|
public:
|
||||||
DTB(const std::string &name, int size) : TLB(name, size)
|
DTB(const std::string &name, int size) : TLB(name, size)
|
||||||
{
|
{
|
||||||
|
cacheEntry[0] = NULL;
|
||||||
|
cacheEntry[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
|
Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
|
||||||
|
@ -157,7 +165,8 @@ class DTB : public TLB
|
||||||
bool se, FaultTypes ft, int asi);
|
bool se, FaultTypes ft, int asi);
|
||||||
void writeTagAccess(ThreadContext *tc, Addr va, int context);
|
void writeTagAccess(ThreadContext *tc, Addr va, int context);
|
||||||
|
|
||||||
|
TlbEntry *cacheEntry[2];
|
||||||
|
ASI cacheAsi[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue