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)