#include "arch/arm/faults.hh"
#include "arch/arm/htm.hh"
#include "arch/arm/interrupts.hh"
+#include "arch/arm/mmu.hh"
#include "arch/arm/pmu.hh"
#include "arch/arm/self_debug.hh"
#include "arch/arm/system.hh"
-#include "arch/arm/tlb.hh"
#include "arch/arm/tlbi_op.hh"
#include "cpu/base.hh"
#include "cpu/checker/cpu.hh"
// Invalidate cached copies of miscregs in the TLBs
if (tc) {
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
}
SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST];
int old_mode = old_cpsr.mode;
CPSR cpsr = val;
if (old_mode != cpsr.mode || cpsr.il != old_cpsr.il) {
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
}
if (cpsr.pan != old_cpsr.pan) {
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg(MMU::D_TLBS);
}
DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n",
}
break;
case MISCREG_SCR:
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
break;
case MISCREG_SCTLR:
{
SCTLR new_sctlr = newVal;
new_sctlr.nmfi = ((bool)sctlr.nmfi) && !haveVirtualization;
miscRegs[sctlr_idx] = (RegVal)new_sctlr;
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
}
case MISCREG_MIDR:
case MISCREG_ID_PFR0:
newVal = (newVal & ttbcrMask) | (ttbcr & (~ttbcrMask));
}
// Invalidate TLB MiscReg
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
break;
}
case MISCREG_TTBR0:
}
}
// Invalidate TLB MiscReg
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
break;
}
case MISCREG_SCTLR_EL1:
case MISCREG_TTBR0_EL2:
case MISCREG_TTBR1_EL2:
case MISCREG_TTBR0_EL3:
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
break;
case MISCREG_HCR_EL2:
{
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
selfDebug->setenableTDETGE((HCR)val, mdcr);
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
}
break;
case MISCREG_NZCV:
case MISCREG_PAN:
{
// PAN is affecting data accesses
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg(MMU::D_TLBS);
CPSR cpsr = miscRegs[MISCREG_CPSR];
cpsr.pan = (uint8_t) ((CPSR) newVal).pan;
val, 0, flags, Request::funcRequestorId,
tc->pcState().pc(), tc->contextId());
- Fault fault = getDTBPtr(tc)->translateFunctional(
+ Fault fault = getMMUPtr(tc)->translateFunctional(
req, tc, mode, tran_type);
PAR par = 0;
if (fault == NoFault) {
Addr paddr = req->getPaddr();
- uint64_t attr = getDTBPtr(tc)->getAttr();
+ uint64_t attr = getMMUPtr(tc)->getAttr();
uint64_t attr1 = attr >> 56;
if (!attr1 || attr1 ==0x44) {
attr |= 0x100;
val, 0, flags, Request::funcRequestorId,
tc->pcState().pc(), tc->contextId());
- Fault fault = getDTBPtr(tc)->translateFunctional(
+ Fault fault = getMMUPtr(tc)->translateFunctional(
req, tc, mode, tran_type);
PAR par = 0;
}
par = (paddr & mask(max_paddr_bit, 12)) |
- (getDTBPtr(tc)->getAttr());
+ (getMMUPtr(tc)->getAttr());
DPRINTF(MiscRegs,
"MISCREG: Translated addr 0x%08x: PAR: 0x%08x\n",
#include "arch/arm/mmu.hh"
+using namespace ArmISA;
+
+bool
+MMU::translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr)
+{
+ return getDTBPtr()->translateFunctional(tc, vaddr, paddr);
+}
+
+Fault
+MMU::translateFunctional(const RequestPtr &req, ThreadContext *tc,
+ BaseTLB::Mode mode, TLB::ArmTranslationType tran_type)
+{
+ if (mode == BaseTLB::Execute)
+ return getITBPtr()->translateFunctional(req, tc, mode, tran_type);
+ else
+ return getDTBPtr()->translateFunctional(req, tc, mode, tran_type);
+}
+
+void
+MMU::invalidateMiscReg(TLBType type)
+{
+ if (type & TLBType::I_TLBS) {
+ getITBPtr()->invalidateMiscReg();
+ }
+ if (type & TLBType::D_TLBS) {
+ getDTBPtr()->invalidateMiscReg();
+ }
+}
+
+void
+MMU::flushAllSecurity(bool secure_lookup, ExceptionLevel target_el,
+ TLBType type, bool ignore_el, bool in_host)
+{
+ if (type & TLBType::I_TLBS) {
+ getITBPtr()->flushAllSecurity(
+ secure_lookup, target_el, ignore_el, in_host);
+ }
+ if (type & TLBType::D_TLBS) {
+ getDTBPtr()->flushAllSecurity(
+ secure_lookup, target_el, ignore_el, in_host);
+ }
+}
+
+void
+MMU::flushAllNs(ExceptionLevel target_el, bool ignore_el,
+ TLBType type)
+{
+ if (type & TLBType::I_TLBS) {
+ getITBPtr()->flushAllNs(target_el, ignore_el);
+ }
+ if (type & TLBType::D_TLBS) {
+ getDTBPtr()->flushAllNs(target_el, ignore_el);
+ }
+}
+
+void
+MMU::flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup,
+ ExceptionLevel target_el, TLBType type,
+ bool in_host)
+{
+ if (type & TLBType::I_TLBS) {
+ getITBPtr()->flushMvaAsid(
+ mva, asn, secure_lookup, target_el, in_host);
+ }
+ if (type & TLBType::D_TLBS) {
+ getDTBPtr()->flushMvaAsid(
+ mva, asn, secure_lookup, target_el, in_host);
+ }
+}
+
+void
+MMU::flushAsid(uint64_t asn, bool secure_lookup,
+ ExceptionLevel target_el, TLBType type,
+ bool in_host)
+{
+ if (type & TLBType::I_TLBS) {
+ getITBPtr()->flushAsid(asn, secure_lookup, target_el, in_host);
+ }
+ if (type & TLBType::D_TLBS) {
+ getDTBPtr()->flushAsid(asn, secure_lookup, target_el, in_host);
+ }
+}
+
+void
+MMU::flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el,
+ TLBType type, bool in_host)
+{
+ if (type & TLBType::I_TLBS) {
+ getITBPtr()->flushMva(mva, secure_lookup, target_el, in_host);
+ }
+ if (type & TLBType::D_TLBS) {
+ getDTBPtr()->flushMva(mva, secure_lookup, target_el, in_host);
+ }
+}
+
+void
+MMU::flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el,
+ TLBType type)
+{
+ if (type & TLBType::I_TLBS) {
+ getITBPtr()->flushIpaVmid(ipa, secure_lookup, target_el);
+ }
+ if (type & TLBType::D_TLBS) {
+ getDTBPtr()->flushIpaVmid(ipa, secure_lookup, target_el);
+ }
+}
+
ArmISA::MMU *
ArmMMUParams::create() const
{
#ifndef __ARCH_ARM_MMU_HH__
#define __ARCH_ARM_MMU_HH__
+#include "arch/arm/tlb.hh"
#include "arch/generic/mmu.hh"
#include "params/ArmMMU.hh"
class MMU : public BaseMMU
{
+ protected:
+ ArmISA::TLB *
+ getDTBPtr() const
+ {
+ return static_cast<ArmISA::TLB *>(dtb);
+ }
+
+ ArmISA::TLB *
+ getITBPtr() const
+ {
+ return static_cast<ArmISA::TLB *>(itb);
+ }
+
public:
+ enum TLBType
+ {
+ I_TLBS = 0x01,
+ D_TLBS = 0x10,
+ ALL_TLBS = 0x11
+ };
+
MMU(const ArmMMUParams &p)
: BaseMMU(p)
{}
+
+ bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr);
+
+ Fault translateFunctional(const RequestPtr &req, ThreadContext *tc,
+ BaseTLB::Mode mode, TLB::ArmTranslationType tran_type);
+
+ void invalidateMiscReg(TLBType type = ALL_TLBS);
+
+ /** Reset the entire TLB
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushAllSecurity(bool secure_lookup, ExceptionLevel target_el,
+ TLBType type = ALL_TLBS,
+ bool ignore_el = false, bool in_host = false);
+
+ /** Remove all entries in the non secure world, depending on whether they
+ * were allocated in hyp mode or not
+ */
+ void flushAllNs(ExceptionLevel target_el, bool ignore_el = false,
+ TLBType type = ALL_TLBS);
+
+ /** Remove any entries that match both a va and asn
+ * @param mva virtual address to flush
+ * @param asn contextid/asn to flush on match
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup,
+ ExceptionLevel target_el, TLBType type = ALL_TLBS,
+ bool in_host = false);
+
+ /** Remove any entries that match the asn
+ * @param asn contextid/asn to flush on match
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushAsid(uint64_t asn, bool secure_lookup,
+ ExceptionLevel target_el, TLBType type = ALL_TLBS,
+ bool in_host = false);
+
+ /** Remove all entries that match the va regardless of asn
+ * @param mva address to flush from cache
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el,
+ TLBType type = ALL_TLBS, bool in_host = false);
+
+ /**
+ * Invalidate all entries in the stage 2 TLB that match the given ipa
+ * and the current VMID
+ * @param ipa the address to invalidate
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el,
+ TLBType type = ALL_TLBS);
+
+ uint64_t
+ getAttr() const
+ {
+ return getDTBPtr()->getAttr();
+ }
+
};
+template<typename T>
+MMU *
+getMMUPtr(T *tc)
+{
+ auto mmu = static_cast<MMU *>(tc->getMMUPtr());
+ assert(mmu);
+ return mmu;
+}
+
+
} // namespace ArmISA
#endif // __ARCH_ARM_MMU_HH__
#include "arch/arm/registers.hh"
#include "arch/arm/system.hh"
#include "arch/arm/utility.hh"
-#include "arch/generic/tlb.hh"
+#include "arch/generic/mmu.hh"
#include "base/chunk_generator.hh"
#include "base/intmath.hh"
#include "base/remote_gdb.hh"
//
// Calling translateFunctional invokes a table-walk if required
// so we should always succeed
- auto *dtb = tc->getDTBPtr();
- auto *itb = tc->getITBPtr();
- return dtb->translateFunctional(req, tc, BaseTLB::Read) == NoFault ||
- itb->translateFunctional(req, tc, BaseTLB::Read) == NoFault;
+ auto *mmu = tc->getMMUPtr();
+ return mmu->translateFunctional(req, tc, BaseTLB::Read) == NoFault ||
+ mmu->translateFunctional(req, tc, BaseTLB::Execute) == NoFault;
}
RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc, int _port)
{
return dynamic_cast<const Params &>(_params);
}
- inline void invalidateMiscReg() { miscRegValid = false; }
+ void invalidateMiscReg() { miscRegValid = false; }
private:
/** Remove any entries that match both a va and asn
LookupLevel lookup_level);
};
-template<typename T>
-TLB *
-getITBPtr(T *tc)
-{
- auto tlb = static_cast<TLB *>(tc->getITBPtr());
- assert(tlb);
- return tlb;
-}
-
-template<typename T>
-TLB *
-getDTBPtr(T *tc)
-{
- auto tlb = static_cast<TLB *>(tc->getDTBPtr());
- assert(tlb);
- return tlb;
-}
-
} // namespace ArmISA
#endif // __ARCH_ARM_TLB_HH__
#include "arch/arm/tlbi_op.hh"
-#include "arch/arm/tlb.hh"
+#include "arch/arm/mmu.hh"
#include "cpu/checker/cpu.hh"
namespace ArmISA {
{
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
- getITBPtr(tc)->flushAllSecurity(secureLookup, targetEL, in_host);
- getDTBPtr(tc)->flushAllSecurity(secureLookup, targetEL, in_host);
+ getMMUPtr(tc)->flushAllSecurity(secureLookup, targetEL,
+ MMU::ALL_TLBS, in_host);
// If CheckerCPU is connected, need to notify it of a flush
CheckerCPU *checker = tc->getCheckerCpuPtr();
if (checker) {
- getITBPtr(checker)->flushAllSecurity(secureLookup,
- targetEL, in_host);
- getDTBPtr(checker)->flushAllSecurity(secureLookup,
- targetEL, in_host);
+ getMMUPtr(checker)->flushAllSecurity(
+ secureLookup, targetEL, MMU::ALL_TLBS, in_host);
}
}
void
ITLBIALL::operator()(ThreadContext* tc)
{
- getITBPtr(tc)->flushAllSecurity(secureLookup, targetEL);
+ getMMUPtr(tc)->flushAllSecurity(secureLookup, targetEL, MMU::I_TLBS);
}
void
DTLBIALL::operator()(ThreadContext* tc)
{
- getDTBPtr(tc)->flushAllSecurity(secureLookup, targetEL);
+ getMMUPtr(tc)->flushAllSecurity(secureLookup, targetEL, MMU::D_TLBS);
}
void
{
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
- getITBPtr(tc)->flushAsid(asid, secureLookup, targetEL, in_host);
- getDTBPtr(tc)->flushAsid(asid, secureLookup, targetEL, in_host);
+ getMMUPtr(tc)->flushAsid(asid, secureLookup, targetEL,
+ MMU::ALL_TLBS, in_host);
CheckerCPU *checker = tc->getCheckerCpuPtr();
if (checker) {
- getITBPtr(checker)->flushAsid(asid, secureLookup, targetEL, in_host);
- getDTBPtr(checker)->flushAsid(asid, secureLookup, targetEL, in_host);
+ getMMUPtr(checker)->flushAsid(asid, secureLookup, targetEL,
+ MMU::ALL_TLBS, in_host);
}
}
void
ITLBIASID::operator()(ThreadContext* tc)
{
- getITBPtr(tc)->flushAsid(asid, secureLookup, targetEL);
+ getMMUPtr(tc)->flushAsid(asid, secureLookup, targetEL, MMU::I_TLBS);
}
void
DTLBIASID::operator()(ThreadContext* tc)
{
- getDTBPtr(tc)->flushAsid(asid, secureLookup, targetEL);
+ getMMUPtr(tc)->flushAsid(asid, secureLookup, targetEL, MMU::D_TLBS);
}
void
TLBIALLN::operator()(ThreadContext* tc)
{
- getITBPtr(tc)->flushAllNs(targetEL);
- getDTBPtr(tc)->flushAllNs(targetEL);
+ getMMUPtr(tc)->flushAllNs(targetEL);
CheckerCPU *checker = tc->getCheckerCpuPtr();
if (checker) {
- getITBPtr(checker)->flushAllNs(targetEL);
- getDTBPtr(checker)->flushAllNs(targetEL);
+ getMMUPtr(checker)->flushAllNs(targetEL);
}
}
{
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
- getITBPtr(tc)->flushMva(addr, secureLookup, targetEL, in_host);
- getDTBPtr(tc)->flushMva(addr, secureLookup, targetEL, in_host);
+ getMMUPtr(tc)->flushMva(addr, secureLookup, targetEL,
+ MMU::ALL_TLBS, in_host);
CheckerCPU *checker = tc->getCheckerCpuPtr();
if (checker) {
- getITBPtr(checker)->flushMva(addr, secureLookup, targetEL, in_host);
- getDTBPtr(checker)->flushMva(addr, secureLookup, targetEL, in_host);
+ getMMUPtr(checker)->flushMva(addr, secureLookup, targetEL,
+ MMU::ALL_TLBS, in_host);
}
}
{
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
- getITBPtr(tc)->flushMvaAsid(addr, asid,
- secureLookup, targetEL, in_host);
- getDTBPtr(tc)->flushMvaAsid(addr, asid,
- secureLookup, targetEL, in_host);
+ getMMUPtr(tc)->flushMvaAsid(addr, asid,
+ secureLookup, targetEL, MMU::ALL_TLBS, in_host);
CheckerCPU *checker = tc->getCheckerCpuPtr();
if (checker) {
- getITBPtr(checker)->flushMvaAsid(
- addr, asid, secureLookup, targetEL, in_host);
- getDTBPtr(checker)->flushMvaAsid(
- addr, asid, secureLookup, targetEL, in_host);
+ getMMUPtr(checker)->flushMvaAsid(
+ addr, asid, secureLookup, targetEL, MMU::ALL_TLBS, in_host);
}
}
void
ITLBIMVA::operator()(ThreadContext* tc)
{
- getITBPtr(tc)->flushMvaAsid(
- addr, asid, secureLookup, targetEL);
+ getMMUPtr(tc)->flushMvaAsid(
+ addr, asid, secureLookup, targetEL, MMU::I_TLBS);
}
void
DTLBIMVA::operator()(ThreadContext* tc)
{
- getDTBPtr(tc)->flushMvaAsid(
- addr, asid, secureLookup, targetEL);
+ getMMUPtr(tc)->flushMvaAsid(
+ addr, asid, secureLookup, targetEL, MMU::D_TLBS);
}
void
TLBIIPA::operator()(ThreadContext* tc)
{
- getITBPtr(tc)->flushIpaVmid(addr,
- secureLookup, targetEL);
- getDTBPtr(tc)->flushIpaVmid(addr,
+ getMMUPtr(tc)->flushIpaVmid(addr,
secureLookup, targetEL);
CheckerCPU *checker = tc->getCheckerCpuPtr();
if (checker) {
- getITBPtr(checker)->flushIpaVmid(addr,
- secureLookup, targetEL);
- getDTBPtr(checker)->flushIpaVmid(addr,
+ getMMUPtr(checker)->flushIpaVmid(addr,
secureLookup, targetEL);
}
}
#include "arch/arm/tracers/tarmac_parser.hh"
-#include "arch/arm/tlb.hh"
#include "arch/arm/insts/static_inst.hh"
+#include "arch/arm/mmu.hh"
#include "config/the_isa.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
unsigned flags)
{
const RequestPtr &req = memReq;
- ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
+ auto mmu = static_cast<MMU*>(thread->getMMUPtr());
req->setVirt(addr, size, flags, thread->pcState().instAddr(),
Request::funcRequestorId);
// Translate to physical address
- Fault fault = dtb->translateAtomic(req, thread, BaseTLB::Read);
+ Fault fault = mmu->translateAtomic(req, thread, BaseTLB::Read);
// Ignore read if the address falls into the ignored range
if (parent.ignoredAddrRange.contains(addr))
#include <memory>
#include "arch/arm/insts/static_inst.hh"
-#include "arch/arm/tlb.hh"
+#include "arch/arm/mmu.hh"
#include "arch/arm/tracers/tarmac_tracer.hh"
using namespace ArmISA;
const auto thread = tarmCtx.thread;
// Evaluate physical address
- ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
- paddrValid = dtb->translateFunctional(thread, addr, paddr);
+ auto mmu = static_cast<ArmISA::MMU*>(thread->getMMUPtr());
+ paddrValid = mmu->translateFunctional(
+ thread, addr, paddr);
}
TarmacTracerRecordV8::TraceMemEntryV8::TraceMemEntryV8(
const auto thread = tarmCtx.thread;
// Evaluate physical address
- ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
- dtb->translateFunctional(thread, addr, paddr);
+ auto mmu = static_cast<ArmISA::MMU*>(thread->getMMUPtr());
+ mmu->translateFunctional(thread, addr, paddr);
}
TarmacTracerRecordV8::TraceRegEntryV8::TraceRegEntryV8(
#include "arch/arm/faults.hh"
#include "arch/arm/interrupts.hh"
#include "arch/arm/isa_traits.hh"
+#include "arch/arm/mmu.hh"
#include "arch/arm/system.hh"
-#include "arch/arm/tlb.hh"
#include "cpu/base.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/thread_context.hh"
dest->pcState(src->pcState());
// Invalidate the tlb misc register cache
- dynamic_cast<TLB *>(dest->getITBPtr())->invalidateMiscReg();
- dynamic_cast<TLB *>(dest->getDTBPtr())->invalidateMiscReg();
+ static_cast<MMU *>(dest->getMMUPtr())->invalidateMiscReg();
}
void