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:
Jui-Min Lee
2022-08-10 18:01:29 +08:00
committed by Jui-min Lee
parent 3b7ac7aa54
commit afd3e17f17
2 changed files with 12 additions and 1 deletions

View File

@@ -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({{

View File

@@ -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"