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:
} 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
void initState();
+ bool adderBootUncacheable(Addr a);
+
private:
#ifndef NDEBUG
/** Event to halt the simulator if the kernel calls panic() */
* 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__
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
#include "sim/process.hh"
#if FULL_SYSTEM
+#include "arch/arm/system.hh"
#include "arch/arm/table_walker.hh"
#endif
#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);
}
}
+
+ if (!bootUncacheability &&
+ ((ArmSystem*)tc->getSystemPtr())->adderBootUncacheable(vaddr))
+ req->setFlags(Request::UNCACHEABLE);
+
switch ( (dacr >> (te->domain * 2)) & 0x3) {
case 0:
domainFaults++;
#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);
int rangeMRU; //On lookup, only move entries ahead when outside rangeMRU
+ bool bootUncacheability;
+
public:
typedef ArmTLBParams Params;
TLB(const Params *p);
void printTlb();
+ void allCpusCaching() { bootUncacheability = true; }
void demapPage(Addr vaddr, uint64_t asn)
{
flushMvaAsid(vaddr, asn);