From 746e2f3c27ad83c36b7bc3b8bd3c92004fcf995b Mon Sep 17 00:00:00 2001 From: Sudhanshu Jha Date: Mon, 27 Feb 2017 10:29:56 +0000 Subject: [PATCH] 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 Reviewed-on: https://gem5-review.googlesource.com/2225 Reviewed-by: Rahul Thakur --- src/dev/arm/kmi.cc | 34 ++++++++++++++-------------------- src/dev/arm/kmi.hh | 12 ++++++++---- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/dev/arm/kmi.cc b/src/dev/arm/kmi.cc index 941546743..9230c15d2 100644 --- a/src/dev/arm/kmi.cc +++ b/src/dev/arm/kmi.cc @@ -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; diff --git a/src/dev/arm/kmi.hh b/src/dev/arm/kmi.hh index a321caf63..55e4b4285 100644 --- a/src/dev/arm/kmi.hh +++ b/src/dev/arm/kmi.hh @@ -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 intEvent;