On 6/1/2026 12:39 PM, Brian Cain wrote:
> 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.
>
Ok.
>>> + 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();
>>> }
>>>
>>
Reviewed-by: Pierrick Bouvier <[email protected]>