summaryrefslogtreecommitdiff
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
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.
-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
-rw-r--r--src/base/loader/dtb_object.cc21
-rw-r--r--src/base/loader/dtb_object.hh7
6 files changed, 94 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);
}
diff --git a/src/base/loader/dtb_object.cc b/src/base/loader/dtb_object.cc
index f22cee1ed..adf7d2c3a 100644
--- a/src/base/loader/dtb_object.cc
+++ b/src/base/loader/dtb_object.cc
@@ -35,6 +35,7 @@
#include <cassert>
#include "base/loader/dtb_object.hh"
+#include "sim/byteswap.hh"
#include "fdt.h"
#include "libfdt.h"
@@ -154,6 +155,26 @@ DtbObject::addBootCmdLine(const char* _args, size_t len)
return true;
}
+Addr
+DtbObject::findReleaseAddr()
+{
+ void *fd = (void*)fileData;
+
+ int offset = fdt_path_offset(fd, "/cpus/cpu@0");
+ int len;
+
+ const void* temp = fdt_getprop(fd, offset, "cpu-release-addr", &len);
+ Addr rel_addr = 0;
+
+ if (len > 3)
+ rel_addr = betoh(*static_cast<const uint32_t*>(temp));
+ if (len == 8)
+ rel_addr = (rel_addr << 32) | betoh(*(static_cast<const uint32_t*>(temp)+1));
+
+ return rel_addr;
+}
+
+
bool
DtbObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
diff --git a/src/base/loader/dtb_object.hh b/src/base/loader/dtb_object.hh
index ec5294553..74bb52d44 100644
--- a/src/base/loader/dtb_object.hh
+++ b/src/base/loader/dtb_object.hh
@@ -60,6 +60,13 @@ class DtbObject : public ObjectFile
* @return returns true on success, false otherwise
*/
bool addBootCmdLine(const char* _args, size_t len);
+
+ /** Parse the DTB file enough to find the provided release
+ * address and return it.
+ * @return release address for SMP boot
+ */
+ Addr findReleaseAddr();
+
bool loadGlobalSymbols(SymbolTable *symtab,
Addr addrMask = std::numeric_limits<Addr>::max());
bool loadLocalSymbols(SymbolTable *symtab,