On Mon, Jun 1, 2026 at 2:23 PM Pierrick Bouvier
<[email protected]> wrote:
>
> On 5/29/2026 2:57 PM, Brian Cain wrote:
> > From: Brian Cain <[email protected]>
> >
> > The hardware-assisted scheduler helps manage tasks on the run queue
> > and interrupt steering.
> >
> > Signed-off-by: Brian Cain <[email protected]>
> > ---
> > target/hexagon/op_helper.c | 77 ++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 77 insertions(+)
> >
> > diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
> > index 64f1fb2043f..82062a2f802 100644
> > --- a/target/hexagon/op_helper.c
> > +++ b/target/hexagon/op_helper.c
> > @@ -1589,6 +1589,64 @@ 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;
> > + HexagonCPU *cpu;
> > +
> > + BQL_LOCK_GUARD();
> > + qemu_log_mask(CPU_LOG_INT, "%s: check resched\n", __func__);
> > + 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;
> > + }
> > +
>
> Is that really a noop in this case?
> Or should it trigger an exception if sched is not enabled?
It's a noop, the scheduler has no effect when SCHEDCFG_EN is disabled.
> > + 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 %u,"
> > + " cur PC 0x%" PRIx32 "\n",
> > + __func__, (unsigned)int_number, env->gpr[HEX_REG_PC]);
> > + SET_SYSTEM_FIELD(env, HEX_SREG_BESTWAIT, BESTWAIT_PRIO, ~0);
> > + hex_raise_interrupts(env, 1 << int_number, CPU_INTERRUPT_SWI);
> > + }
> > +}
> > +
> > void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
> > {
> > BQL_LOCK_GUARD();
> > @@ -1697,8 +1755,27 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState
> > *env, uint32_t reg)
> > g_assert_not_reached();
> > }
> >
> > +/*
> > + * setprio/resched - hardware-assisted scheduler helpers for managing
> > + * the run queue and interrupt steering.
> > + */
> > 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 %" PRIu32 " prio = 0x%" PRIx32 "\n",
> > + __func__, found_env->threadId, prio);
> > + resched(env);
> > + return;
> > + }
> > + }
> > g_assert_not_reached();
> > }
> >
>