devices: Fixed periodic interrupts to work with draining
authorBrad Beckmann <Brad.Beckmann@amd.com>
Fri, 20 Aug 2010 18:46:13 +0000 (11:46 -0700)
committerBrad Beckmann <Brad.Beckmann@amd.com>
Fri, 20 Aug 2010 18:46:13 +0000 (11:46 -0700)
Added drain functions to the RTC and 8254 timer so that periodic interrupts
stop when the system is draining.  This patch is needed to checkpoint in
timing mode.  Otherwise under certain situations, the event queue will never
be completely empty.

src/dev/alpha/tsunami_io.cc
src/dev/alpha/tsunami_io.hh
src/dev/intel_8254_timer.cc
src/dev/intel_8254_timer.hh
src/dev/mc146818.cc
src/dev/mc146818.hh

index c90f06b5a97825cf6a413a5d03090cfb8dc1ae90..1a76c2c32619caf39ce9255c31941b679a0cc890 100644 (file)
@@ -249,6 +249,17 @@ TsunamiIO::clearPIC(uint8_t bitvector)
     }
 }
 
+unsigned int 
+TsunamiIO::drain(Event *de)
+{
+    unsigned int count = 0;
+    count += pitimer.drain(de);
+    count += rtc.drain(de);
+    assert(count == 0);
+    changeState(SimObject::Drained);
+    return count;
+}
+
 void
 TsunamiIO::serialize(ostream &os)
 {
index b6d63322b61b94ef01c42a76f51a2cb84818a3e5..f649247e2d0e5da6bfc6cce931ff199a222cf501 100644 (file)
@@ -140,6 +140,12 @@ class TsunamiIO : public BasicPioDevice
      */
     void clearPIC(uint8_t bitvector);
 
+    /**
+     * Drain the io state including all associated events.
+     * @param drainEvent
+     */
+    unsigned int drain(Event *de);
+
     /**
      * Serialize this object to the given output stream.
      * @param os The stream to serialize to.
index 9e507b9681a6a4c5b619ed8a9026a624350167d5..b61aa7c5694608d20b736526dbb788ce38d07f31 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "base/misc.hh"
 #include "dev/intel_8254_timer.hh"
+#include "sim/sim_object.hh"
 
 using namespace std;
 
@@ -69,6 +70,17 @@ Intel8254Timer::writeControl(const CtrlReg data)
     }
 }
 
+unsigned int 
+Intel8254Timer::drain(Event *de)
+{
+    unsigned int count = 0;
+    count += counter[0]->drain(de);
+    count += counter[1]->drain(de);
+    count += counter[2]->drain(de);
+    assert(count == 0);
+    return count;
+}
+
 void
 Intel8254Timer::serialize(const string &base, ostream &os)
 {
@@ -216,6 +228,18 @@ Intel8254Timer::Counter::outputHigh()
     return output_high;
 }
 
+unsigned int 
+Intel8254Timer::Counter::drain(Event *de)
+{
+    if (event.scheduled()) {
+        event_tick = event.when();
+        parent->deschedule(event);
+    } else {
+        event_tick = 0;
+    }
+    return 0;
+}
+
 void
 Intel8254Timer::Counter::serialize(const string &base, ostream &os)
 {
@@ -227,10 +251,6 @@ Intel8254Timer::Counter::serialize(const string &base, ostream &os)
     paramOut(os, base + ".latch_on", latch_on);
     paramOut(os, base + ".read_byte", read_byte);
     paramOut(os, base + ".write_byte", write_byte);
-
-    Tick event_tick = 0;
-    if (event.scheduled())
-        event_tick = event.when();
     paramOut(os, base + ".event_tick", event_tick);
 }
 
@@ -247,7 +267,6 @@ Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp,
     paramIn(cp, section, base + ".read_byte", read_byte);
     paramIn(cp, section, base + ".write_byte", write_byte);
 
-    Tick event_tick;
     paramIn(cp, section, base + ".event_tick", event_tick);
     if (event_tick)
         parent->schedule(event, event_tick);
index 30ddc7bcae148fa59612c30b6ffb9bef104866ea..26ea0687eebc739fcd20c81ba844048ae1e8611e 100644 (file)
@@ -137,6 +137,10 @@ class Intel8254Timer : public EventManager
         /** Pointer to container */
         Intel8254Timer *parent;
 
+        /** if non-zero, the scheduled tick of an event used for drain
+            serialization coordination */
+        Tick event_tick;
+
       public:
         Counter(Intel8254Timer *p, const std::string &name, unsigned int num);
 
@@ -164,6 +168,12 @@ class Intel8254Timer : public EventManager
         /** Is the output high? */
         bool outputHigh();
 
+        /**
+         * Drain all associated events.
+         * @param drainEvent
+         */
+        unsigned int drain(Event *de);
+
         /**
          * Serialize this object to the given output stream.
          * @param base The base name of the counter object.
@@ -229,6 +239,8 @@ class Intel8254Timer : public EventManager
         return counter[num]->outputHigh();
     }
 
+    unsigned int drain(Event *de);
+
     /**
      * Serialize this object to the given output stream.
      * @param base The base name of the counter object.
index 16ed58e463bb635bf8bf790be4856eb9e0033e83..fd70b503b65b2943fcd219f1a7d912ececc685a9 100644 (file)
@@ -40,6 +40,7 @@
 #include "base/trace.hh"
 #include "dev/mc146818.hh"
 #include "dev/rtcreg.h"
+#include "sim/sim_object.hh"
 
 using namespace std;
 
@@ -105,8 +106,12 @@ MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
 
 MC146818::~MC146818()
 {
-    deschedule(tickEvent);
-    deschedule(event);
+    if (tickEvent.scheduled()) {
+        deschedule(tickEvent);
+    }
+    if (event.scheduled()) {
+        deschedule(event);
+    }
 }
 
 void
@@ -203,6 +208,20 @@ MC146818::tickClock()
     setTime(*gmtime(&calTime));
 }
 
+unsigned int 
+MC146818::drain(Event *de)
+{
+    if (event.scheduled()) {
+        rtcTimerInterruptTickOffset = event.when() - curTick;
+        rtcClockTickOffset = event.when() - curTick;
+        deschedule(event);
+    }
+    if (tickEvent.scheduled()) {
+        deschedule(tickEvent);
+    }
+    return 0;
+}
+
 void
 MC146818::serialize(const string &base, ostream &os)
 {
@@ -214,9 +233,7 @@ MC146818::serialize(const string &base, ostream &os)
     // save the timer tick and rtc clock tick values to correctly reschedule 
     // them during unserialize
     //
-    Tick rtcTimerInterruptTickOffset = event.when() - curTick;
     SERIALIZE_SCALAR(rtcTimerInterruptTickOffset);
-    Tick rtcClockTickOffset = event.when() - curTick;
     SERIALIZE_SCALAR(rtcClockTickOffset);
 }
 
index 699785199a3ad9618875d3fce1fbe0ee0e85fc3a..507abab5a43b759c487feb566a7758feb0a664da 100644 (file)
@@ -119,6 +119,10 @@ class MC146818 : public EventManager
     /** RTC status register B */
     uint8_t stat_regB;
 
+    /** RTC event times for drain and serialization coordination */
+    Tick rtcTimerInterruptTickOffset;
+    Tick rtcClockTickOffset;
+
   public:
     MC146818(EventManager *em, const std::string &name, const struct tm time,
             bool bcd, Tick frequency);
@@ -132,6 +136,8 @@ class MC146818 : public EventManager
 
     void tickClock();
 
+    unsigned int drain(Event *de);
+
     /**
       * Serialize this object to the given output stream.
       * @param base The base name of the counter object.