arch-riscv: Fix WFI race condition
Current WFI implementation always put the CPU to sleep even if there's an pending interrupt. This might cause issue because an interrupt might happen just before the WFI is executed, and there might not be any further interrupts to wake the CPU up, so the CPU sleeps indefinitely. In this CL, we ensure the CPU sleeps only if there's no pending interrupt at all, regardless whether the interrupt is masked or not. We intentionally check for masked interrupt as well because a masked interrupt is also able to wake the CPU up if it occurs after WFI. This will make the behavior consistent no matter the interrupt comes before or after WFI. Change-Id: I74dbc01fed52652101675f1ae8e481b77c932088 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/62251 Tested-by: kokoro <noreply+kokoro@google.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
This commit is contained in:
@@ -1906,7 +1906,17 @@ decode QUADRANT default Unknown::unknown() {
|
||||
"wfi in user mode or TW enabled",
|
||||
machInst);
|
||||
}
|
||||
xc->tcBase()->quiesce();
|
||||
// Go to sleep only if there's no pending interrupt
|
||||
// at all, including masked interrupts.
|
||||
auto tc = xc->tcBase();
|
||||
auto cpu = tc->getCpuPtr();
|
||||
auto ic = dynamic_cast<RiscvISA::Interrupts*>(
|
||||
cpu->getInterruptController(tc->threadId()));
|
||||
panic_if(!ic, "Invalid Interrupt Controller.");
|
||||
if (ic->readIP() == 0
|
||||
&& xc->readMiscReg(MISCREG_NMIP) == 0) {
|
||||
tc->quiesce();
|
||||
}
|
||||
}}, No_OpClass);
|
||||
}
|
||||
0x9: sfence_vma({{
|
||||
|
||||
@@ -52,6 +52,7 @@ output header {{
|
||||
#include "arch/riscv/insts/standard.hh"
|
||||
#include "arch/riscv/insts/static_inst.hh"
|
||||
#include "arch/riscv/insts/unknown.hh"
|
||||
#include "arch/riscv/interrupts.hh"
|
||||
#include "cpu/static_inst.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
Reference in New Issue
Block a user