kvm, arm: don't create interrupt events while saving GIC state
authorCurtis Dunham <Curtis.Dunham@arm.com>
Wed, 26 Apr 2017 15:21:34 +0000 (15:21 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Fri, 7 Jul 2017 10:32:28 +0000 (10:32 +0000)
If an interrupt was pending according to Kvm state during a drain,
the Pl390 model would create an interrupt event that could not be
serviced, preventing the system from draining.  The proper behavior
is for the Pl390 not actively being used for simulation to just skip
the GIC state machine that delivers interrupts.

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

src/arch/arm/kvm/gic.cc
src/arch/arm/kvm/gic.hh
src/dev/arm/gic_pl390.cc
src/dev/arm/gic_pl390.hh

index ce3baa5588f127459ec45a66558c66580a638559..d490265b88fe716145784c738aec648d726a0a97 100644 (file)
@@ -291,6 +291,17 @@ MuxingKvmGic::clearPPInt(uint32_t num, uint32_t cpu)
     kernelGic->clearPPI(cpu, num);
 }
 
+void
+MuxingKvmGic::updateIntState(int hint)
+{
+    // During Kvm->Pl390 state transfer, writes to the Pl390 will call
+    // updateIntState() which can post an interrupt.  Since we're only
+    // using the Pl390 model for holding state in this circumstance, we
+    // short-circuit this behavior, as the Pl390 is not actually active.
+    if (!usingKvm)
+        return Pl390::updateIntState(hint);
+}
+
 void
 MuxingKvmGic::copyDistRegister(BaseGicRegisters* from, BaseGicRegisters* to,
                                ContextID ctx, Addr daddr)
index ee04088d37123037213c2aa5d57e4f2679dd11bc..5447e6a92ae38edf821d5686feb51f8e90a22d5d 100644 (file)
@@ -194,6 +194,9 @@ class MuxingKvmGic : public Pl390
     void sendPPInt(uint32_t num, uint32_t cpu) override;
     void clearPPInt(uint32_t num, uint32_t cpu) override;
 
+  protected: // Pl390
+    void updateIntState(int hint) override;
+
   protected:
     /** System this interrupt controller belongs to */
     System &system;
index 7b63306c39236972d6668ad720cd0ce18549c289..93aaf5c45cb6acb3a0a787323c8f82dbce30fb1d 100644 (file)
@@ -871,6 +871,14 @@ Pl390::drain()
     }
 }
 
+
+void
+Pl390::drainResume()
+{
+    // There may be pending interrupts if checkpointed from Kvm; post them.
+    updateIntState(-1);
+}
+
 void
 Pl390::serialize(CheckpointOut &cp) const
 {
index 5c8a71222fb9295c360375a097fac7f3ba5a0ae2..3b35b59fb087f5d53e34630203584f2ef66e67a6 100644 (file)
@@ -318,7 +318,7 @@ class Pl390 : public BaseGic, public BaseGicRegisters
     /** See if some processor interrupt flags need to be enabled/disabled
      * @param hint which set of interrupts needs to be checked
      */
-    void updateIntState(int hint);
+    virtual void updateIntState(int hint);
 
     /** Update the register that records priority of the highest priority
      *  active interrupt*/
@@ -368,6 +368,7 @@ class Pl390 : public BaseGic, public BaseGicRegisters
     ~Pl390();
 
     DrainState drain() override;
+    void drainResume() override;
 
     void serialize(CheckpointOut &cp) const override;
     void unserialize(CheckpointIn &cp) override;