arm, kmi: Clear interrupts in KMI devices
authorSudhanshu Jha <sudhanshu.jha@arm.com>
Mon, 27 Feb 2017 10:29:56 +0000 (10:29 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 7 Mar 2017 11:14:28 +0000 (11:14 +0000)
Added functionality to check and clear interrupts for KMI
devices. This fixes a boot bug when using KVM and in-kernel GIC
emulation.

Change-Id: Ia3e91d07567b7faf3f82b0adfda4a165a502a339
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2225
Reviewed-by: Rahul Thakur <rjthakur@google.com>
src/dev/arm/kmi.cc
src/dev/arm/kmi.hh

index 941546743f02e299bd95a5dbaf13f14a6c814f75..9230c15d2636546262812616f224a68a816a11e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010, 2017 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -53,7 +53,7 @@
 
 Pl050::Pl050(const Params *p)
     : AmbaIntDevice(p, 0xfff), control(0), status(0x43), clkdiv(0),
-      interrupts(0), rawInterrupts(0), ackNext(false), shiftDown(false),
+      rawInterrupts(0), ackNext(false), shiftDown(false),
       vnc(p->vnc), driverInitialized(false), intEvent(this)
 {
     if (vnc) {
@@ -101,8 +101,8 @@ Pl050::read(PacketPtr pkt)
         data = clkdiv;
         break;
       case kmiISR:
-        data = interrupts;
-        DPRINTF(Pl050, "Read Interrupts: %#x\n", (uint32_t)interrupts);
+        data = getInterrupt();
+        DPRINTF(Pl050, "Read Interrupts: %#x\n", getInterrupt());
         break;
       default:
         if (readId(pkt, ambaId, pioAddr)) {
@@ -238,28 +238,29 @@ Pl050::processCommand(uint8_t byte)
 void
 Pl050::updateIntStatus()
 {
+    const bool old_interrupt(getInterrupt());
+
     if (!rxQueue.empty())
         rawInterrupts.rx = 1;
     else
         rawInterrupts.rx = 0;
 
-    interrupts.tx = rawInterrupts.tx & control.txint_enable;
-    interrupts.rx = rawInterrupts.rx & control.rxint_enable;
-
-    DPRINTF(Pl050, "rawInterupts=%#x control=%#x interrupts=%#x\n",
-            (uint32_t)rawInterrupts, (uint32_t)control, (uint32_t)interrupts);
-
-    if (interrupts && !intEvent.scheduled())
+    if ((!old_interrupt && getInterrupt()) && !intEvent.scheduled()) {
         schedule(intEvent, curTick() + intDelay);
+    } else if (old_interrupt && !(getInterrupt())) {
+            gic->clearInt(intNum);
+    }
 }
 
 void
 Pl050::generateInterrupt()
 {
+    DPRINTF(Pl050, "Generate Interrupt: rawInt=%#x ctrl=%#x int=%#x\n",
+            rawInterrupts, control, getInterrupt());
 
-    if (interrupts) {
+    if (getInterrupt()) {
         gic->sendInt(intNum);
-        DPRINTF(Pl050, "Generated interrupt\n");
+        DPRINTF(Pl050, " -- Generated\n");
     }
 }
 
@@ -318,9 +319,6 @@ Pl050::serialize(CheckpointOut &cp) const
     SERIALIZE_SCALAR(stsreg);
     SERIALIZE_SCALAR(clkdiv);
 
-    uint8_t ints = interrupts;
-    SERIALIZE_SCALAR(ints);
-
     uint8_t raw_ints = rawInterrupts;
     SERIALIZE_SCALAR(raw_ints);
 
@@ -344,10 +342,6 @@ Pl050::unserialize(CheckpointIn &cp)
 
     UNSERIALIZE_SCALAR(clkdiv);
 
-    uint8_t ints;
-    UNSERIALIZE_SCALAR(ints);
-    interrupts = ints;
-
     uint8_t raw_ints;
     UNSERIALIZE_SCALAR(raw_ints);
     rawInterrupts = raw_ints;
index a321caf63754d35c2bf69569c5667f35ce3e77dd..55e4b4285ac9f900dbaf8d9dfc5103cacfb9477b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010, 2017 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -101,9 +101,6 @@ class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
         Bitfield<1> tx;
     EndBitUnion(InterruptReg)
 
-    /** interrupt status register. */
-    InterruptReg interrupts;
-
     /** raw interrupt register (unmasked) */
     InterruptReg rawInterrupts;
 
@@ -129,6 +126,13 @@ class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
     /** Function to generate interrupt */
     void generateInterrupt();
 
+    /** Get interrupt value */
+    InterruptReg getInterrupt() const {
+        InterruptReg tmp_interrupt(0);
+        tmp_interrupt.tx = rawInterrupts.tx & control.txint_enable;
+        tmp_interrupt.rx = rawInterrupts.rx & control.rxint_enable;
+        return tmp_interrupt;
+    }
     /** Wrapper to create an event out of the thing */
     EventWrapper<Pl050, &Pl050::generateInterrupt> intEvent;