ARM: Support switchover with hardware table walkers
authorAli Saidi <Ali.Saidi@ARM.com>
Wed, 8 Dec 2010 00:19:57 +0000 (16:19 -0800)
committerAli Saidi <Ali.Saidi@ARM.com>
Wed, 8 Dec 2010 00:19:57 +0000 (16:19 -0800)
src/arch/arm/table_walker.cc
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh
src/cpu/base.cc
src/sim/tlb.hh

index 98dc1760d1f97659ab11700c811e4739bf253c3d..88f2a455f7fbc7213dfade32e792a0fa19faf136 100644 (file)
@@ -92,8 +92,7 @@ TableWalker::getPort(const std::string &if_name, int idx)
 {
     if (if_name == "port") {
         if (port != NULL)
-            fatal("%s: port already connected to %s",
-                  name(), port->getPeer()->name());
+            return port;
         System *sys = params()->sys;
         Tick minb = params()->min_backoff;
         Tick maxb = params()->max_backoff;
index 6d6da15c805ca85040fad98b7d1c51efb35612f3..f142e03f82911b66c6c20907932c943baee531b8 100644 (file)
@@ -693,6 +693,18 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc,
     return fault;
 }
 
+Port*
+TLB::getPort()
+{
+#if FULL_SYSTEM
+    return tableWalker->getPort("port");
+#else
+    return NULL;
+#endif
+}
+
+
+
 ArmISA::TLB *
 ArmTLBParams::create()
 {
index 0b8bc1046ea9d2d565587a2c02d53c725f52906e..21062ea0d763599ad6072def01c1e53b3bbb91bc 100644 (file)
@@ -209,6 +209,9 @@ class TLB : public BaseTLB
 
     void regStats();
 
+    // Get the port from the table walker and return it
+    virtual Port *getPort();
+
     // Caching misc register values here.
     // Writing to misc registers needs to invalidate them.
     // translateFunctional/translateSe/translateFs checks if they are
index 556e7ec6f66c2497e100deaf644aa40c005b32c8..e0d29577d1755769a75aa9602ea9f0485d204736 100644 (file)
@@ -33,6 +33,7 @@
 #include <string>
 #include <sstream>
 
+#include "arch/tlb.hh"
 #include "base/cprintf.hh"
 #include "base/loader/symtab.hh"
 #include "base/misc.hh"
@@ -359,6 +360,26 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
            if (DTRACE(Context))
             ThreadContext::compare(oldTC, newTC);
         */
+
+        Port  *old_itb_port, *old_dtb_port, *new_itb_port, *new_dtb_port;
+        old_itb_port = oldTC->getITBPtr()->getPort();
+        old_dtb_port = oldTC->getDTBPtr()->getPort();
+        new_itb_port = newTC->getITBPtr()->getPort();
+        new_dtb_port = newTC->getDTBPtr()->getPort();
+
+        // Move over any table walker ports if they exist
+        if (new_itb_port && !new_itb_port->isConnected()) {
+            assert(old_itb_port);
+            Port *peer = old_itb_port->getPeer();;
+            new_itb_port->setPeer(peer);
+            peer->setPeer(new_itb_port);
+        }
+        if (new_dtb_port && !new_dtb_port->isConnected()) {
+            assert(old_dtb_port);
+            Port *peer = old_dtb_port->getPeer();;
+            new_dtb_port->setPeer(peer);
+            peer->setPeer(new_dtb_port);
+        }
     }
 
 #if FULL_SYSTEM
index ddd3127e50987a1c7666f7647b6db11b2615620c..a3e5c22c7b5202859a0a75fb16491f22c0f067d2 100644 (file)
@@ -38,6 +38,7 @@
 
 class ThreadContext;
 class Packet;
+class Port;
 
 class BaseTLB : public SimObject
 {
@@ -52,6 +53,11 @@ class BaseTLB : public SimObject
   public:
     virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
 
+    /** Get any port that the TLB or hardware table walker needs.
+     * This is used for migrating port connections during a takeOverFrom()
+     * call. */
+    virtual Port*  getPort() { return NULL; }
+
     class Translation
     {
       public: