dev,arm: remove and recreate timer events around drains
authorCurtis Dunham <Curtis.Dunham@arm.com>
Thu, 18 May 2017 21:18:48 +0000 (21:18 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Wed, 5 Jul 2017 14:24:03 +0000 (14:24 +0000)
Having timer events stored in checkpoints complicates Kvm
execution.  We change the timer behavior so that it always
deschedules any pending events on a drain() and recreates
them on a drainResume(), thus they will never appear in
checkpoints henceforth.  This pattern of behavior makes
it simpler to handle Kvm execution, where the hardware
performs the timer function directly.

Change-Id: Ia218868c69350d96e923c640634d492b5c19cd3f
Reviewed-on: https://gem5-review.googlesource.com/3541
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/dev/arm/generic_timer.cc
src/dev/arm/generic_timer.hh

index efaebb1bad2e3c72845e770b68a7930fd01cf7a1..48f70e135346121a362ed153928670af918c6c6f 100644 (file)
@@ -179,13 +179,6 @@ ArchTimer::serialize(CheckpointOut &cp) const
     paramOut(cp, "control_serial", _control);
     SERIALIZE_SCALAR(_counterLimit);
     SERIALIZE_SCALAR(_offset);
-
-    const bool event_scheduled(_counterLimitReachedEvent.scheduled());
-    SERIALIZE_SCALAR(event_scheduled);
-    if (event_scheduled) {
-        const Tick event_time(_counterLimitReachedEvent.when());
-        SERIALIZE_SCALAR(event_time);
-    }
 }
 
 void
@@ -197,13 +190,24 @@ ArchTimer::unserialize(CheckpointIn &cp)
     // compatibility.
     if (!UNSERIALIZE_OPT_SCALAR(_offset))
         _offset = 0;
-    bool event_scheduled;
-    UNSERIALIZE_SCALAR(event_scheduled);
-    if (event_scheduled) {
-        Tick event_time;
-        UNSERIALIZE_SCALAR(event_time);
-        _parent.schedule(_counterLimitReachedEvent, event_time);
-    }
+
+    // We no longer schedule an event here because we may enter KVM
+    // emulation.  The event creation is delayed until drainResume().
+}
+
+DrainState
+ArchTimer::drain()
+{
+    if (_counterLimitReachedEvent.scheduled())
+        _parent.deschedule(_counterLimitReachedEvent);
+
+    return DrainState::Drained;
+}
+
+void
+ArchTimer::drainResume()
+{
+    updateCounter();
 }
 
 void
index 3a389548922385df542de3c8282da1fd460efe65..3eec1d42e22704ea248913149ed8d26ef1d836cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015 ARM Limited
+ * Copyright (c) 2013, 2015, 2017 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -102,7 +102,7 @@ class SystemCounter : public Serializable
 };
 
 /// Per-CPU architected timer.
-class ArchTimer : public Serializable
+class ArchTimer : public Serializable, public Drainable
 {
   public:
     class Interrupt
@@ -188,9 +188,14 @@ class ArchTimer : public Serializable
     /// Returns the value of the counter which this timer relies on.
     uint64_t value() const;
 
+    // Serializable
     void serialize(CheckpointOut &cp) const override;
     void unserialize(CheckpointIn &cp) override;
 
+    // Drainable
+    DrainState drain() override;
+    void drainResume() override;
+
   private:
     // Disable copying
     ArchTimer(const ArchTimer &t);