diff options
-rw-r--r-- | src/arch/arm/isa.cc | 17 | ||||
-rw-r--r-- | src/arch/arm/linux/system.cc | 21 | ||||
-rw-r--r-- | src/arch/arm/linux/system.hh | 11 | ||||
-rw-r--r-- | src/arch/arm/system.hh | 9 | ||||
-rw-r--r-- | src/arch/arm/tlb.cc | 10 | ||||
-rw-r--r-- | src/arch/arm/tlb.hh | 3 |
6 files changed, 69 insertions, 2 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 25bc3161b..676abfa68 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -360,6 +360,23 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr; tc->getITBPtr()->invalidateMiscReg(); tc->getDTBPtr()->invalidateMiscReg(); + + // Check if all CPUs are booted with caches enabled + // so we can stop enforcing coherency of some kernel + // structures manually. + sys = tc->getSystemPtr(); + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + SCTLR other_sctlr = oc->readMiscRegNoEffect(MISCREG_SCTLR); + if (!other_sctlr.c && oc->status() != ThreadContext::Halted) + return; + } + + for (x = 0; x < sys->numContexts(); x++) { + oc = sys->getThreadContext(x); + oc->getDTBPtr()->allCpusCaching(); + oc->getITBPtr()->allCpusCaching(); + } return; } case MISCREG_TLBTR: diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc index 445fa2f19..66f4f26af 100644 --- a/src/arch/arm/linux/system.cc +++ b/src/arch/arm/linux/system.cc @@ -117,6 +117,27 @@ LinuxArmSystem::LinuxArmSystem(Params *p) } else { panic("couldn't find kernel symbol \'udelay\'"); } + + secDataPtrAddr = 0; + secDataAddr = 0; + penReleaseAddr = 0; + kernelSymtab->findAddress("__secondary_data", secDataPtrAddr); + kernelSymtab->findAddress("secondary_data", secDataAddr); + kernelSymtab->findAddress("pen_release", penReleaseAddr); + + secDataPtrAddr &= ~ULL(0x7F); + secDataAddr &= ~ULL(0x7F); + penReleaseAddr &= ~ULL(0x7F); +} + +bool +LinuxArmSystem::adderBootUncacheable(Addr a) +{ + Addr block = a & ~ULL(0x7F); + if (block == secDataPtrAddr || block == secDataAddr || + block == penReleaseAddr) + return true; + return false; } void diff --git a/src/arch/arm/linux/system.hh b/src/arch/arm/linux/system.hh index 2ef65fea2..54681096b 100644 --- a/src/arch/arm/linux/system.hh +++ b/src/arch/arm/linux/system.hh @@ -69,6 +69,8 @@ class LinuxArmSystem : public ArmSystem void initState(); + bool adderBootUncacheable(Addr a); + private: #ifndef NDEBUG /** Event to halt the simulator if the kernel calls panic() */ @@ -87,6 +89,15 @@ class LinuxArmSystem : public ArmSystem * Thus we need to do some division to get back to us. */ Linux::UDelayEvent *constUDelaySkipEvent; + + /** These variables store addresses of important data structures + * that are normaly kept coherent at boot with cache mainetence operations. + * Since these operations aren't supported in gem5, we keep them coherent + * by making them uncacheable until all processors in the system boot. + */ + Addr secDataPtrAddr; + Addr secDataAddr; + Addr penReleaseAddr; }; #endif // __ARCH_ARM_LINUX_SYSTEM_HH__ diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh index 4898d433c..32b48a85b 100644 --- a/src/arch/arm/system.hh +++ b/src/arch/arm/system.hh @@ -78,6 +78,15 @@ class ArmSystem : public System void initState(); + /** Check if an address should be uncacheable until all caches are enabled. + * This exits because coherence on some addresses at boot is maintained via + * sw coherence until the caches are enbaled. Since we don't support sw + * coherence operations in gem5, this is a method that allows a system + * type to designate certain addresses that should remain uncachebale + * for a while. + */ + virtual bool adderBootUncacheable(Addr a) { return false; } + virtual Addr fixFuncEventAddr(Addr addr) { // Remove the low bit that thumb symbols have set diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index c59498212..942f85120 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -61,6 +61,7 @@ #include "sim/process.hh" #if FULL_SYSTEM +#include "arch/arm/system.hh" #include "arch/arm/table_walker.hh" #endif @@ -72,7 +73,7 @@ TLB::TLB(const Params *p) #if FULL_SYSTEM , tableWalker(p->walker) #endif - , rangeMRU(1), miscRegValid(false) + , rangeMRU(1), bootUncacheability(false), miscRegValid(false) { table = new TlbEntry[size]; memset(table, 0, sizeof(TlbEntry) * size); @@ -575,6 +576,11 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, } } + + if (!bootUncacheability && + ((ArmSystem*)tc->getSystemPtr())->adderBootUncacheable(vaddr)) + req->setFlags(Request::UNCACHEABLE); + switch ( (dacr >> (te->domain * 2)) & 0x3) { case 0: domainFaults++; @@ -704,7 +710,7 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc, #else fault = translateSe(req, tc, mode, translation, delay, true); #endif - DPRINTF(TLB, "Translation returning delay=%d fault=%d\n", delay, fault != + DPRINTF(TLBVerbose, "Translation returning delay=%d fault=%d\n", delay, fault != NoFault); if (!delay) translation->finish(fault, req, tc, mode); diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index bf6ae22f8..f78e38a3d 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -128,6 +128,8 @@ class TLB : public BaseTLB int rangeMRU; //On lookup, only move entries ahead when outside rangeMRU + bool bootUncacheability; + public: typedef ArmTLBParams Params; TLB(const Params *p); @@ -162,6 +164,7 @@ class TLB : public BaseTLB void printTlb(); + void allCpusCaching() { bootUncacheability = true; } void demapPage(Addr vaddr, uint64_t asn) { flushMvaAsid(vaddr, asn); |