On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <[email protected]> wrote:
> From: Brian Cain <[email protected]> > > The hardware-assisted scheduler helps manage tasks on the run queue > and interrupt steering. > > This instruction is defined in the Qualcomm Hexagon V71 Programmer's > Reference > Manual - > > https://docs.qualcomm.com/bundle/publicresource/80-N2040-51_REV_AB_Hexagon_V71_ProgrammerS_Reference_Manual.pdf > See §11.9.2 SYSTEM MONITOR. > This document doesn't have a section 11.9.2. > > Signed-off-by: Brian Cain <[email protected]> > --- > target/hexagon/op_helper.c | 75 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 75 insertions(+) > > diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c > index 9090a5c20ab..36822219b4b 100644 > --- a/target/hexagon/op_helper.c > +++ b/target/hexagon/op_helper.c > @@ -1575,6 +1575,62 @@ static void hexagon_wait_thread(CPUHexagonState > *env, uint32_t PC) > cpu_interrupt(cs, CPU_INTERRUPT_HALT); > } > > +static inline QEMU_ALWAYS_INLINE void resched(CPUHexagonState *env) > +{ > + uint32_t schedcfg; > + uint32_t schedcfg_en; > + int int_number; > + CPUState *cs; > + uint32_t lowest_th_prio = 0; /* 0 is highest prio */ > + uint32_t bestwait_reg; > + uint32_t best_prio; > + > + BQL_LOCK_GUARD(); > + qemu_log_mask(CPU_LOG_INT, "%s: check resched\n", __func__); > + HexagonCPU *cpu = env_archcpu(env); > + schedcfg = cpu->globalregs ? > + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SCHEDCFG, > + env->threadId) : 0; > + schedcfg_en = GET_FIELD(SCHEDCFG_EN, schedcfg); > + int_number = GET_FIELD(SCHEDCFG_INTNO, schedcfg); > + > + if (!schedcfg_en) { > + return; > + } > + > + CPU_FOREACH(cs) { > + HexagonCPU *thread = HEXAGON_CPU(cs); > + CPUHexagonState *thread_env = &(thread->env); > + uint32_t th_prio = GET_FIELD( > + STID_PRIO, thread_env->t_sreg[HEX_SREG_STID]); > + if (!hexagon_thread_is_enabled(thread_env)) { > + continue; > + } > + > + lowest_th_prio = (lowest_th_prio > th_prio) > + ? lowest_th_prio > + : th_prio; > + } > + > + bestwait_reg = cpu->globalregs ? > + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_BESTWAIT, > + env->threadId) : 0; > + best_prio = GET_FIELD(BESTWAIT_PRIO, bestwait_reg); > + > + /* > + * If the lowest priority thread is lower priority than the > + * value in the BESTWAIT register, we must raise the reschedule > + * interrupt on the lowest priority thread. > + */ > + if (lowest_th_prio > best_prio) { > + qemu_log_mask(CPU_LOG_INT, > + "%s: raising resched int %d, cur PC 0x" TARGET_FMT_lx > "\n", > Don't use %d > + __func__, int_number, env->gpr[HEX_REG_PC]); > + SET_SYSTEM_FIELD(env, HEX_SREG_BESTWAIT, BESTWAIT_PRIO, ~0); > Is ~0 the correct value here? Seems like it should be best_prio. > + hex_raise_interrupts(env, 1 << int_number, CPU_INTERRUPT_SWI); > + } > +} > + > void HELPER(wait)(CPUHexagonState *env, uint32_t PC) > { > BQL_LOCK_GUARD(); > @@ -1680,8 +1736,27 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState > *env, uint32_t reg) > g_assert_not_reached(); > } > > +/* > + * setprio/resched - See the Hexagon V73 Programmer's Reference Manual, > + * Section 6.4 "Interrupt and Thread Scheduling" > Neither the V71 (mentioned above) or V73 PRM contain section 6.4. > + */ > void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio) > { > + CPUState *cs; > + > + BQL_LOCK_GUARD(); > + CPU_FOREACH(cs) { > + HexagonCPU *found_cpu = HEXAGON_CPU(cs); > + CPUHexagonState *found_env = &found_cpu->env; > + if (thread == found_env->threadId) { > + SET_SYSTEM_FIELD(found_env, HEX_SREG_STID, STID_PRIO, prio); > + qemu_log_mask(CPU_LOG_INT, > + "%s: tid " TARGET_FMT_lx " prio = 0x%x\n", > Don't use %x > + __func__, found_env->threadId, prio); > + resched(env); > + return; > + } > + } > g_assert_not_reached(); > } > > -- > 2.34.1 > >
