diff options
Diffstat (limited to 'src/arch/riscv/faults.cc')
-rw-r--r-- | src/arch/riscv/faults.cc | 35 |
1 files changed, 22 insertions, 13 deletions
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; |