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:
parent
46bfc14312
commit
746e2f3c27
2 changed files with 22 additions and 24 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue