summaryrefslogtreecommitdiff
path: root/src/arch/riscv/faults.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/riscv/faults.cc')
-rw-r--r--src/arch/riscv/faults.cc35
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;