changeset aa46a8ae3487 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=aa46a8ae3487
description:
        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:

 src/arch/arm/isa.cc           |  74 ++++++++++++++++++++++++++----------------
 src/arch/arm/isa.hh           |   8 ++++
 src/arch/arm/linux/system.cc  |   4 ++
 src/arch/arm/tlb.cc           |   9 ++++-
 src/base/loader/dtb_object.cc |  21 ++++++++++++
 src/base/loader/dtb_object.hh |   7 ++++
 6 files changed, 94 insertions(+), 29 deletions(-)

diffs (216 lines):

diff -r f33fab6214c4 -r aa46a8ae3487 src/arch/arm/isa.cc
--- a/src/arch/arm/isa.cc       Wed Oct 29 23:18:26 2014 -0500
+++ b/src/arch/arm/isa.cc       Wed Oct 29 23:18:26 2014 -0500
@@ -1101,33 +1101,10 @@
                 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 @@
                     }
                 }
             }
+          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 @@
           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 @@
 }
 
 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 -r f33fab6214c4 -r aa46a8ae3487 src/arch/arm/isa.hh
--- a/src/arch/arm/isa.hh       Wed Oct 29 23:18:26 2014 -0500
+++ b/src/arch/arm/isa.hh       Wed Oct 29 23:18:26 2014 -0500
@@ -429,6 +429,14 @@
 
         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 -r f33fab6214c4 -r aa46a8ae3487 src/arch/arm/linux/system.cc
--- a/src/arch/arm/linux/system.cc      Wed Oct 29 23:18:26 2014 -0500
+++ b/src/arch/arm/linux/system.cc      Wed Oct 29 23:18:26 2014 -0500
@@ -175,6 +175,10 @@
                  "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 -r f33fab6214c4 -r aa46a8ae3487 src/arch/arm/tlb.cc
--- a/src/arch/arm/tlb.cc       Wed Oct 29 23:18:26 2014 -0500
+++ b/src/arch/arm/tlb.cc       Wed Oct 29 23:18:26 2014 -0500
@@ -1089,7 +1089,14 @@
             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 -r f33fab6214c4 -r aa46a8ae3487 src/base/loader/dtb_object.cc
--- a/src/base/loader/dtb_object.cc     Wed Oct 29 23:18:26 2014 -0500
+++ b/src/base/loader/dtb_object.cc     Wed Oct 29 23:18:26 2014 -0500
@@ -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 @@
     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 -r f33fab6214c4 -r aa46a8ae3487 src/base/loader/dtb_object.hh
--- a/src/base/loader/dtb_object.hh     Wed Oct 29 23:18:26 2014 -0500
+++ b/src/base/loader/dtb_object.hh     Wed Oct 29 23:18:26 2014 -0500
@@ -60,6 +60,13 @@
           * @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,
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to