@samitouri / QOSamiQemu / commits / 36858aaf8a

target/hexagon: Implement exec_interrupt, set_irq

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Brian Cain committed Jun 22, 2026 at 15:28 UTC 36858aaf8af23171815778c6d72a0c15033f6043
1 file changed +84
target/hexagon/cpu.c
+84
@@ -16,6 +16,7 @@
16 */
17
18 #include "qemu/osdep.h"
19 +#include "qemu/log.h"
20 #include "qemu/qemu-print.h"
21 #include "cpu.h"
22 #include "internal.h"
@@ -31,10 +32,12 @@
32 #include "hex_mmu.h"
33
34 #ifndef CONFIG_USER_ONLY
35 +#include "macros.h"
36 #include "sys_macros.h"
37 #include "accel/tcg/cpu-ldst.h"
38 #include "qemu/main-loop.h"
39 #include "hex_interrupts.h"
40 +#include "exec/cpu-interrupt.h"
41 #endif
42
43 static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
@@ -304,6 +307,36 @@ static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
307 cpu_env(cs)->gpr[HEX_REG_PC] = tb->pc;
308 }
309
310 +#ifndef CONFIG_USER_ONLY
311 +bool hexagon_thread_is_enabled(CPUHexagonState *env)
312 +{
313 + HexagonCPU *cpu = env_archcpu(env);
314 + uint32_t modectl;
315 + uint32_t thread_enabled_mask;
316 + bool E_bit;
317 +
318 + if (!cpu->globalregs) {
319 + return true;
320 + }
321 + modectl =
322 + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
323 + env->threadId);
324 + thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
325 + E_bit = thread_enabled_mask & (0x1 << env->threadId);
326 +
327 + return E_bit;
328 +}
329 +
330 +static bool hexagon_cpu_has_work(CPUState *cs)
331 +{
332 + CPUHexagonState *env = cpu_env(cs);
333 +
334 + return hexagon_thread_is_enabled(env) &&
335 + (cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI
336 + | CPU_INTERRUPT_K0_UNLOCK | CPU_INTERRUPT_TLB_UNLOCK));
337 +}
338 +#endif
339 +
340 static void hexagon_restore_state_to_opc(CPUState *cs,
341 const TranslationBlock *tb,
342 const uint64_t *data)
@@ -412,10 +445,58 @@ static int hexagon_cpu_mmu_index(CPUState *cs, bool ifetch)
445 return MMU_USER_IDX;
446 }
447
448 +#ifndef CONFIG_USER_ONLY
449 +static void hexagon_cpu_set_irq(void *opaque, int irq, int level)
450 +{
451 + HexagonCPU *cpu = HEXAGON_CPU(opaque);
452 + CPUState *cs = CPU(cpu);
453 + CPUHexagonState *env = cpu_env(cs);
454 +
455 + switch (irq) {
456 + case HEXAGON_CPU_IRQ_0 ... HEXAGON_CPU_IRQ_7:
457 + qemu_log_mask(CPU_LOG_INT, "%s: irq %d, level %d\n",
458 + __func__, irq, level);
459 + if (level) {
460 + hex_raise_interrupts(env, 1 << irq, CPU_INTERRUPT_HARD);
461 + }
462 + break;
463 + default:
464 + g_assert_not_reached();
465 + }
466 +}
467 +#endif
468 +
469 static void hexagon_cpu_init(Object *obj)
470 {
471 +#ifndef CONFIG_USER_ONLY
472 + HexagonCPU *cpu = HEXAGON_CPU(obj);
473 + qdev_init_gpio_in(DEVICE(cpu), hexagon_cpu_set_irq, 8);
474 +#endif
475 +}
476 +
477 +#ifndef CONFIG_USER_ONLY
478 +
479 +static bool hexagon_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
480 +{
481 + CPUHexagonState *env = cpu_env(cs);
482 + if (interrupt_request & CPU_INTERRUPT_TLB_UNLOCK) {
483 + cs->halted = false;
484 + cpu_reset_interrupt(cs, CPU_INTERRUPT_TLB_UNLOCK);
485 + return true;
486 + }
487 + if (interrupt_request & CPU_INTERRUPT_K0_UNLOCK) {
488 + cs->halted = false;
489 + cpu_reset_interrupt(cs, CPU_INTERRUPT_K0_UNLOCK);
490 + return true;
491 + }
492 + if (interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI)) {
493 + return hex_check_interrupts(env);
494 + }
495 + return false;
496 }
497
498 +#endif
499 +
500 static const TCGCPUOps hexagon_tcg_ops = {
501 /* MTTCG not yet supported: require strict ordering */
502 .guest_default_memory_order = TCG_MO_ALL,
@@ -426,6 +507,9 @@ static const TCGCPUOps hexagon_tcg_ops = {
507 .synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
508 .restore_state_to_opc = hexagon_restore_state_to_opc,
509 .mmu_index = hexagon_cpu_mmu_index,
510 +#ifndef CONFIG_USER_ONLY
511 + .cpu_exec_interrupt = hexagon_cpu_exec_interrupt,
512 +#endif /* !CONFIG_USER_ONLY */
513 };
514
515 static void hexagon_cpu_class_init(ObjectClass *c, const void *data)