[PATCH v2 4/7] target/arm: Store SVC immediate for user-only

Richard Henderson posted 7 patches 2 days, 13 hours ago
Maintainers: Laurent Vivier <laurent@vivier.eu>, Pierrick Bouvier <pierrick.bouvier@linaro.org>, Peter Maydell <peter.maydell@linaro.org>
[PATCH v2 4/7] target/arm: Store SVC immediate for user-only
Posted by Richard Henderson 2 days, 13 hours ago
Rather than re-reading the insn during syscall processing to
find the immediate, store it in CPUARMState during translate.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h           |  1 +
 linux-user/arm/cpu_loop.c  | 13 ++++---------
 target/arm/tcg/translate.c | 19 +++++++++++++++++--
 3 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b11a31c807..5b564c7113 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -817,6 +817,7 @@ typedef struct CPUArchState {
     bool tagged_addr_enable;
 #else
     /* For usermode syscall translation.  */
+    uint32_t syscall_info;
     bool eabi;
 #endif /* !CONFIG_USER_ONLY */
 } CPUARMState;
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 19874f4c72..86f13ad83a 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -271,7 +271,6 @@ void cpu_loop(CPUARMState *env)
 {
     CPUState *cs = env_cpu(env);
     int trapnr, si_signo, si_code;
-    unsigned int n, insn;
     abi_ulong ret;
 
     for(;;) {
@@ -312,20 +311,16 @@ void cpu_loop(CPUARMState *env)
             break;
         case EXCP_SWI:
             {
+                unsigned int n;
+
                 env->eabi = true;
                 /* system call */
                 if (env->thumb) {
                     /* Thumb is always EABI style with syscall number in r7 */
                     n = env->regs[7];
                 } else {
-                    /*
-                     * Equivalent of kernel CONFIG_OABI_COMPAT: read the
-                     * Arm SVC insn to extract the immediate, which is the
-                     * syscall number in OABI.
-                     */
-                    /* FIXME - what to do if get_user() fails? */
-                    get_user_code_u32(insn, env->regs[15] - 4, env);
-                    n = insn & 0xffffff;
+                    /* The 24-bit SVC immediate is stored during translate. */
+                    n = env->syscall_info;
                     if (n == 0) {
                         /* zero immediate: EABI, syscall number in r7 */
                         n = env->regs[7];
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index ce427c5a3c..ec21e33a06 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -1158,6 +1158,21 @@ void unallocated_encoding(DisasContext *s)
     gen_exception_insn(s, 0, EXCP_UDEF, syn_uncategorized());
 }
 
+static void gen_exception_swi(DisasContext *s)
+{
+#ifdef CONFIG_USER_ONLY
+# ifndef TARGET_AARCH64
+    /*
+     * Only 16-bits of the immediate are recorded in the syndrome,
+     * so store the entire 24-bit immediate for cpu_loop().
+     */
+    tcg_gen_st_i32(tcg_constant_i32(s->svc_imm), tcg_env,
+                   offsetof(CPUARMState, syscall_info));
+# endif
+#endif
+    gen_exception(EXCP_SWI, syn_aa32_svc(s->svc_imm, s->thumb));
+}
+
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 void gen_lookup_tb(DisasContext *s)
 {
@@ -6781,7 +6796,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
         switch (dc->base.is_jmp) {
         case DISAS_SWI:
             gen_ss_advance(dc);
-            gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+            gen_exception_swi(dc);
             break;
         case DISAS_HVC:
             gen_ss_advance(dc);
@@ -6854,7 +6869,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
             gen_helper_yield(tcg_env);
             break;
         case DISAS_SWI:
-            gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+            gen_exception_swi(dc);
             break;
         case DISAS_HVC:
             gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
-- 
2.43.0