On Wed, 21 Jan 2026 at 13:27, Ashish Anand <[email protected]> wrote: > > Currently, QEMU implements the 'Wait For Event' (WFE) instruction as a > simple yield. This causes high host CPU usage because guest > RTOS idle loops effectively become busy-wait loops. > > To improve efficiency, this patch transitions WFE to use the architectural > 'Halt' state (EXCP_HLT) for M-profile CPUs. This allows the host thread > to sleep when the guest is idle. > > To support this transition, we implement the full architectural behavior > required for WFE, specifically the 'Event Register', 'SEVONPEND' logic, > and 'R_BPBR' exception handling requirements defined in the ARM > Architecture Reference Manual. > > This patch enables resource-efficient idle emulation for Cortex-M. > > Signed-off-by: Ashish Anand <[email protected]> > --- > Changes in v2: > 1. Added R_BPBR handling as required by the Armv8-M architecture. > 2. Unified pending-state updates to detect interrupt transitions for > SEVONPEND. > 3. Moved the Event Register to the top-level ARM CPU state, since it is > architecturally shared between A-profile and M-profile CPUs. > 4. Updated migration handling to be profile-agnostic so the state can be > reused if A-profile WFE support is implemented in the future. > 5. Added CONFIG_USER_ONLY handling for WFE/SEV and tightened profile checks. > 6. Addressed review comments and fixes raised during v1 discussion. > > Link to v1 - > https://lore.kernel.org/qemu-devel/[email protected]/ > > > hw/intc/armv7m_nvic.c | 85 ++++++++++++++++++++++++++++++-------- > target/arm/cpu.c | 6 +++ > target/arm/cpu.h | 7 ++++ > target/arm/machine.c | 19 +++++++++ > target/arm/tcg/helper.h | 1 + > target/arm/tcg/m_helper.c | 5 +++ > target/arm/tcg/op_helper.c | 56 +++++++++++++++++++++---- > target/arm/tcg/t16.decode | 5 ++- > target/arm/tcg/t32.decode | 5 ++- > target/arm/tcg/translate.c | 29 +++++++++++-- > 10 files changed, 185 insertions(+), 33 deletions(-) > > diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c > index 3a31eb56f3..854d27e413 100644 > --- a/hw/intc/armv7m_nvic.c > +++ b/hw/intc/armv7m_nvic.c > @@ -221,6 +221,40 @@ static int exc_group_prio(NVICState *s, int rawprio, > bool targets_secure) > return rawprio; > } > > +/* > + * Update the pending state of an exception vector. > + * This is the central function for all updates to vec->pending. > + * Handles SEVONPEND: if this is a 0->1 transition on an external interrupt > + * and SEVONPEND is set in the appropriate SCR, sets the event register. > + */ > +static void nvic_update_pending_state(NVICState *s, int irq, bool secure, > + uint8_t next_pending_val) > +{ > + VecInfo *vec; > + int scr_bank; > + uint8_t prev_pending_val; > + > + if (secure && exc_is_banked(irq)) { > + vec = &s->sec_vectors[irq]; > + scr_bank = M_REG_S; > + } else { > + vec = &s->vectors[irq]; > + scr_bank = M_REG_NS; > + }
You already have the VecInfo pointer at all the callsites, so I think it would be better to pass it to this function rather than recalculating it from the irq number etc. I agree with Alex about using a bool for the event_register struct field. Otherwise I think this looks good! thanks -- PMM
