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