From: Brian Cain <bc...@quicinc.com> Reviewed-by: Taylor Simpson <ltaylorsimp...@gmail.com> Signed-off-by: Brian Cain <brian.c...@oss.qualcomm.com> --- target/hexagon/cpu.h | 5 +++ target/hexagon/cpu.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h index 354e9e9cbf..1491313d06 100644 --- a/target/hexagon/cpu.h +++ b/target/hexagon/cpu.h @@ -209,6 +209,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 22e21d401b..85ccf9893a 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -30,11 +30,13 @@ #include "hex_mmu.h" #ifndef CONFIG_USER_ONLY +#include "macros.h" #include "sys_macros.h" #include "accel/tcg/cpu-ldst.h" #include "qemu/main-loop.h" #include "hex_interrupts.h" #include "hexswi.h" +#include "exec/cpu-interrupt.h" #endif static void hexagon_v66_cpu_init(Object *obj) { } @@ -310,6 +312,34 @@ 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) +{ + HexagonCPU *cpu = env_archcpu(env); + if (!cpu->globalregs) { + return true; + } + 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, const TranslationBlock *tb, const uint64_t *data) @@ -431,10 +461,58 @@ static int hexagon_cpu_mmu_index(CPUState *cs, bool ifetch) return MMU_USER_IDX; } +#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 } +#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 = { /* MTTCG not yet supported: require strict ordering */ .guest_default_memory_order = TCG_MO_ALL, @@ -445,6 +523,9 @@ static const TCGCPUOps hexagon_tcg_ops = { .synchronize_from_tb = hexagon_cpu_synchronize_from_tb, .restore_state_to_opc = hexagon_restore_state_to_opc, .mmu_index = hexagon_cpu_mmu_index, +#if !defined(CONFIG_USER_ONLY) + .cpu_exec_interrupt = hexagon_cpu_exec_interrupt, +#endif /* !CONFIG_USER_ONLY */ }; static void hexagon_cpu_class_init(ObjectClass *c, const void *data) -- 2.34.1