cpu: Flush TLBs on switchOut()
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>
Mon, 7 Jan 2013 18:05:48 +0000 (13:05 -0500)
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>
Mon, 7 Jan 2013 18:05:48 +0000 (13:05 -0500)
This changeset inserts a TLB flush in BaseCPU::switchOut to prevent
stale translations when doing repeated switching. Additionally, the
TLB flushing functionality is exported to the Python to make debugging
of switching/checkpointing easier.

A simulation script will typically use the TLB flushing functionality
to generate a reference trace. The following sequence can be used to
simulate a handover (this depends on how drain is implemented, but is
generally the case) between identically configured CPU models:

  m5.drain(test_sys)
  [ cpu.flushTLBs() for cpu in test_sys.cpu ]
  m5.resume(test_sys)

The generated trace should normally be identical to a trace generated
when switching between identically configured CPU models or
checkpointing and resuming.

src/arch/sparc/tlb.hh
src/cpu/BaseCPU.py
src/cpu/base.cc
src/cpu/base.hh

index 8ed10ff0e66dcfe7cf9a4a668c5279d48b130cca..7246cd4f6f19b936f7b5a891b5519c5308d66a3d 100644 (file)
@@ -114,6 +114,10 @@ class TLB : public BaseTLB
      */
     TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0,
             bool update_used = true);
+
+    /** Remove all entries from the TLB */
+    void flushAll();
+
   protected:
     /** Insert a PTE into the TLB. */
     void insert(Addr vpn, int partition_id, int context_id, bool real,
@@ -122,9 +126,6 @@ class TLB : public BaseTLB
     /** Given an entry id, read that tlb entries' tag. */
     uint64_t TagRead(int entry);
 
-    /** Remove all entries from the TLB */
-    void flushAll();
-
     /** Remove all non-locked entries from the tlb that match partition id. */
     void demapAll(int partition_id);
 
index 6673b9d4136dc81732dbd42c9bd9c239f141ab7b..900a2399117a4d5d7b332d392cd50444320c68bf 100644 (file)
@@ -96,6 +96,7 @@ class BaseCPU(MemObject):
     void switchOut();
     void takeOverFrom(BaseCPU *cpu);
     bool switchedOut();
+    void flushTLBs();
 ''')
 
     def takeOverFrom(self, old_cpu):
index 202dc476a6abb7e4f56040fb61d7683b6039fd7a..14b5586c88300b6ed160990e2a66c109d92dd880 100644 (file)
@@ -361,6 +361,10 @@ BaseCPU::switchOut()
     _switchedOut = true;
     if (profileEvent && profileEvent->scheduled())
         deschedule(profileEvent);
+
+    // Flush all TLBs in the CPU to avoid having stale translations if
+    // it gets switched in later.
+    flushTLBs();
 }
 
 void
@@ -482,6 +486,22 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
     getDataPort().bind(data_peer_port);
 }
 
+void
+BaseCPU::flushTLBs()
+{
+    for (ThreadID i = 0; i < threadContexts.size(); ++i) {
+        ThreadContext &tc(*threadContexts[i]);
+        CheckerCPU *checker(tc.getCheckerCpuPtr());
+
+        tc.getITBPtr()->flushAll();
+        tc.getDTBPtr()->flushAll();
+        if (checker) {
+            checker->getITBPtr()->flushAll();
+            checker->getDTBPtr()->flushAll();
+        }
+    }
+}
+
 
 BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval)
     : cpu(_cpu), interval(_interval)
index 633b7f2a70cf7eca0992a40b032e8a65d8814494..cd30d29bcaf31ebccf98143d9cdcd6a9439b88e5 100644 (file)
@@ -323,6 +323,17 @@ class BaseCPU : public MemObject
      */
     virtual void takeOverFrom(BaseCPU *cpu);
 
+    /**
+     * Flush all TLBs in the CPU.
+     *
+     * This method is mainly used to flush stale translations when
+     * switching CPUs. It is also exported to the Python world to
+     * allow it to request a TLB flush after draining the CPU to make
+     * it easier to compare traces when debugging
+     * handover/checkpointing.
+     */
+    void flushTLBs();
+
     /**
      * Determine if the CPU is switched out.
      *