@samitouri / QOSamiQemu / commits / 6a6542827a

target/hexagon: Implement setprio, resched

The hardware-assisted scheduler helps manage tasks on the run queue and interrupt steering. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Brian Cain committed Jun 22, 2026 at 15:28 UTC 6a6542827a0d7c7f23a69f635b00a9d2cb062563
1 file changed +77
target/hexagon/op_helper.c
+77
@@ -1590,6 +1590,64 @@ static void hexagon_wait_thread(CPUHexagonState *env, uint32_t PC)
1590 cpu_interrupt(cs, CPU_INTERRUPT_HALT);
1591 }
1592
1593 +static inline QEMU_ALWAYS_INLINE void resched(CPUHexagonState *env)
1594 +{
1595 + uint32_t schedcfg;
1596 + uint32_t schedcfg_en;
1597 + int int_number;
1598 + CPUState *cs;
1599 + uint32_t lowest_th_prio = 0; /* 0 is highest prio */
1600 + uint32_t bestwait_reg;
1601 + uint32_t best_prio;
1602 + HexagonCPU *cpu;
1603 +
1604 + BQL_LOCK_GUARD();
1605 + qemu_log_mask(CPU_LOG_INT, "%s: check resched\n", __func__);
1606 + cpu = env_archcpu(env);
1607 + schedcfg = cpu->globalregs ?
1608 + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SCHEDCFG,
1609 + env->threadId) : 0;
1610 + schedcfg_en = GET_FIELD(SCHEDCFG_EN, schedcfg);
1611 + int_number = GET_FIELD(SCHEDCFG_INTNO, schedcfg);
1612 +
1613 + if (!schedcfg_en) {
1614 + return;
1615 + }
1616 +
1617 + CPU_FOREACH(cs) {
1618 + HexagonCPU *thread = HEXAGON_CPU(cs);
1619 + CPUHexagonState *thread_env = &(thread->env);
1620 + uint32_t th_prio = GET_FIELD(
1621 + STID_PRIO, thread_env->t_sreg[HEX_SREG_STID]);
1622 + if (!hexagon_thread_is_enabled(thread_env)) {
1623 + continue;
1624 + }
1625 +
1626 + lowest_th_prio = (lowest_th_prio > th_prio)
1627 + ? lowest_th_prio
1628 + : th_prio;
1629 + }
1630 +
1631 + bestwait_reg = cpu->globalregs ?
1632 + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_BESTWAIT,
1633 + env->threadId) : 0;
1634 + best_prio = GET_FIELD(BESTWAIT_PRIO, bestwait_reg);
1635 +
1636 + /*
1637 + * If the lowest priority thread is lower priority than the
1638 + * value in the BESTWAIT register, we must raise the reschedule
1639 + * interrupt on the lowest priority thread.
1640 + */
1641 + if (lowest_th_prio > best_prio) {
1642 + qemu_log_mask(CPU_LOG_INT,
1643 + "%s: raising resched int %u,"
1644 + " cur PC 0x%" PRIx32 "\n",
1645 + __func__, (unsigned)int_number, env->gpr[HEX_REG_PC]);
1646 + SET_SYSTEM_FIELD(env, HEX_SREG_BESTWAIT, BESTWAIT_PRIO, ~0);
1647 + hex_raise_interrupts(env, 1 << int_number, CPU_INTERRUPT_SWI);
1648 + }
1649 +}
1650 +
1651 void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
1652 {
1653 BQL_LOCK_GUARD();
@@ -1698,8 +1756,27 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
1756 g_assert_not_reached();
1757 }
1758
1759 +/*
1760 + * setprio/resched - hardware-assisted scheduler helpers for managing
1761 + * the run queue and interrupt steering.
1762 + */
1763 void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio)
1764 {
1765 + CPUState *cs;
1766 +
1767 + BQL_LOCK_GUARD();
1768 + CPU_FOREACH(cs) {
1769 + HexagonCPU *found_cpu = HEXAGON_CPU(cs);
1770 + CPUHexagonState *found_env = &found_cpu->env;
1771 + if (thread == found_env->threadId) {
1772 + SET_SYSTEM_FIELD(found_env, HEX_SREG_STID, STID_PRIO, prio);
1773 + qemu_log_mask(CPU_LOG_INT,
1774 + "%s: tid %" PRIu32 " prio = 0x%" PRIx32 "\n",
1775 + __func__, found_env->threadId, prio);
1776 + resched(env);
1777 + return;
1778 + }
1779 + }
1780 g_assert_not_reached();
1781 }
1782