summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcdirik <cdirik@micron.com>2015-01-06 15:10:22 -0700
committercdirik <cdirik@micron.com>2015-01-06 15:10:22 -0700
commit1693e526d090f47323e378f0bd8546f28c2a97f7 (patch)
treebf026901c1b0fd644cef546fc1d69e252a46e789
parent1c1fb2c9886134c5ab4a877e2ac5baae8c2390a9 (diff)
downloadgem5-1693e526d090f47323e378f0bd8546f28c2a97f7.tar.xz
dev: prevent intel 8254 timer counter events firing before startup
This change includes edits to Intel8254Timer to prevent counter events firing before startup to comply with SimObject initialization call sequence. Committed by: Nilay Vaish <nilay@cs.wisc.edu>
-rw-r--r--src/dev/alpha/tsunami_io.cc1
-rw-r--r--src/dev/intel_8254_timer.cc54
-rw-r--r--src/dev/intel_8254_timer.hh14
-rwxr-xr-xsrc/dev/mips/malta_io.cc1
-rw-r--r--src/dev/x86/i8254.cc6
-rw-r--r--src/dev/x86/i8254.hh1
6 files changed, 63 insertions, 14 deletions
diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc
index a20cd8a88..2236546fc 100644
--- a/src/dev/alpha/tsunami_io.cc
+++ b/src/dev/alpha/tsunami_io.cc
@@ -288,6 +288,7 @@ void
TsunamiIO::startup()
{
rtc.startup();
+ pitimer.startup();
}
TsunamiIO *
diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc
index 4aa3fec14..63bb6e8af 100644
--- a/src/dev/intel_8254_timer.cc
+++ b/src/dev/intel_8254_timer.cc
@@ -89,13 +89,22 @@ Intel8254Timer::unserialize(const string &base, Checkpoint *cp,
counter[2]->unserialize(base + ".counter2", cp, section);
}
+void
+Intel8254Timer::startup()
+{
+ counter[0]->startup();
+ counter[1]->startup();
+ counter[2]->startup();
+}
+
Intel8254Timer::Counter::Counter(Intel8254Timer *p,
const string &name, unsigned int _num)
- : _name(name), num(_num), event(this), initial_count(0),
- latched_count(0), period(0), mode(0), output_high(false),
- latch_on(false), read_byte(LSB), write_byte(LSB), parent(p)
+ : _name(name), num(_num), event(this), running(false),
+ initial_count(0), latched_count(0), period(0), mode(0),
+ output_high(false), latch_on(false), read_byte(LSB),
+ write_byte(LSB), parent(p)
{
-
+ offset = period * event.getInterval();
}
void
@@ -179,7 +188,9 @@ Intel8254Timer::Counter::write(const uint8_t data)
else
period = initial_count;
- if (period > 0)
+ offset = period * event.getInterval();
+
+ if (running && (period > 0))
event.setTo(period);
write_byte = LSB;
@@ -229,10 +240,10 @@ Intel8254Timer::Counter::serialize(const string &base, ostream &os)
paramOut(os, base + ".read_byte", read_byte);
paramOut(os, base + ".write_byte", write_byte);
- Tick event_tick = 0;
+ Tick event_tick_offset = 0;
if (event.scheduled())
- event_tick = event.when();
- paramOut(os, base + ".event_tick", event_tick);
+ event_tick_offset = event.when() - curTick();
+ paramOut(os, base + ".event_tick_offset", event_tick_offset);
}
void
@@ -248,12 +259,20 @@ 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 = 0;
- if (event.scheduled())
- parent->deschedule(event);
- paramIn(cp, section, base + ".event_tick", event_tick);
- if (event_tick)
- parent->schedule(event, event_tick);
+ Tick event_tick_offset = 0;
+ assert(!event.scheduled());
+ paramIn(cp, section, base + ".event_tick_offset", event_tick_offset);
+ offset = event_tick_offset;
+}
+
+void
+Intel8254Timer::Counter::startup()
+{
+ running = true;
+ if ((period > 0) && (offset > 0))
+ {
+ parent->schedule(event, curTick() + offset);
+ }
}
Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
@@ -302,3 +321,10 @@ Intel8254Timer::Counter::CounterEvent::description() const
{
return "Intel 8254 Interval timer";
}
+
+Tick
+Intel8254Timer::Counter::CounterEvent::getInterval()
+{
+ return interval;
+}
+
diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh
index ad751447e..b2fd949f2 100644
--- a/src/dev/intel_8254_timer.hh
+++ b/src/dev/intel_8254_timer.hh
@@ -102,6 +102,8 @@ class Intel8254Timer : public EventManager
void setTo(int clocks);
int clocksLeft();
+
+ Tick getInterval();
};
private:
@@ -112,6 +114,9 @@ class Intel8254Timer : public EventManager
CounterEvent event;
+ /** True after startup is called. */
+ bool running;
+
/** Initial count value */
uint16_t initial_count;
@@ -121,6 +126,9 @@ class Intel8254Timer : public EventManager
/** Interrupt period */
uint16_t period;
+ /** When to start ticking */
+ Tick offset;
+
/** Current mode of operation */
uint8_t mode;
@@ -181,6 +189,9 @@ class Intel8254Timer : public EventManager
*/
void unserialize(const std::string &base, Checkpoint *cp,
const std::string &section);
+
+ /** Start ticking */
+ void startup();
};
protected:
@@ -246,6 +257,9 @@ class Intel8254Timer : public EventManager
*/
void unserialize(const std::string &base, Checkpoint *cp,
const std::string &section);
+
+ /** Start ticking */
+ void startup();
};
#endif // __DEV_8254_HH__
diff --git a/src/dev/mips/malta_io.cc b/src/dev/mips/malta_io.cc
index 6797a054c..d79e43260 100755
--- a/src/dev/mips/malta_io.cc
+++ b/src/dev/mips/malta_io.cc
@@ -146,6 +146,7 @@ void
MaltaIO::startup()
{
rtc.startup();
+ pitimer.startup();
}
MaltaIO *
diff --git a/src/dev/x86/i8254.cc b/src/dev/x86/i8254.cc
index f6af34a65..b80952237 100644
--- a/src/dev/x86/i8254.cc
+++ b/src/dev/x86/i8254.cc
@@ -89,6 +89,12 @@ X86ISA::I8254::unserialize(Checkpoint *cp, const std::string &section)
pit.unserialize("pit", cp, section);
}
+void
+X86ISA::I8254::startup()
+{
+ pit.startup();
+}
+
X86ISA::I8254 *
I8254Params::create()
{
diff --git a/src/dev/x86/i8254.hh b/src/dev/x86/i8254.hh
index 49ea271e9..76521e73e 100644
--- a/src/dev/x86/i8254.hh
+++ b/src/dev/x86/i8254.hh
@@ -111,6 +111,7 @@ class I8254 : public BasicPioDevice
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ virtual void startup();
};