From f5e03741c7a4daa36d56fc4d187c02adfd8af172 Mon Sep 17 00:00:00 2001 From: Jui-Min Lee Date: Wed, 20 Jul 2022 16:59:32 +0800 Subject: [PATCH] arch-riscv: Make WFI halt the hart First, this CL modifies the implementation of WFI so it actually put the calling CPU into sleep. This CL also adds an id in the IRQ table to represent NMI. This is because the wakeup path is only implemented on cpu's postInterrupt function, and it expects an int_num. We still keep the MISCREG for nmie and nmip instead of merging them into other ip/ie as that will give the user ability to get/set the nmi status, which is pretty dangerous. Change-Id: Idf8a5748990efa20aa9372efa97d3bed2aac82d9 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/61511 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/arch/riscv/faults.hh | 6 +++++- src/arch/riscv/interrupts.hh | 12 ++++++++++-- src/arch/riscv/isa/decoder.isa | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/arch/riscv/faults.hh b/src/arch/riscv/faults.hh index 1bc671ef26..e66476727c 100644 --- a/src/arch/riscv/faults.hh +++ b/src/arch/riscv/faults.hh @@ -93,7 +93,11 @@ enum ExceptionCode : uint64_t INT_EXT_USER = 8, INT_EXT_SUPER = 9, INT_EXT_MACHINE = 11, - NumInterruptTypes + NumInterruptTypes, + // INT_NMI does not exist in the spec, it's a modeling artifact for NMI. We + // intentionally set it to be NumInterruptTypes so it can never conflict + // with any real INT_NUM in used. + INT_NMI = NumInterruptTypes, }; enum class FaultType diff --git a/src/arch/riscv/interrupts.hh b/src/arch/riscv/interrupts.hh index 88b7b2e5a4..f10c5f386a 100644 --- a/src/arch/riscv/interrupts.hh +++ b/src/arch/riscv/interrupts.hh @@ -141,14 +141,22 @@ class Interrupts : public BaseInterrupts post(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); - ip[int_num] = true; + if (int_num != INT_NMI) { + ip[int_num] = true; + } else { + postNMI(); + } } void clear(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); - ip[int_num] = false; + if (int_num != INT_NMI) { + ip[int_num] = false; + } else { + clearNMI(); + } } void postNMI() { tc->setMiscReg(MISCREG_NMIP, 1); } diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 7a10fa0bdb..04a36c1a8c 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -1906,7 +1906,7 @@ decode QUADRANT default Unknown::unknown() { "wfi in user mode or TW enabled", machInst); } - // don't do anything for now + xc->tcBase()->quiesce(); }}, No_OpClass); } 0x9: sfence_vma({{