summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2014-10-29 23:18:26 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2014-10-29 23:18:26 -0500
commitbaf88e908d285191c13b5e96c16065957e5af7a6 (patch)
tree7361d43b795f80a80a89995eb6865d51a972f36a /src/arch/arm
parent3a5c975fd7a0e6c8f25067c1794581056c01c22c (diff)
downloadgem5-baf88e908d285191c13b5e96c16065957e5af7a6.tar.xz
arm: Fix multi-system AArch64 boot w/caches.
Automatically extract cpu release address from DTB file. Check SCTLR_EL1 to verify all caches are enabled.
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/isa.cc74
-rw-r--r--src/arch/arm/isa.hh8
-rw-r--r--src/arch/arm/linux/system.cc4
-rw-r--r--src/arch/arm/tlb.cc9
4 files changed, 66 insertions, 29 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index c2250e38a..d97c03db5 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -1101,33 +1101,10 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
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);
- // @todo: double check this for security
- 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();
-
- // If CheckerCPU is connected, need to notify it.
- CheckerCPU *checker = oc->getCheckerCpuPtr();
- if (checker) {
- checker->getDTBPtr()->allCpusCaching();
- checker->getITBPtr()->allCpusCaching();
- }
- }
+ if (new_sctlr.c)
+ updateBootUncacheable(sctlr_idx, tc);
return;
}
-
case MISCREG_MIDR:
case MISCREG_ID_PFR0:
case MISCREG_ID_PFR1:
@@ -1674,6 +1651,16 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
}
}
}
+ case MISCREG_SCTLR_EL1:
+ {
+ tc->getITBPtr()->invalidateMiscReg();
+ tc->getDTBPtr()->invalidateMiscReg();
+ SCTLR new_sctlr = newVal;
+ setMiscRegNoEffect(misc_reg, newVal);
+ if (new_sctlr.c)
+ updateBootUncacheable(misc_reg, tc);
+ return;
+ }
case MISCREG_CONTEXTIDR:
case MISCREG_PRRR:
case MISCREG_NMRR:
@@ -1682,12 +1669,11 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
case MISCREG_DACR:
case MISCREG_VTTBR:
case MISCREG_SCR_EL3:
- case MISCREG_SCTLR_EL1:
- case MISCREG_SCTLR_EL2:
- case MISCREG_SCTLR_EL3:
case MISCREG_TCR_EL1:
case MISCREG_TCR_EL2:
case MISCREG_TCR_EL3:
+ case MISCREG_SCTLR_EL2:
+ case MISCREG_SCTLR_EL3:
case MISCREG_TTBR0_EL1:
case MISCREG_TTBR1_EL1:
case MISCREG_TTBR0_EL2:
@@ -1922,6 +1908,38 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
}
void
+ISA::updateBootUncacheable(int sctlr_idx, ThreadContext *tc)
+{
+ System *sys;
+ ThreadContext *oc;
+
+ // Check if all CPUs are booted with caches enabled
+ // so we can stop enforcing coherency of some kernel
+ // structures manually.
+ sys = tc->getSystemPtr();
+ for (int x = 0; x < sys->numContexts(); x++) {
+ oc = sys->getThreadContext(x);
+ // @todo: double check this for security
+ SCTLR other_sctlr = oc->readMiscRegNoEffect(sctlr_idx);
+ if (!other_sctlr.c && oc->status() != ThreadContext::Halted)
+ return;
+ }
+
+ for (int x = 0; x < sys->numContexts(); x++) {
+ oc = sys->getThreadContext(x);
+ oc->getDTBPtr()->allCpusCaching();
+ oc->getITBPtr()->allCpusCaching();
+
+ // If CheckerCPU is connected, need to notify it.
+ CheckerCPU *checker = oc->getCheckerCpuPtr();
+ if (checker) {
+ checker->getDTBPtr()->allCpusCaching();
+ checker->getITBPtr()->allCpusCaching();
+ }
+ }
+}
+
+void
ISA::tlbiVA(ThreadContext *tc, MiscReg newVal, uint8_t asid, bool secure_lookup,
uint8_t target_el)
{
diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh
index 9f7fa111e..ae5ff2131 100644
--- a/src/arch/arm/isa.hh
+++ b/src/arch/arm/isa.hh
@@ -429,6 +429,14 @@ namespace ArmISA
void startup(ThreadContext *tc) {}
+ /** Check if all CPUs have their caches enabled and if they do
+ * disable the bootAddrUncacheability flag because it's no longer
+ * needed.
+ * @s_idx the register number of the SCTLR that we are checking
+ * @tc Threadcontext to use to get access to the system and other cpus
+ */
+ void updateBootUncacheable(int sctlr_idx, ThreadContext *tc);
+
/// Explicitly import the otherwise hidden startup
using SimObject::startup;
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index 216a65899..66278681d 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -175,6 +175,10 @@ LinuxArmSystem::initState()
"to DTB file: %s\n", params()->dtb_filename);
}
+ Addr ra = _dtb_file->findReleaseAddr();
+ if (ra)
+ bootReleaseAddr = ra & ~ULL(0x7F);
+
dtb_file->setTextBase(params()->atags_addr + loadAddrOffset);
dtb_file->loadSections(physProxy);
delete dtb_file;
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index ef0702d44..46f124665 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -1089,7 +1089,14 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
req->setFlags(Request::UNCACHEABLE);
}
- req->setPaddr(te->pAddr(vaddr));
+ Addr pa = te->pAddr(vaddr);
+ req->setPaddr(pa);
+
+ if (!bootUncacheability &&
+ ((ArmSystem*)tc->getSystemPtr())->adderBootUncacheable(pa)) {
+ req->setFlags(Request::UNCACHEABLE);
+ }
+
if (isSecure && !te->ns) {
req->setFlags(Request::SECURE);
}