* Authors: Ali Saidi
*/
+#include "arch/sparc/tlb.hh"
+
#include <cstring>
#include "arch/sparc/asi.hh"
+#include "arch/sparc/faults.hh"
+#include "arch/sparc/interrupts.hh"
#include "arch/sparc/registers.hh"
-#include "arch/sparc/tlb.hh"
#include "base/bitfield.hh"
+#include "base/compiler.hh"
#include "base/trace.hh"
-#include "cpu/thread_context.hh"
#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
+#include "debug/IPR.hh"
+#include "debug/TLB.hh"
#include "mem/packet_access.hh"
#include "mem/request.hh"
+#include "sim/full_system.hh"
#include "sim/system.hh"
/* @todo remove some of the magic constants. -- ali
TLB::TLB(const Params *p)
: BaseTLB(p), size(p->size), usedEntries(0), lastReplaced(0),
- cacheValid(false)
+ cacheState(0), cacheValid(false)
{
// To make this work you'll have to change the hypervisor and OS
if (size > 64)
}
}
-/*
- i = lookupTable.find(tr);
- if (i != lookupTable.end()) {
- i->second->valid = false;
- if (i->second->used) {
- i->second->used = false;
- usedEntries--;
- }
- freeList.push_front(i->second);
- DPRINTF(TLB, "TLB: Found conflicting entry %#X , deleting it\n",
- i->second);
- lookupTable.erase(i);
- }
-*/
-
if (entry != -1) {
assert(entry < size && entry >= 0);
new_entry = &tlb[entry];
lastReplaced = x;
new_entry = &tlb[x];
}
- /*
- for (x = 0; x < size; x++) {
- if (!tlb[x].valid || !tlb[x].used) {
- new_entry = &tlb[x];
- break;
- }
- }*/
}
insertAllLocked:
for (int x = 0; x < size; x++) {
if (tlb[x].range.contextId == context_id &&
tlb[x].range.partitionId == partition_id) {
- if (tlb[x].valid == true) {
+ if (tlb[x].valid) {
freeList.push_front(&tlb[x]);
}
tlb[x].valid = false;
}
void
-TLB::invalidateAll()
+TLB::flushAll()
{
cacheValid = false;
lookupTable.clear();
for (int x = 0; x < size; x++) {
- if (tlb[x].valid == true)
+ if (tlb[x].valid)
freeList.push_back(&tlb[x]);
tlb[x].valid = false;
tlb[x].used = false;
}
Fault
-TLB::translateInst(RequestPtr req, ThreadContext *tc)
+TLB::translateInst(const RequestPtr &req, ThreadContext *tc)
{
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
Addr vaddr = req->getVaddr();
TlbEntry *e;
- assert(req->getAsi() == ASI_IMPLICIT);
+ assert(req->getArchFlags() == ASI_IMPLICIT);
DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
vaddr, req->getSize());
// If the access is unaligned trap
if (vaddr & 0x3) {
writeSfsr(false, ct, false, OtherFault, asi);
- return new MemAddressNotAligned;
+ return std::make_shared<MemAddressNotAligned>();
}
if (addr_mask)
if (!validVirtualAddress(vaddr, addr_mask)) {
writeSfsr(false, ct, false, VaOutOfRange, asi);
- return new InstructionAccessException;
+ return std::make_shared<InstructionAccessException>();
}
if (!lsu_im) {
if (e == NULL || !e->valid) {
writeTagAccess(vaddr, context);
- if (real)
- return new InstructionRealTranslationMiss;
- else
-#if FULL_SYSTEM
- return new FastInstructionAccessMMUMiss;
-#else
- return new FastInstructionAccessMMUMiss(req->getVaddr());
-#endif
+ if (real) {
+ return std::make_shared<InstructionRealTranslationMiss>();
+ } else {
+ if (FullSystem)
+ return std::make_shared<FastInstructionAccessMMUMiss>();
+ else
+ return std::make_shared<FastInstructionAccessMMUMiss>(
+ req->getVaddr());
+ }
}
// were not priviledged accesing priv page
if (!priv && e->pte.priv()) {
writeTagAccess(vaddr, context);
writeSfsr(false, ct, false, PrivViolation, asi);
- return new InstructionAccessException;
+ return std::make_shared<InstructionAccessException>();
}
// cache translation date for next translation
}
Fault
-TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
+TLB::translateData(const RequestPtr &req, ThreadContext *tc, bool write)
{
/*
* @todo this could really use some profiling and fixing to make
Addr vaddr = req->getVaddr();
Addr size = req->getSize();
ASI asi;
- asi = (ASI)req->getAsi();
+ asi = (ASI)req->getArchFlags();
bool implicit = false;
bool hpriv = bits(tlbdata,0,0);
bool unaligned = vaddr & (size - 1);
ce_va < vaddr + size && ce_va + ce->range.size > vaddr &&
(!write || ce->pte.writable())) {
req->setPaddr(ce->pte.translate(vaddr));
- if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1)
- req->setFlags(Request::UNCACHEABLE);
+ if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) {
+ req->setFlags(
+ Request::UNCACHEABLE | Request::STRICT_ORDER);
+ }
DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
return NoFault;
} // if matched
ce_va < vaddr + size && ce_va + ce->range.size > vaddr &&
(!write || ce->pte.writable())) {
req->setPaddr(ce->pte.translate(vaddr));
- if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1)
- req->setFlags(Request::UNCACHEABLE);
+ if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) {
+ req->setFlags(
+ Request::UNCACHEABLE | Request::STRICT_ORDER);
+ }
DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
return NoFault;
} // if matched
}
} else {
// We need to check for priv level/asi priv
- if (!priv && !hpriv && !AsiIsUnPriv(asi)) {
+ if (!priv && !hpriv && !asiIsUnPriv(asi)) {
// It appears that context should be Nucleus in these cases?
writeSfsr(vaddr, write, Nucleus, false, IllegalAsi, asi);
- return new PrivilegedAction;
+ return std::make_shared<PrivilegedAction>();
}
- if (!hpriv && AsiIsHPriv(asi)) {
+ if (!hpriv && asiIsHPriv(asi)) {
writeSfsr(vaddr, write, Nucleus, false, IllegalAsi, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
- if (AsiIsPrimary(asi)) {
+ if (asiIsPrimary(asi)) {
context = pri_context;
ct = Primary;
- } else if (AsiIsSecondary(asi)) {
+ } else if (asiIsSecondary(asi)) {
context = sec_context;
ct = Secondary;
- } else if (AsiIsNucleus(asi)) {
+ } else if (asiIsNucleus(asi)) {
ct = Nucleus;
context = 0;
} else { // ????
}
if (!implicit && asi != ASI_P && asi != ASI_S) {
- if (AsiIsLittle(asi))
+ if (asiIsLittle(asi))
panic("Little Endian ASIs not supported\n");
//XXX It's unclear from looking at the documentation how a no fault
- //load differs from a regular one, other than what happens concerning
- //nfo and e bits in the TTE
-// if (AsiIsNoFault(asi))
+ // load differs from a regular one, other than what happens concerning
+ // nfo and e bits in the TTE
+// if (asiIsNoFault(asi))
// panic("No Fault ASIs not supported\n");
- if (AsiIsPartialStore(asi))
+ if (asiIsPartialStore(asi))
panic("Partial Store ASIs not supported\n");
- if (AsiIsCmt(asi))
+ if (asiIsCmt(asi))
panic("Cmt ASI registers not implmented\n");
- if (AsiIsInterrupt(asi))
+ if (asiIsInterrupt(asi))
goto handleIntRegAccess;
- if (AsiIsMmu(asi))
+ if (asiIsMmu(asi))
goto handleMmuRegAccess;
- if (AsiIsScratchPad(asi))
+ if (asiIsScratchPad(asi))
goto handleScratchRegAccess;
- if (AsiIsQueue(asi))
+ if (asiIsQueue(asi))
goto handleQueueRegAccess;
- if (AsiIsSparcError(asi))
+ if (asiIsSparcError(asi))
goto handleSparcErrorRegAccess;
- if (!AsiIsReal(asi) && !AsiIsNucleus(asi) && !AsiIsAsIfUser(asi) &&
- !AsiIsTwin(asi) && !AsiIsBlock(asi) && !AsiIsNoFault(asi))
+ if (!asiIsReal(asi) && !asiIsNucleus(asi) && !asiIsAsIfUser(asi) &&
+ !asiIsTwin(asi) && !asiIsBlock(asi) && !asiIsNoFault(asi))
panic("Accessing ASI %#X. Should we?\n", asi);
}
// If the asi is unaligned trap
if (unaligned) {
writeSfsr(vaddr, false, ct, false, OtherFault, asi);
- return new MemAddressNotAligned;
+ return std::make_shared<MemAddressNotAligned>();
}
if (addr_mask)
if (!validVirtualAddress(vaddr, addr_mask)) {
writeSfsr(vaddr, false, ct, true, VaOutOfRange, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
- if ((!lsu_dm && !hpriv && !red) || AsiIsReal(asi)) {
+ if ((!lsu_dm && !hpriv && !red) || asiIsReal(asi)) {
real = true;
context = 0;
}
- if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
+ if (hpriv && (implicit || (!asiIsAsIfUser(asi) && !asiIsReal(asi)))) {
req->setPaddr(vaddr & PAddrImplMask);
return NoFault;
}
if (e == NULL || !e->valid) {
writeTagAccess(vaddr, context);
DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
- if (real)
- return new DataRealTranslationMiss;
- else
-#if FULL_SYSTEM
- return new FastDataAccessMMUMiss;
-#else
- return new FastDataAccessMMUMiss(req->getVaddr());
-#endif
+ if (real) {
+ return std::make_shared<DataRealTranslationMiss>();
+ } else {
+ if (FullSystem)
+ return std::make_shared<FastDataAccessMMUMiss>();
+ else
+ return std::make_shared<FastDataAccessMMUMiss>(
+ req->getVaddr());
+ }
}
if (!priv && e->pte.priv()) {
writeTagAccess(vaddr, context);
writeSfsr(vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
if (write && !e->pte.writable()) {
writeTagAccess(vaddr, context);
writeSfsr(vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
- return new FastDataAccessProtection;
+ return std::make_shared<FastDataAccessProtection>();
}
- if (e->pte.nofault() && !AsiIsNoFault(asi)) {
+ if (e->pte.nofault() && !asiIsNoFault(asi)) {
writeTagAccess(vaddr, context);
writeSfsr(vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
- if (e->pte.sideffect() && AsiIsNoFault(asi)) {
+ if (e->pte.sideffect() && asiIsNoFault(asi)) {
writeTagAccess(vaddr, context);
writeSfsr(vaddr, write, ct, e->pte.sideffect(), SideEffect, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
if (e->pte.sideffect() || (e->pte.paddr() >> 39) & 1)
- req->setFlags(Request::UNCACHEABLE);
+ req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
// cache translation date for next translation
cacheState = tlbdata;
if (!hpriv) {
writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi);
if (priv)
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
else
- return new PrivilegedAction;
+ return std::make_shared<PrivilegedAction>();
}
if ((asi == ASI_SWVR_UDB_INTR_W && !write) ||
(asi == ASI_SWVR_UDB_INTR_R && write)) {
writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
goto regAccessOk;
handleScratchRegAccess:
if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
goto regAccessOk;
handleQueueRegAccess:
if (!priv && !hpriv) {
writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi);
- return new PrivilegedAction;
+ return std::make_shared<PrivilegedAction>();
}
if ((!hpriv && vaddr & 0xF) || vaddr > 0x3f8 || vaddr < 0x3c0) {
writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
goto regAccessOk;
if (!hpriv) {
writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi);
if (priv)
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
else
- return new PrivilegedAction;
+ return std::make_shared<PrivilegedAction>();
}
goto regAccessOk;
regAccessOk:
handleMmuRegAccess:
DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
- req->setFlags(Request::MMAPED_IPR);
+ req->setFlags(Request::MMAPPED_IPR);
req->setPaddr(req->getVaddr());
return NoFault;
};
Fault
-TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
+TLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode)
{
if (mode == Execute)
return translateInst(req, tc);
}
void
-TLB::translateTiming(RequestPtr req, ThreadContext *tc,
+TLB::translateTiming(const RequestPtr &req, ThreadContext *tc,
Translation *translation, Mode mode)
{
assert(translation);
translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
}
-#if FULL_SYSTEM
+Fault
+TLB::finalizePhysical(const RequestPtr &req,
+ ThreadContext *tc, Mode mode) const
+{
+ return NoFault;
+}
-Tick
+Cycles
TLB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
{
Addr va = pkt->getAddr();
- ASI asi = (ASI)pkt->req->getAsi();
+ ASI asi = (ASI)pkt->req->getArchFlags();
uint64_t temp;
DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
- (uint32_t)pkt->req->getAsi(), pkt->getAddr());
+ (uint32_t)pkt->req->getArchFlags(), pkt->getAddr());
- TLB *itb = tc->getITBPtr();
+ TLB *itb = dynamic_cast<TLB *>(tc->getITBPtr());
switch (asi) {
case ASI_LSU_CONTROL_REG:
assert(va == 0);
- pkt->set(tc->readMiscReg(MISCREG_MMU_LSU_CTRL));
+ pkt->setBE(tc->readMiscReg(MISCREG_MMU_LSU_CTRL));
break;
case ASI_MMU:
switch (va) {
case 0x8:
- pkt->set(tc->readMiscReg(MISCREG_MMU_P_CONTEXT));
+ pkt->setBE(tc->readMiscReg(MISCREG_MMU_P_CONTEXT));
break;
case 0x10:
- pkt->set(tc->readMiscReg(MISCREG_MMU_S_CONTEXT));
+ pkt->setBE(tc->readMiscReg(MISCREG_MMU_S_CONTEXT));
break;
default:
goto doMmuReadError;
}
break;
case ASI_QUEUE:
- pkt->set(tc->readMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD +
+ pkt->setBE(tc->readMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD +
(va >> 4) - 0x3c));
break;
case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
assert(va == 0);
- pkt->set(c0_tsb_ps0);
+ pkt->setBE(c0_tsb_ps0);
break;
case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
assert(va == 0);
- pkt->set(c0_tsb_ps1);
+ pkt->setBE(c0_tsb_ps1);
break;
case ASI_DMMU_CTXT_ZERO_CONFIG:
assert(va == 0);
- pkt->set(c0_config);
+ pkt->setBE(c0_config);
break;
case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
assert(va == 0);
- pkt->set(itb->c0_tsb_ps0);
+ pkt->setBE(itb->c0_tsb_ps0);
break;
case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
assert(va == 0);
- pkt->set(itb->c0_tsb_ps1);
+ pkt->setBE(itb->c0_tsb_ps1);
break;
case ASI_IMMU_CTXT_ZERO_CONFIG:
assert(va == 0);
- pkt->set(itb->c0_config);
+ pkt->setBE(itb->c0_config);
break;
case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
assert(va == 0);
- pkt->set(cx_tsb_ps0);
+ pkt->setBE(cx_tsb_ps0);
break;
case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
assert(va == 0);
- pkt->set(cx_tsb_ps1);
+ pkt->setBE(cx_tsb_ps1);
break;
case ASI_DMMU_CTXT_NONZERO_CONFIG:
assert(va == 0);
- pkt->set(cx_config);
+ pkt->setBE(cx_config);
break;
case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
assert(va == 0);
- pkt->set(itb->cx_tsb_ps0);
+ pkt->setBE(itb->cx_tsb_ps0);
break;
case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
assert(va == 0);
- pkt->set(itb->cx_tsb_ps1);
+ pkt->setBE(itb->cx_tsb_ps1);
break;
case ASI_IMMU_CTXT_NONZERO_CONFIG:
assert(va == 0);
- pkt->set(itb->cx_config);
+ pkt->setBE(itb->cx_config);
break;
case ASI_SPARC_ERROR_STATUS_REG:
- pkt->set((uint64_t)0);
+ pkt->setBE((uint64_t)0);
break;
case ASI_HYP_SCRATCHPAD:
case ASI_SCRATCHPAD:
- pkt->set(tc->readMiscReg(MISCREG_SCRATCHPAD_R0 + (va >> 3)));
+ pkt->setBE(tc->readMiscReg(MISCREG_SCRATCHPAD_R0 + (va >> 3)));
break;
case ASI_IMMU:
switch (va) {
case 0x0:
temp = itb->tag_access;
- pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
+ pkt->setBE(bits(temp,63,22) | bits(temp,12,0) << 48);
break;
case 0x18:
- pkt->set(itb->sfsr);
+ pkt->setBE(itb->sfsr);
break;
case 0x30:
- pkt->set(itb->tag_access);
+ pkt->setBE(itb->tag_access);
break;
default:
goto doMmuReadError;
switch (va) {
case 0x0:
temp = tag_access;
- pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
+ pkt->setBE(bits(temp,63,22) | bits(temp,12,0) << 48);
break;
case 0x18:
- pkt->set(sfsr);
+ pkt->setBE(sfsr);
break;
case 0x20:
- pkt->set(sfar);
+ pkt->setBE(sfar);
break;
case 0x30:
- pkt->set(tag_access);
+ pkt->setBE(tag_access);
break;
case 0x80:
- pkt->set(tc->readMiscReg(MISCREG_MMU_PART_ID));
+ pkt->setBE(tc->readMiscReg(MISCREG_MMU_PART_ID));
break;
default:
goto doMmuReadError;
}
break;
case ASI_DMMU_TSB_PS0_PTR_REG:
- pkt->set(MakeTsbPtr(Ps0,
+ pkt->setBE(MakeTsbPtr(Ps0,
tag_access,
c0_tsb_ps0,
c0_config,
cx_config));
break;
case ASI_DMMU_TSB_PS1_PTR_REG:
- pkt->set(MakeTsbPtr(Ps1,
+ pkt->setBE(MakeTsbPtr(Ps1,
tag_access,
c0_tsb_ps1,
c0_config,
cx_config));
break;
case ASI_IMMU_TSB_PS0_PTR_REG:
- pkt->set(MakeTsbPtr(Ps0,
+ pkt->setBE(MakeTsbPtr(Ps0,
itb->tag_access,
itb->c0_tsb_ps0,
itb->c0_config,
itb->cx_config));
break;
case ASI_IMMU_TSB_PS1_PTR_REG:
- pkt->set(MakeTsbPtr(Ps1,
+ pkt->setBE(MakeTsbPtr(Ps1,
itb->tag_access,
itb->c0_tsb_ps1,
itb->c0_config,
{
SparcISA::Interrupts * interrupts =
dynamic_cast<SparcISA::Interrupts *>(
- tc->getCpuPtr()->getInterruptController());
- pkt->set(interrupts->get_vec(IT_INT_VEC));
+ tc->getCpuPtr()->getInterruptController(0));
+ pkt->setBE(interrupts->get_vec(IT_INT_VEC));
}
break;
case ASI_SWVR_UDB_INTR_R:
{
SparcISA::Interrupts * interrupts =
dynamic_cast<SparcISA::Interrupts *>(
- tc->getCpuPtr()->getInterruptController());
+ tc->getCpuPtr()->getInterruptController(0));
temp = findMsbSet(interrupts->get_vec(IT_INT_VEC));
- tc->getCpuPtr()->clearInterrupt(IT_INT_VEC, temp);
- pkt->set(temp);
+ tc->getCpuPtr()->clearInterrupt(0, IT_INT_VEC, temp);
+ pkt->setBE(temp);
}
break;
default:
(uint32_t)asi, va);
}
pkt->makeAtomicResponse();
- return tc->getCpuPtr()->ticks(1);
+ return Cycles(1);
}
-Tick
+Cycles
TLB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
{
- uint64_t data = pkt->get<uint64_t>();
+ uint64_t data = pkt->getBE<uint64_t>();
Addr va = pkt->getAddr();
- ASI asi = (ASI)pkt->req->getAsi();
+ ASI asi = (ASI)pkt->req->getArchFlags();
Addr ta_insert;
Addr va_insert;
DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n",
(uint32_t)asi, va, data);
- TLB *itb = tc->getITBPtr();
+ TLB *itb = dynamic_cast<TLB *>(tc->getITBPtr());
switch (asi) {
case ASI_LSU_CONTROL_REG:
break;
case ASI_ITLB_DATA_ACCESS_REG:
entry_insert = bits(va, 8,3);
+ M5_FALLTHROUGH;
case ASI_ITLB_DATA_IN_REG:
assert(entry_insert != -1 || mbits(va,10,9) == va);
ta_insert = itb->tag_access;
real_insert = bits(va, 9,9);
pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v :
PageTableEntry::sun4u);
- tc->getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert,
- pte, entry_insert);
+ itb->insert(va_insert, part_insert, ct_insert, real_insert,
+ pte, entry_insert);
break;
case ASI_DTLB_DATA_ACCESS_REG:
entry_insert = bits(va, 8,3);
+ M5_FALLTHROUGH;
case ASI_DTLB_DATA_IN_REG:
assert(entry_insert != -1 || mbits(va,10,9) == va);
ta_insert = tag_access;
ignore = true;
}
- switch(bits(va,7,6)) {
+ switch (bits(va,7,6)) {
case 0: // demap page
if (!ignore)
- tc->getITBPtr()->demapPage(mbits(va,63,13), part_id,
- bits(va,9,9), ctx_id);
+ itb->demapPage(mbits(va,63,13), part_id, bits(va,9,9), ctx_id);
break;
- case 1: //demap context
+ case 1: // demap context
if (!ignore)
- tc->getITBPtr()->demapContext(part_id, ctx_id);
+ itb->demapContext(part_id, ctx_id);
break;
case 2:
- tc->getITBPtr()->demapAll(part_id);
+ itb->demapAll(part_id);
break;
default:
panic("Invalid type for IMMU demap\n");
ignore = true;
}
- switch(bits(va,7,6)) {
+ switch (bits(va,7,6)) {
case 0: // demap page
if (!ignore)
demapPage(mbits(va,63,13), part_id, bits(va,9,9), ctx_id);
break;
- case 1: //demap context
+ case 1: // demap context
if (!ignore)
demapContext(part_id, ctx_id);
break;
// clear all the interrupts that aren't set in the write
SparcISA::Interrupts * interrupts =
dynamic_cast<SparcISA::Interrupts *>(
- tc->getCpuPtr()->getInterruptController());
+ tc->getCpuPtr()->getInterruptController(0));
while (interrupts->get_vec(IT_INT_VEC) & data) {
msb = findMsbSet(interrupts->get_vec(IT_INT_VEC) & data);
- tc->getCpuPtr()->clearInterrupt(IT_INT_VEC, msb);
+ tc->getCpuPtr()->clearInterrupt(0, IT_INT_VEC, msb);
}
}
break;
case ASI_SWVR_UDB_INTR_W:
tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()->
- postInterrupt(bits(data, 5, 0), 0);
+ postInterrupt(0, bits(data, 5, 0), 0);
break;
default:
doMmuWriteError:
panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
- (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data);
+ (uint32_t)pkt->req->getArchFlags(), pkt->getAddr(), data);
}
pkt->makeAtomicResponse();
- return tc->getCpuPtr()->ticks(1);
+ return Cycles(1);
}
-#endif
-
void
TLB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs)
{
uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0);
- TLB * itb = tc->getITBPtr();
+ TLB *itb = dynamic_cast<TLB *>(tc->getITBPtr());
ptrs[0] = MakeTsbPtr(Ps0, tag_access,
c0_tsb_ps0,
c0_config,
}
void
-TLB::serialize(std::ostream &os)
+TLB::serialize(CheckpointOut &cp) const
{
SERIALIZE_SCALAR(size);
SERIALIZE_SCALAR(usedEntries);
SERIALIZE_SCALAR(lastReplaced);
// convert the pointer based free list into an index based one
- int *free_list = (int*)malloc(sizeof(int) * size);
- int cntr = 0;
- std::list<TlbEntry*>::iterator i;
- i = freeList.begin();
- while (i != freeList.end()) {
- free_list[cntr++] = ((size_t)*i - (size_t)tlb)/ sizeof(TlbEntry);
- i++;
- }
- SERIALIZE_SCALAR(cntr);
- SERIALIZE_ARRAY(free_list, cntr);
+ std::vector<int> free_list;
+ for (const TlbEntry *entry : freeList)
+ free_list.push_back(entry - tlb);
+
+ SERIALIZE_CONTAINER(free_list);
SERIALIZE_SCALAR(c0_tsb_ps0);
SERIALIZE_SCALAR(c0_tsb_ps1);
SERIALIZE_SCALAR(cx_config);
SERIALIZE_SCALAR(sfsr);
SERIALIZE_SCALAR(tag_access);
+ SERIALIZE_SCALAR(sfar);
for (int x = 0; x < size; x++) {
- nameOut(os, csprintf("%s.PTE%d", name(), x));
- tlb[x].serialize(os);
+ ScopedCheckpointSection sec(cp, csprintf("PTE%d", x));
+ tlb[x].serialize(cp);
}
- SERIALIZE_SCALAR(sfar);
}
void
-TLB::unserialize(Checkpoint *cp, const std::string §ion)
+TLB::unserialize(CheckpointIn &cp)
{
int oldSize;
- paramIn(cp, section, "size", oldSize);
+ paramIn(cp, "size", oldSize);
if (oldSize != size)
panic("Don't support unserializing different sized TLBs\n");
UNSERIALIZE_SCALAR(usedEntries);
UNSERIALIZE_SCALAR(lastReplaced);
- int cntr;
- UNSERIALIZE_SCALAR(cntr);
-
- int *free_list = (int*)malloc(sizeof(int) * cntr);
+ std::vector<int> free_list;
+ UNSERIALIZE_CONTAINER(free_list);
freeList.clear();
- UNSERIALIZE_ARRAY(free_list, cntr);
- for (int x = 0; x < cntr; x++)
- freeList.push_back(&tlb[free_list[x]]);
+ for (int idx : free_list)
+ freeList.push_back(&tlb[idx]);
UNSERIALIZE_SCALAR(c0_tsb_ps0);
UNSERIALIZE_SCALAR(c0_tsb_ps1);
lookupTable.clear();
for (int x = 0; x < size; x++) {
- tlb[x].unserialize(cp, csprintf("%s.PTE%d", section, x));
+ ScopedCheckpointSection sec(cp, csprintf("PTE%d", x));
+ tlb[x].unserialize(cp);
if (tlb[x].valid)
lookupTable.insert(tlb[x].range, &tlb[x]);
UNSERIALIZE_SCALAR(sfar);
}
-/* end namespace SparcISA */ }
+} // namespace SparcISA
SparcISA::TLB *
SparcTLBParams::create()