diff -r f5550fd097b8 -r 676806651643 src/arch/arm/isa.cc --- a/src/arch/arm/isa.cc Tue Aug 09 14:37:45 2011 -0500 +++ b/src/arch/arm/isa.cc Tue Aug 09 14:38:34 2011 -0500 @@ -360,6 +360,19 @@ 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; + } + tc->getDTBPtr()->allCpusCaching(); + tc->getITBPtr()->allCpusCaching(); return; } case MISCREG_TLBTR: diff -r f5550fd097b8 -r 676806651643 src/arch/arm/linux/system.hh --- a/src/arch/arm/linux/system.hh Tue Aug 09 14:37:45 2011 -0500 +++ b/src/arch/arm/linux/system.hh Tue Aug 09 14:38:34 2011 -0500 @@ -69,6 +69,8 @@ void initState(); + bool adderBootUncacheable(Addr a); + private: #ifndef NDEBUG /** Event to halt the simulator if the kernel calls panic() */ @@ -87,6 +89,15 @@ * 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 -r f5550fd097b8 -r 676806651643 src/arch/arm/linux/system.cc --- a/src/arch/arm/linux/system.cc Tue Aug 09 14:37:45 2011 -0500 +++ b/src/arch/arm/linux/system.cc Tue Aug 09 14:38:34 2011 -0500 @@ -117,6 +117,27 @@ } 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 -r f5550fd097b8 -r 676806651643 src/arch/arm/system.hh --- a/src/arch/arm/system.hh Tue Aug 09 14:37:45 2011 -0500 +++ b/src/arch/arm/system.hh Tue Aug 09 14:38:34 2011 -0500 @@ -78,6 +78,15 @@ 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 -r f5550fd097b8 -r 676806651643 src/arch/arm/tlb.hh --- a/src/arch/arm/tlb.hh Tue Aug 09 14:37:45 2011 -0500 +++ b/src/arch/arm/tlb.hh Tue Aug 09 14:38:34 2011 -0500 @@ -128,6 +128,8 @@ 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 @@ void printTlb(); + void allCpusCaching() { bootUncacheability = true; } void demapPage(Addr vaddr, uint64_t asn) { flushMvaAsid(vaddr, asn); diff -r f5550fd097b8 -r 676806651643 src/arch/arm/tlb.cc --- a/src/arch/arm/tlb.cc Tue Aug 09 14:37:45 2011 -0500 +++ b/src/arch/arm/tlb.cc Tue Aug 09 14:38:34 2011 -0500 @@ -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 @@ #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 @@ } } + + if (!bootUncacheability && + ((ArmSystem*)tc->getSystemPtr())->adderBootUncacheable(vaddr)) + req->setFlags(Request::UNCACHEABLE); + switch ( (dacr >> (te->domain * 2)) & 0x3) { case 0: domainFaults++; @@ -704,7 +710,7 @@ #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);