arm, kmi: Clear interrupts in KMI devices

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>
This commit is contained in:
Sudhanshu Jha 2017-02-27 10:29:56 +00:00 committed by Andreas Sandberg
parent 46bfc14312
commit 746e2f3c27
2 changed files with 22 additions and 24 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010 ARM Limited * Copyright (c) 2010, 2017 ARM Limited
* All rights reserved * All rights reserved
* *
* The license below extends only to copyright in the software and shall * The license below extends only to copyright in the software and shall
@ -53,7 +53,7 @@
Pl050::Pl050(const Params *p) Pl050::Pl050(const Params *p)
: AmbaIntDevice(p, 0xfff), control(0), status(0x43), clkdiv(0), : 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) vnc(p->vnc), driverInitialized(false), intEvent(this)
{ {
if (vnc) { if (vnc) {
@ -101,8 +101,8 @@ Pl050::read(PacketPtr pkt)
data = clkdiv; data = clkdiv;
break; break;
case kmiISR: case kmiISR:
data = interrupts; data = getInterrupt();
DPRINTF(Pl050, "Read Interrupts: %#x\n", (uint32_t)interrupts); DPRINTF(Pl050, "Read Interrupts: %#x\n", getInterrupt());
break; break;
default: default:
if (readId(pkt, ambaId, pioAddr)) { if (readId(pkt, ambaId, pioAddr)) {
@ -238,28 +238,29 @@ Pl050::processCommand(uint8_t byte)
void void
Pl050::updateIntStatus() Pl050::updateIntStatus()
{ {
const bool old_interrupt(getInterrupt());
if (!rxQueue.empty()) if (!rxQueue.empty())
rawInterrupts.rx = 1; rawInterrupts.rx = 1;
else else
rawInterrupts.rx = 0; rawInterrupts.rx = 0;
interrupts.tx = rawInterrupts.tx & control.txint_enable; if ((!old_interrupt && getInterrupt()) && !intEvent.scheduled()) {
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())
schedule(intEvent, curTick() + intDelay); schedule(intEvent, curTick() + intDelay);
} else if (old_interrupt && !(getInterrupt())) {
gic->clearInt(intNum);
}
} }
void void
Pl050::generateInterrupt() Pl050::generateInterrupt()
{ {
DPRINTF(Pl050, "Generate Interrupt: rawInt=%#x ctrl=%#x int=%#x\n",
rawInterrupts, control, getInterrupt());
if (interrupts) { if (getInterrupt()) {
gic->sendInt(intNum); 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(stsreg);
SERIALIZE_SCALAR(clkdiv); SERIALIZE_SCALAR(clkdiv);
uint8_t ints = interrupts;
SERIALIZE_SCALAR(ints);
uint8_t raw_ints = rawInterrupts; uint8_t raw_ints = rawInterrupts;
SERIALIZE_SCALAR(raw_ints); SERIALIZE_SCALAR(raw_ints);
@ -344,10 +342,6 @@ Pl050::unserialize(CheckpointIn &cp)
UNSERIALIZE_SCALAR(clkdiv); UNSERIALIZE_SCALAR(clkdiv);
uint8_t ints;
UNSERIALIZE_SCALAR(ints);
interrupts = ints;
uint8_t raw_ints; uint8_t raw_ints;
UNSERIALIZE_SCALAR(raw_ints); UNSERIALIZE_SCALAR(raw_ints);
rawInterrupts = raw_ints; rawInterrupts = raw_ints;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010 ARM Limited * Copyright (c) 2010, 2017 ARM Limited
* All rights reserved * All rights reserved
* *
* The license below extends only to copyright in the software and shall * 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; Bitfield<1> tx;
EndBitUnion(InterruptReg) EndBitUnion(InterruptReg)
/** interrupt status register. */
InterruptReg interrupts;
/** raw interrupt register (unmasked) */ /** raw interrupt register (unmasked) */
InterruptReg rawInterrupts; InterruptReg rawInterrupts;
@ -129,6 +126,13 @@ class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
/** Function to generate interrupt */ /** Function to generate interrupt */
void generateInterrupt(); 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 */ /** Wrapper to create an event out of the thing */
EventWrapper<Pl050, &Pl050::generateInterrupt> intEvent; EventWrapper<Pl050, &Pl050::generateInterrupt> intEvent;