From: Brian Cain <bc...@quicinc.com> Signed-off-by: Brian Cain <brian.c...@oss.qualcomm.com> --- target/hexagon/cpu.h | 5 +++ target/hexagon/cpu.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h index 045581d7be..d28c1249f3 100644 --- a/target/hexagon/cpu.h +++ b/target/hexagon/cpu.h @@ -207,6 +207,11 @@ G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env, uintptr_t pc); #ifndef CONFIG_USER_ONLY +/* + * @return true if the @a thread_env hardware thread is + * not stopped. + */ +bool hexagon_thread_is_enabled(CPUHexagonState *thread_env); uint32_t hexagon_greg_read(CPUHexagonState *env, uint32_t reg); uint32_t hexagon_sreg_read(CPUHexagonState *env, uint32_t reg); void hexagon_gdb_sreg_write(CPUHexagonState *env, uint32_t reg, uint32_t val); diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index 843be8221f..e9f24581a6 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -31,6 +31,7 @@ #include "hex_mmu.h" #ifndef CONFIG_USER_ONLY +#include "macros.h" #include "sys_macros.h" #include "qemu/main-loop.h" #include "hex_interrupts.h" @@ -278,9 +279,28 @@ static void hexagon_cpu_synchronize_from_tb(CPUState *cs, cpu_env(cs)->gpr[HEX_REG_PC] = tb->pc; } +#ifndef CONFIG_USER_ONLY +bool hexagon_thread_is_enabled(CPUHexagonState *env) +{ + target_ulong modectl = arch_get_system_reg(env, HEX_SREG_MODECTL); + uint32_t thread_enabled_mask = GET_FIELD(MODECTL_E, modectl); + bool E_bit = thread_enabled_mask & (0x1 << env->threadId); + + return E_bit; +} +#endif + static bool hexagon_cpu_has_work(CPUState *cs) { +#ifndef CONFIG_USER_ONLY + CPUHexagonState *env = cpu_env(cs); + + return hexagon_thread_is_enabled(env) && + (cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI + | CPU_INTERRUPT_K0_UNLOCK | CPU_INTERRUPT_TLB_UNLOCK)); +#else return true; +#endif } static void hexagon_restore_state_to_opc(CPUState *cs, @@ -411,19 +431,72 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp) mcc->parent_realize(dev, errp); } +#if !defined(CONFIG_USER_ONLY) +static void hexagon_cpu_set_irq(void *opaque, int irq, int level) +{ + HexagonCPU *cpu = HEXAGON_CPU(opaque); + CPUState *cs = CPU(cpu); + CPUHexagonState *env = cpu_env(cs); + + switch (irq) { + case HEXAGON_CPU_IRQ_0 ... HEXAGON_CPU_IRQ_7: + qemu_log_mask(CPU_LOG_INT, "%s: irq %d, level %d\n", + __func__, irq, level); + if (level) { + hex_raise_interrupts(env, 1 << irq, CPU_INTERRUPT_HARD); + } + break; + default: + g_assert_not_reached(); + } +} +#endif + + static void hexagon_cpu_init(Object *obj) { +#if !defined(CONFIG_USER_ONLY) + HexagonCPU *cpu = HEXAGON_CPU(obj); + qdev_init_gpio_in(DEVICE(cpu), hexagon_cpu_set_irq, 8); +#endif } #include "hw/core/tcg-cpu-ops.h" +#ifndef CONFIG_USER_ONLY + +static bool hexagon_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + CPUHexagonState *env = cpu_env(cs); + if (interrupt_request & CPU_INTERRUPT_TLB_UNLOCK) { + cs->halted = false; + cpu_reset_interrupt(cs, CPU_INTERRUPT_TLB_UNLOCK); + return true; + } + if (interrupt_request & CPU_INTERRUPT_K0_UNLOCK) { + cs->halted = false; + cpu_reset_interrupt(cs, CPU_INTERRUPT_K0_UNLOCK); + return true; + } + if (interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI)) { + return hex_check_interrupts(env); + } + return false; +} + +#endif + static const TCGCPUOps hexagon_tcg_ops = { .initialize = hexagon_translate_init, .translate_code = hexagon_translate_code, .synchronize_from_tb = hexagon_cpu_synchronize_from_tb, .restore_state_to_opc = hexagon_restore_state_to_opc, +#if !defined(CONFIG_USER_ONLY) + .cpu_exec_interrupt = hexagon_cpu_exec_interrupt, +#endif /* !CONFIG_USER_ONLY */ }; + static void hexagon_cpu_class_init(ObjectClass *c, void *data) { HexagonCPUClass *mcc = HEXAGON_CPU_CLASS(c); -- 2.34.1