diff options
author | Andrew Waterman <andrew@sifive.com> | 2019-03-27 23:06:05 -0700 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2019-03-27 23:06:05 -0700 |
commit | 496c59d064961bb81e63e2bba1bdadd4abf05a52 (patch) | |
tree | 19bbefa4f3b7daad6144bf8fb5479a6dc72c8b2f | |
parent | c01631de5027b211a374a01cbbd046a11926df0e (diff) | |
download | riscv-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.cc | 22 |
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(); |