diff options
author | Ali Saidi <Ali.Saidi@ARM.com> | 2014-10-29 23:18:26 -0500 |
---|---|---|
committer | Ali Saidi <Ali.Saidi@ARM.com> | 2014-10-29 23:18:26 -0500 |
commit | baf88e908d285191c13b5e96c16065957e5af7a6 (patch) | |
tree | 7361d43b795f80a80a89995eb6865d51a972f36a /src | |
parent | 3a5c975fd7a0e6c8f25067c1794581056c01c22c (diff) | |
download | gem5-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')
-rw-r--r-- | src/arch/arm/isa.cc | 74 | ||||
-rw-r--r-- | src/arch/arm/isa.hh | 8 | ||||
-rw-r--r-- | src/arch/arm/linux/system.cc | 4 | ||||
-rw-r--r-- | src/arch/arm/tlb.cc | 9 | ||||
-rw-r--r-- | src/base/loader/dtb_object.cc | 21 | ||||
-rw-r--r-- | src/base/loader/dtb_object.hh | 7 |
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, |