From: Brian Cain <bc...@quicinc.com> Signed-off-by: Brian Cain <brian.c...@oss.qualcomm.com> --- target/hexagon/cpu_helper.h | 1 + target/hexagon/cpu.c | 23 +++++++++++++++++++++ target/hexagon/cpu_helper.c | 41 +++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+)
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h index 0723485e79..0a5134204f 100644 --- a/target/hexagon/cpu_helper.h +++ b/target/hexagon/cpu_helper.h @@ -15,6 +15,7 @@ void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t); void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env, uint32_t); void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env, uint32_t); void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old); +int get_cpu_mode(CPUHexagonState *env); int get_exe_mode(CPUHexagonState *env); void clear_wait_mode(CPUHexagonState *env); void hexagon_ssr_set_cause(CPUHexagonState *env, uint32_t cause); diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index 7afdcbf9d0..c7c470b099 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -650,6 +650,28 @@ static const TCGCPUOps hexagon_tcg_ops = { #endif /* !CONFIG_USER_ONLY */ }; +static int hexagon_cpu_mmu_index(CPUState *cs, bool ifetch) +{ +#ifndef CONFIG_USER_ONLY + BQL_LOCK_GUARD(); + CPUHexagonState *env = cpu_env(cs); + uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG); + uint8_t mmuen = GET_SYSCFG_FIELD(SYSCFG_MMUEN, syscfg); + if (!mmuen) { + return MMU_KERNEL_IDX; + } + + int cpu_mode = get_cpu_mode(env); + if (cpu_mode == HEX_CPU_MODE_MONITOR) { + return MMU_KERNEL_IDX; + } else if (cpu_mode == HEX_CPU_MODE_GUEST) { + return MMU_GUEST_IDX; + } +#endif + + return MMU_USER_IDX; +} + static void hexagon_cpu_class_init(ObjectClass *c, void *data) { @@ -667,6 +689,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = hexagon_cpu_class_by_name; cc->has_work = hexagon_cpu_has_work; + cc->mmu_index = hexagon_cpu_mmu_index; cc->dump_state = hexagon_dump_state; cc->set_pc = hexagon_cpu_set_pc; cc->get_pc = hexagon_cpu_get_pc; diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c index cc1a896542..9c44cb7950 100644 --- a/target/hexagon/cpu_helper.c +++ b/target/hexagon/cpu_helper.c @@ -394,4 +394,45 @@ void hexagon_stop_thread(CPUHexagonState *env) } } +static int sys_in_monitor_mode_ssr(uint32_t ssr) +{ + if ((GET_SSR_FIELD(SSR_EX, ssr) != 0) || + ((GET_SSR_FIELD(SSR_EX, ssr) == 0) && (GET_SSR_FIELD(SSR_UM, ssr) == 0))) + return 1; + return 0; +} + +static int sys_in_guest_mode_ssr(uint32_t ssr) +{ + if ((GET_SSR_FIELD(SSR_EX, ssr) == 0) && + (GET_SSR_FIELD(SSR_UM, ssr) != 0) && + (GET_SSR_FIELD(SSR_GM, ssr) != 0)) + return 1; + return 0; +} + +static int sys_in_user_mode_ssr(uint32_t ssr) +{ + if ((GET_SSR_FIELD(SSR_EX, ssr) == 0) && + (GET_SSR_FIELD(SSR_UM, ssr) != 0) && + (GET_SSR_FIELD(SSR_GM, ssr) == 0)) + return 1; + return 0; +} + +int get_cpu_mode(CPUHexagonState *env) + +{ + uint32_t ssr = arch_get_system_reg(env, HEX_SREG_SSR); + + if (sys_in_monitor_mode_ssr(ssr)) { + return HEX_CPU_MODE_MONITOR; + } else if (sys_in_guest_mode_ssr(ssr)) { + return HEX_CPU_MODE_GUEST; + } else if (sys_in_user_mode_ssr(ssr)) { + return HEX_CPU_MODE_USER; + } + return HEX_CPU_MODE_MONITOR; +} + #endif -- 2.34.1