aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2019-03-27 23:06:05 -0700
committerAndrew Waterman <andrew@sifive.com>2019-03-27 23:06:05 -0700
commit496c59d064961bb81e63e2bba1bdadd4abf05a52 (patch)
tree19bbefa4f3b7daad6144bf8fb5479a6dc72c8b2f
parentc01631de5027b211a374a01cbbd046a11926df0e (diff)
downloadriscv-isa-sim-496c59d064961bb81e63e2bba1bdadd4abf05a52.zip
riscv-isa-sim-496c59d064961bb81e63e2bba1bdadd4abf05a52.tar.gz
riscv-isa-sim-496c59d064961bb81e63e2bba1bdadd4abf05a52.tar.bz2
Respect interrupt priorities even when not delegated
The spec says that e.g. MEI takes priority over SEI. We got this right in the common case that SEI is delegated to S-mode, but we reversed it in the undelegated case. The destination privilege was correct, so this wasn't much of a problem, but it is technically noncompliant. Resolves #288
-rw-r--r--riscv/processor.cc22
1 files changed, 13 insertions, 9 deletions
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 08d5854..f8c4446 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -191,15 +191,19 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
// nonstandard interrupts have highest priority
if (enabled_interrupts >> IRQ_M_EXT)
enabled_interrupts = enabled_interrupts >> IRQ_M_EXT << IRQ_M_EXT;
- // external interrupts have next-highest priority
- else if (enabled_interrupts & (MIP_MEIP | MIP_SEIP))
- enabled_interrupts = enabled_interrupts & (MIP_MEIP | MIP_SEIP);
- // software interrupts have next-highest priority
- else if (enabled_interrupts & (MIP_MSIP | MIP_SSIP))
- enabled_interrupts = enabled_interrupts & (MIP_MSIP | MIP_SSIP);
- // timer interrupts have next-highest priority
- else if (enabled_interrupts & (MIP_MTIP | MIP_STIP))
- enabled_interrupts = enabled_interrupts & (MIP_MTIP | MIP_STIP);
+ // standard interrupt priority is MEI, MSI, MTI, SEI, SSI, STI
+ else if (enabled_interrupts & MIP_MEIP)
+ enabled_interrupts = MIP_MEIP;
+ else if (enabled_interrupts & MIP_MSIP)
+ enabled_interrupts = MIP_MSIP;
+ else if (enabled_interrupts & MIP_MTIP)
+ enabled_interrupts = MIP_MTIP;
+ else if (enabled_interrupts & MIP_SEIP)
+ enabled_interrupts = MIP_SEIP;
+ else if (enabled_interrupts & MIP_SSIP)
+ enabled_interrupts = MIP_SSIP;
+ else if (enabled_interrupts & MIP_STIP)
+ enabled_interrupts = MIP_STIP;
else
abort();