From b47b123b32d8125ed0e797f4ae8104f69cce1df7 Mon Sep 17 00:00:00 2001 From: Alec Roelke Date: Fri, 13 Jul 2018 10:48:01 -0400 Subject: 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 Maintainer: Jason Lowe-Power --- src/arch/riscv/faults.cc | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'src/arch/riscv/faults.cc') diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index a151334c4..2cf6d768f 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -61,13 +61,24 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) STATUS status = tc->readMiscReg(MISCREG_STATUS); // Set fault handler privilege mode - if (pp != PRV_M && - bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) { - prv = PRV_S; - } - if (pp == PRV_U && - bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) { - prv = PRV_U; + if (isInterrupt()) { + if (pp != PRV_M && + bits(tc->readMiscReg(MISCREG_MIDELEG), _code) != 0) { + prv = PRV_S; + } + if (pp == PRV_U && + bits(tc->readMiscReg(MISCREG_SIDELEG), _code) != 0) { + prv = PRV_U; + } + } else { + if (pp != PRV_M && + bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) { + prv = PRV_S; + } + if (pp == PRV_U && + bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) { + prv = PRV_U; + } } // Set fault registers and status @@ -116,7 +127,10 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) tc->setMiscReg(MISCREG_STATUS, status); // Set PC to fault handler address - pcState.set(tc->readMiscReg(tvec) >> 2); + Addr addr = tc->readMiscReg(tvec) >> 2; + if (isInterrupt() && bits(tc->readMiscReg(tvec), 1, 0) == 1) + addr += 4 * _code; + pcState.set(addr); } else { invokeSE(tc, inst); advancePC(pcState, inst); @@ -126,11 +140,6 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) void Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst) { - if (FullSystem) { - tc->getCpuPtr()->clearInterrupts(tc->threadId()); - tc->clearArchRegs(); - } - tc->setMiscReg(MISCREG_PRV, PRV_M); STATUS status = tc->readMiscReg(MISCREG_STATUS); status.mie = 0; -- cgit v1.2.3