* 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/base.hh"
#include "cpu/thread_context.hh"
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;
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);
// 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;
+ return std::make_shared<InstructionRealTranslationMiss>();
} else {
if (FullSystem)
- return new FastInstructionAccessMMUMiss;
+ return std::make_shared<FastInstructionAccessMMUMiss>();
else
- return new FastInstructionAccessMMUMiss(req->getVaddr());
+ return std::make_shared<FastInstructionAccessMMUMiss>(
+ req->getVaddr());
}
}
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
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
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)) {
writeSfsr(vaddr, write, Nucleus, false, IllegalAsi, asi);
- return new DataAccessException;
+ return std::make_shared<DataAccessException>();
}
if (asiIsPrimary(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)) {
writeTagAccess(vaddr, context);
DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
if (real) {
- return new DataRealTranslationMiss;
+ return std::make_shared<DataRealTranslationMiss>();
} else {
if (FullSystem)
- return new FastDataAccessMMUMiss;
+ return std::make_shared<FastDataAccessMMUMiss>();
else
- return new FastDataAccessMMUMiss(req->getVaddr());
+ 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)) {
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)) {
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;
};
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);
}
Fault
-TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode)
-{
- panic("Not implemented\n");
- return NoFault;
-}
-
-Fault
-TLB::finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
+TLB::finalizePhysical(const RequestPtr &req,
+ ThreadContext *tc, Mode mode) const
{
return NoFault;
}
DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
(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:
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->getArchFlags();
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;
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
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");
// 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:
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]);