Andreas Sandberg has submitted this change and it was merged. ( https://gem5-review.googlesource.com/2331 )

Change subject: dev, arm: Add draining to the GIC model
......................................................................

dev, arm: Add draining to the GIC model

The GIC model currently adds a delay to interrupts when posting them
to a target CPU. This means that an interrupt signal will be
represented by an event for a short period of time. We currently
ignore this when draining and serialize the tick when the interrupt
will fire. Upon loading the checkpoint, the simulated GIC reschedules
the pending events. This behaviour is undesirable when we implement
support for switching between in-kernel GIC emulation and gem5 GIC
emulation. In that case, the (kernel) GIC model gets a lot simpler if
we don't need to worry about in-flight interrupts from the gem5 GIC.

This changeset adds a draining check to force the GIC into a state
where all interrupts have been delivered prior to checkpointing/CPU
switching. It also removes the now redundant serialization of
interrupt events.

Change-Id: I8b8b080aa291ca029a3a7bdd1777f1fcd5b01179
Signed-off-by: Andreas Sandberg <[email protected]>
Reviewed-by: Curtis Dunham <[email protected]>
Reviewed-on: https://gem5-review.googlesource.com/2331
Reviewed-by: Jason Lowe-Power <[email protected]>
---
M src/dev/arm/gic_pl390.cc
M src/dev/arm/gic_pl390.hh
2 files changed, 49 insertions(+), 21 deletions(-)

Approvals:
  Jason Lowe-Power: Looks good to me, approved
  Andreas Sandberg: Looks good to me, approved



diff --git a/src/dev/arm/gic_pl390.cc b/src/dev/arm/gic_pl390.cc
index f21d5c5..04c3949 100644
--- a/src/dev/arm/gic_pl390.cc
+++ b/src/dev/arm/gic_pl390.cc
@@ -76,7 +76,8 @@
       cpuSgiPending {}, cpuSgiActive {},
       cpuSgiPendingExt {}, cpuSgiActiveExt {},
       cpuPpiPending {}, cpuPpiActive {},
-      irqEnable(false)
+      irqEnable(false),
+      pendingDelayedInterrupts(0)
 {
     for (int x = 0; x < CPU_MAX; x++) {
         iccrpr[x] = 0xff;
@@ -85,7 +86,7 @@
         cpuBpr[x] = 0;
         // Initialize cpu highest int
         cpuHighestInt[x] = SPURIOUS_INT;
-        postIntEvent[x] = new PostIntEvent(x, p->platform);
+        postIntEvent[x] = new PostIntEvent(*this, x);
     }
DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
             cpuEnabled[1]);
@@ -812,10 +813,31 @@
 void
 Pl390::postInt(uint32_t cpu, Tick when)
 {
-    if (!(postIntEvent[cpu]->scheduled()))
+    if (!(postIntEvent[cpu]->scheduled())) {
+        ++pendingDelayedInterrupts;
         eventq->schedule(postIntEvent[cpu], when);
+    }
 }

+void
+Pl390::postDelayedInt(uint32_t cpu)
+{
+    platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0);
+    --pendingDelayedInterrupts;
+    assert(pendingDelayedInterrupts >= 0);
+    if (pendingDelayedInterrupts == 0)
+        signalDrainDone();
+}
+
+DrainState
+Pl390::drain()
+{
+    if (pendingDelayedInterrupts == 0) {
+        return DrainState::Drained;
+    } else {
+        return DrainState::Draining;
+    }
+}

 void
 Pl390::serialize(CheckpointOut &cp) const
@@ -842,14 +864,6 @@
     SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
     SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
     SERIALIZE_SCALAR(irqEnable);
-    Tick interrupt_time[CPU_MAX];
-    for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
-        interrupt_time[cpu] = 0;
-        if (postIntEvent[cpu]->scheduled()) {
-            interrupt_time[cpu] = postIntEvent[cpu]->when();
-        }
-    }
-    SERIALIZE_ARRAY(interrupt_time, CPU_MAX);
     SERIALIZE_SCALAR(gem5ExtensionsEnabled);

     for (uint32_t i=0; i < bankedRegs.size(); ++i) {
@@ -895,13 +909,18 @@
     UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
     UNSERIALIZE_SCALAR(irqEnable);

-    Tick interrupt_time[CPU_MAX];
-    UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
+    // Handle checkpoints from before we drained the GIC to prevent
+    // in-flight interrupts.
+    if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) {
+        Tick interrupt_time[CPU_MAX];
+        UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);

-    for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
-        if (interrupt_time[cpu])
-            schedule(postIntEvent[cpu], interrupt_time[cpu]);
+        for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
+            if (interrupt_time[cpu])
+                schedule(postIntEvent[cpu], interrupt_time[cpu]);
+        }
     }
+
     if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled))
         gem5ExtensionsEnabled = false;

diff --git a/src/dev/arm/gic_pl390.hh b/src/dev/arm/gic_pl390.hh
index 533a0f3..6647058 100644
--- a/src/dev/arm/gic_pl390.hh
+++ b/src/dev/arm/gic_pl390.hh
@@ -318,25 +318,32 @@
     int intNumToWord(int num) const { return num >> 5; }
     int intNumToBit(int num) const { return num % 32; }

-    /** Post an interrupt to a CPU
+    /**
+     * Post an interrupt to a CPU with a delay
      */
     void postInt(uint32_t cpu, Tick when);
+
+    /**
+     * Deliver a delayed interrupt to the target CPU
+     */
+    void postDelayedInt(uint32_t cpu);

     /** Event definition to post interrupt to CPU after a delay
     */
     class PostIntEvent : public Event
     {
       private:
+        Pl390 &parent;
         uint32_t cpu;
-        Platform *platform;
       public:
-        PostIntEvent( uint32_t c, Platform* p)
-            : cpu(c), platform(p)
+        PostIntEvent(Pl390 &_parent, uint32_t _cpu)
+            : parent(_parent), cpu(_cpu)
         { }
- void process() { platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0);}
+        void process() { parent.postDelayedInt(cpu); }
         const char *description() const { return "Post Interrupt to CPU"; }
     };
     PostIntEvent *postIntEvent[CPU_MAX];
+    int pendingDelayedInterrupts;

   public:
     typedef Pl390Params Params;
@@ -347,6 +354,8 @@
     }
     Pl390(const Params *p);

+    DrainState drain() override;
+
     void serialize(CheckpointOut &cp) const override;
     void unserialize(CheckpointIn &cp) override;


--
To view, visit https://gem5-review.googlesource.com/2331
To unsubscribe, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I8b8b080aa291ca029a3a7bdd1777f1fcd5b01179
Gerrit-Change-Number: 2331
Gerrit-PatchSet: 2
Gerrit-Owner: Andreas Sandberg <[email protected]>
Gerrit-Reviewer: Andreas Sandberg <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to