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

Reply via email to