summaryrefslogtreecommitdiff
path: root/src/arch/riscv/interrupts.hh
diff options
context:
space:
mode:
authorAlec Roelke <alec.roelke@gmail.com>2018-07-13 10:48:01 -0400
committerAlec Roelke <alec.roelke@gmail.com>2019-01-16 00:20:34 +0000
commitb47b123b32d8125ed0e797f4ae8104f69cce1df7 (patch)
treeaf8551a75cc2c32c16ece1796344f59cdfc7e03a /src/arch/riscv/interrupts.hh
parenta3be0a4cbc2665b91e1d83e25cfe709dd100ce5d (diff)
downloadgem5-b47b123b32d8125ed0e797f4ae8104f69cce1df7.tar.xz
arch-riscv: Add interrupt handling
Implement the Interrupts SimObject for RISC-V. This basically just handles setting and getting the values of the interrupt-pending and interrupt-enable CSRs according to the privileged ISA reference chapter 3.1.14. Note that it does NOT implement the PLIC as defined in chapter 7, as that is used for handling external interrupts which are defined based on peripherals that are available. Change-Id: Ia1321430f870ff5a3950217266fde0511332485b Reviewed-on: https://gem5-review.googlesource.com/c/14377 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Jason Lowe-Power <jason@lowepower.com>
Diffstat (limited to 'src/arch/riscv/interrupts.hh')
-rw-r--r--src/arch/riscv/interrupts.hh97
1 files changed, 66 insertions, 31 deletions
diff --git a/src/arch/riscv/interrupts.hh b/src/arch/riscv/interrupts.hh
index 60a5b5bc5..729af6fb9 100644
--- a/src/arch/riscv/interrupts.hh
+++ b/src/arch/riscv/interrupts.hh
@@ -31,8 +31,14 @@
#ifndef __ARCH_RISCV_INTERRUPT_HH__
#define __ARCH_RISCV_INTERRUPT_HH__
+#include <bitset>
+#include <memory>
+
+#include "arch/riscv/faults.hh"
+#include "arch/riscv/registers.hh"
#include "base/logging.hh"
#include "cpu/thread_context.hh"
+#include "debug/Interrupt.hh"
#include "params/RiscvInterrupts.hh"
#include "sim/sim_object.hh"
@@ -41,10 +47,16 @@ class ThreadContext;
namespace RiscvISA {
+/*
+ * This is based on version 1.10 of the RISC-V privileged ISA reference,
+ * chapter 3.1.14.
+ */
class Interrupts : public SimObject
{
private:
BaseCPU * cpu;
+ std::bitset<NumInterruptTypes> ip;
+ std::bitset<NumInterruptTypes> ie;
public:
typedef RiscvInterruptsParams Params;
@@ -55,64 +67,87 @@ class Interrupts : public SimObject
return dynamic_cast<const Params *>(_params);
}
- Interrupts(Params * p) : SimObject(p), cpu(nullptr)
- {}
+ Interrupts(Params * p) : SimObject(p), cpu(nullptr), ip(0), ie(0) {}
- void
- setCPU(BaseCPU * _cpu)
+ void setCPU(BaseCPU * _cpu) { cpu = _cpu; }
+
+ std::bitset<NumInterruptTypes>
+ globalMask(ThreadContext *tc) const
+ {
+ INTERRUPT mask;
+ STATUS status = tc->readMiscReg(MISCREG_STATUS);
+ if (status.mie)
+ mask.mei = mask.mti = mask.msi = 1;
+ if (status.sie)
+ mask.sei = mask.sti = mask.ssi = 1;
+ if (status.uie)
+ mask.uei = mask.uti = mask.usi = 1;
+ return std::bitset<NumInterruptTypes>(mask);
+ }
+
+ bool checkInterrupt(int num) const { return ip[num] && ie[num]; }
+ bool checkInterrupts(ThreadContext *tc) const
+ {
+ return (ip & ie & globalMask(tc)).any();
+ }
+
+ Fault
+ getInterrupt(ThreadContext *tc) const
{
- cpu = _cpu;
+ assert(checkInterrupts(tc));
+ std::bitset<NumInterruptTypes> mask = globalMask(tc);
+ for (int c = 0; c < NumInterruptTypes; c++)
+ if (checkInterrupt(c) && mask[c])
+ return std::make_shared<InterruptFault>(c);
+ return NoFault;
}
+ void updateIntrInfo(ThreadContext *tc) {}
+
void
post(int int_num, int index)
{
- panic("Interrupts::post not implemented.\n");
+ DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+ ip[int_num] = true;
}
void
clear(int int_num, int index)
{
- panic("Interrupts::clear not implemented.\n");
+ DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
+ ip[int_num] = false;
}
void
clearAll()
{
- warn_once("Interrupts::clearAll not implemented.\n");
+ DPRINTF(Interrupt, "All interrupts cleared\n");
+ ip = 0;
}
- bool
- checkInterrupts(ThreadContext *tc) const
- {
- warn_once("Interrupts::checkInterrupts just rudimentary implemented");
- /**
- * read the machine interrupt register in order to check if interrupts
- * are pending
- * should be sufficient for now, as interrupts
- * are not implemented at all
- */
- if (tc->readMiscReg(MISCREG_IP))
- return true;
-
- return false;
- }
+ MiscReg readIP() const { return (MiscReg)ip.to_ulong(); }
+ MiscReg readIE() const { return (MiscReg)ie.to_ulong(); }
+ void setIP(const MiscReg& val) { ip = val; }
+ void setIE(const MiscReg& val) { ie = val; }
- Fault
- getInterrupt(ThreadContext *tc)
+ void
+ serialize(CheckpointOut &cp)
{
- assert(checkInterrupts(tc));
- panic("Interrupts::getInterrupt not implemented.\n");
+ SERIALIZE_SCALAR(ip.to_ulong());
+ SERIALIZE_SCALAR(ie.to_ulong());
}
void
- updateIntrInfo(ThreadContext *tc)
+ unserialize(CheckpointIn &cp)
{
- panic("Interrupts::updateIntrInfo not implemented.\n");
+ long reg;
+ UNSERIALIZE_SCALAR(reg);
+ ip = reg;
+ UNSERIALIZE_SCALAR(reg);
+ ie = reg;
}
};
} // namespace RiscvISA
-#endif // __ARCH_RISCV_INTERRUPT_HH__
-
+#endif // __ARCH_RISCV_INTERRUPT_HH__ \ No newline at end of file