From 3a0c3aecafaeabc52ba63785552ba3b6baa798e6 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 29 Jan 2021 17:48:20 +0800 Subject: [PATCH] arch-riscv: Fixing interrupt handling order and effect of mideleg This patch fixes the issues listed in: https://gem5.atlassian.net/browse/GEM5-887 https://gem5.atlassian.net/browse/GEM5-889 The code change has been verified by booting FS linux. Software, timer and external interrupts work as expected. Change-Id: I6ce4fc843d2e0338355152c3fc33c966d6b4a481 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40076 Reviewed-by: Ayaz Akram Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/arch/riscv/interrupts.hh | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/arch/riscv/interrupts.hh b/src/arch/riscv/interrupts.hh index f07e7d7a7b..142911e892 100644 --- a/src/arch/riscv/interrupts.hh +++ b/src/arch/riscv/interrupts.hh @@ -66,16 +66,24 @@ class Interrupts : public BaseInterrupts { INTERRUPT mask = 0; STATUS status = tc->readMiscReg(MISCREG_STATUS); + INTERRUPT mideleg = tc->readMiscReg(MISCREG_MIDELEG); + INTERRUPT sideleg = tc->readMiscReg(MISCREG_SIDELEG); PrivilegeMode prv = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV); switch (prv) { case PRV_U: - mask.mei = mask.mti = mask.msi = 1; - mask.sei = mask.sti = mask.ssi = 1; + mask.mei = (!sideleg.mei) | (sideleg.mei & status.uie); + mask.mti = (!sideleg.mti) | (sideleg.mti & status.uie); + mask.msi = (!sideleg.msi) | (sideleg.msi & status.uie); + mask.sei = (!sideleg.sei) | (sideleg.sei & status.uie); + mask.sti = (!sideleg.sti) | (sideleg.sti & status.uie); + mask.ssi = (!sideleg.ssi) | (sideleg.ssi & status.uie); if (status.uie) mask.uei = mask.uti = mask.usi = 1; break; case PRV_S: - mask.mei = mask.mti = mask.msi = 1; + mask.mei = (!mideleg.mei) | (mideleg.mei & status.sie); + mask.mti = (!mideleg.mti) | (mideleg.mti & status.sie); + mask.msi = (!mideleg.msi) | (mideleg.msi & status.sie); if (status.sie) mask.sei = mask.sti = mask.ssi = 1; mask.uei = mask.uti = mask.usi = 0; @@ -105,9 +113,14 @@ class Interrupts : public BaseInterrupts { assert(checkInterrupts()); std::bitset mask = globalMask(); - for (int c = 0; c < NumInterruptTypes; c++) - if (checkInterrupt(c) && mask[c]) - return std::make_shared(c); + const std::vector interrupt_order { + INT_EXT_MACHINE, INT_TIMER_MACHINE, INT_SOFTWARE_MACHINE, + INT_EXT_SUPER, INT_TIMER_SUPER, INT_SOFTWARE_SUPER, + INT_EXT_USER, INT_TIMER_USER, INT_SOFTWARE_USER + }; + for (const int &id : interrupt_order) + if (checkInterrupt(id) && mask[id]) + return std::make_shared(id); return NoFault; }