From: Brian Cain <[email protected]>
Reviewed-by: Taylor Simpson <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
target/hexagon/cpu_helper.h | 1 +
target/hexagon/cpu.c | 22 +++++++++++++++++++
target/hexagon/cpu_helper.c | 44 +++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index dc99b4c294b..7d7cf58acc8 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 6849dc7966b..cec06daed73 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -449,6 +449,28 @@ static void hexagon_cpu_realize(DeviceState *dev, Error
**errp)
static int hexagon_cpu_mmu_index(CPUState *cs, bool ifetch)
{
+#ifndef CONFIG_USER_ONLY
+ BQL_LOCK_GUARD();
+ CPUHexagonState *env = cpu_env(cs);
+ HexagonCPU *cpu = HEXAGON_CPU(cs);
+ if (cpu->globalregs) {
+ uint32_t syscfg =
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+ env->threadId);
+ 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;
}
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index dcb07283494..0521c01c84c 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -302,3 +302,47 @@ void hexagon_stop_thread(CPUHexagonState *env)
SHUTDOWN_CAUSE_GUEST_SHUTDOWN, get_thread0_r2());
}
}
+
+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 = env->t_sreg[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;
+}
--
2.34.1