arch-riscv: Extend wfi behavior (#1364)

At the moment, a hart does not halt if there are pending interrupts.
However, an implementation can also consider the enable status of the
individual interrupts, i.e., a halted hart would only resume if there
are locally enabled pending interrupts. This commit introduces this
behavior. The wfi behavior is controlled by the new configuration
variable wfi_pending_resume of RiscvISA.

Change-Id: I316239f9732c6e73e6ad692491bca08d773dd995

---------

Signed-off-by: Robert Hauser <robert.hauser@uni-rostock.de>
This commit is contained in:
Robert Hauser
2024-08-09 20:28:15 +02:00
committed by GitHub
parent b8001a861b
commit e980780efd
4 changed files with 43 additions and 5 deletions

View File

@@ -14,6 +14,7 @@
# Copyright (c) 2016 RISC-V Foundation
# Copyright (c) 2016 The University of Virginia
# Copyright (c) 2023 The Regents of the University of California
# Copyright (c) 2024 University of Rostock
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -114,6 +115,16 @@ class RiscvISA(BaseISA):
enable_Zicbom_fs = Param.Bool(True, "Enable Zicbom extension in FS mode")
enable_Zicboz_fs = Param.Bool(True, "Enable Zicboz extension in FS mode")
wfi_resume_on_pending = Param.Bool(
False,
"If wfi_resume_on_pending is set to True, the hart will resume "
"execution when interrupt becomes pending. The local enabled status "
"is not considered.\n"
"If wfi_resume_on_pending is set to False, the hart will only "
"resume the execution when an locally enabled interrupt becomes "
"pending.",
)
def get_isa_string(self):
isa_extensions = []
# check for the base ISA type

View File

@@ -3,6 +3,7 @@
* Copyright (c) 2016 The University of Virginia
* Copyright (c) 2020 Barkhausen Institut
* Copyright (c) 2022 Google LLC
* Copyright (c) 2024 University of Rostock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -258,7 +259,8 @@ RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs);
ISA::ISA(const Params &p) : BaseISA(p, "riscv"),
_rvType(p.riscv_type), enableRvv(p.enable_rvv), vlen(p.vlen), elen(p.elen),
_privilegeModeSet(p.privilege_mode_set)
_privilegeModeSet(p.privilege_mode_set),
_wfiResumeOnPending(p.wfi_resume_on_pending)
{
_regClasses.push_back(&intRegClass);
_regClasses.push_back(&floatRegClass);

View File

@@ -5,6 +5,7 @@
* Copyright (c) 2016 RISC-V Foundation
* Copyright (c) 2016 The University of Virginia
* Copyright (c) 2020 Barkhausen Institut
* Coypright (c) 2024 University of Rostock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -98,6 +99,15 @@ class ISA : public BaseISA
*/
PrivilegeModeSet _privilegeModeSet;
/**
* The WFI instruction can halt the execution of a hart.
* If this variable is set true, the execution resumes if
* an interrupt becomes pending. If this variable is set
* to false, the execution only resumes if an locally enabled
* interrupt becomes pending.
*/
const bool _wfiResumeOnPending;
public:
using Params = RiscvISAParams;
@@ -170,6 +180,8 @@ class ISA : public BaseISA
PrivilegeModeSet getPrivilegeModeSet() { return _privilegeModeSet; }
bool resumeOnPending() { return _wfiResumeOnPending; }
virtual Addr getFaultHandlerAddr(
RegIndex idx, uint64_t cause, bool intr) const;
};

View File

@@ -4873,16 +4873,29 @@ decode QUADRANT default Unknown::unknown() {
"wfi in user mode or TW enabled",
machInst);
}
// 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()));
auto isa = dynamic_cast<RiscvISA::ISA*>(
tc->getIsaPtr());
panic_if(!ic, "Invalid Interrupt Controller.");
if (ic->readIP() == 0
if (isa->resumeOnPending()) {
// Go to sleep only if there are no pending
// interrupts at all, and no non-maskable
// interrupts.
if (ic->readIP() == 0
&& xc->readMiscReg(MISCREG_NMIP) == 0) {
tc->quiesce();
tc->quiesce();
}
} else {
// Go to sleep only if there are no enabled
// pending interrupts at all, and no
// non-maskable interrupts
if (!(ic->readIP() & ic->readIE())
&& xc->readMiscReg(MISCREG_NMIP) == 0) {
tc->quiesce();
}
}
}}, IsNonSpeculative, IsQuiesce,
IsSerializeAfter, No_OpClass, IsSquashAfter);