[PATCH v2 5/7] target/arm: Recognize linux faux BPKT

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 5/7] target/arm: Recognize linux faux BPKT
Posted by Richard Henderson 2 days, 13 hours ago
It is easier to recognize the insn from decodetree than it
is from cpu_loop.  In particular, there is a BE32 bug in
how we rebuild thumb2 insns in get_user_code_u32.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/arm/cpu_loop.c  | 28 ----------------------------
 target/arm/tcg/translate.c | 17 +++++++++++++++++
 target/arm/tcg/a32.decode  |  5 ++++-
 target/arm/tcg/t16.decode  |  1 +
 target/arm/tcg/t32.decode  |  5 ++++-
 5 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 86f13ad83a..4f7c5dab9c 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -194,24 +194,6 @@ do_kernel_trap(CPUARMState *env)
     return 0;
 }
 
-static bool insn_is_linux_bkpt(uint32_t opcode, bool is_thumb)
-{
-    /*
-     * Return true if this insn is one of the three magic UDF insns
-     * which the kernel treats as breakpoint insns.
-     */
-    if (!is_thumb) {
-        return (opcode & 0x0fffffff) == 0x07f001f0;
-    } else {
-        /*
-         * Note that we get the two halves of the 32-bit T32 insn
-         * in the opposite order to the value the kernel uses in
-         * its undef_hook struct.
-         */
-        return ((opcode & 0xffff) == 0xde01) || (opcode == 0xa000f7f0);
-    }
-}
-
 static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode)
 {
     TaskState *ts = get_task_state(env_cpu(env));
@@ -291,16 +273,6 @@ void cpu_loop(CPUARMState *env)
                 /* FIXME - what to do if get_user() fails? */
                 get_user_code_u32(opcode, env->regs[15], env);
 
-                /*
-                 * The Linux kernel treats some UDF patterns specially
-                 * to use as breakpoints (instead of the architectural
-                 * bkpt insn). These should trigger a SIGTRAP rather
-                 * than SIGILL.
-                 */
-                if (insn_is_linux_bkpt(opcode, env->thumb)) {
-                    goto excp_debug;
-                }
-
                 if (!env->thumb && emulate_arm_fpa11(env, opcode)) {
                     break;
                 }
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index ec21e33a06..0447be0907 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -4508,6 +4508,23 @@ static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
     return true;
 }
 
+static bool trans_LINUX_BKPT(DisasContext *s, arg_LINUX_BKPT *a)
+{
+#ifdef CONFIG_USER_ONLY
+# ifdef CONFIG_LINUX
+    /*
+     * The Linux kernel recognizes 3 UDF patterns as breakpoints.
+     * Recognizing these during translate is much less error prone
+     * than deferring to cpu_loop.
+     */
+    gen_exception_bkpt_insn(s, 0);
+    return true;
+# endif
+#endif
+    /* Fall through to UDF. */
+    return false;
+}
+
 static bool trans_UDF(DisasContext *s, arg_UDF *a)
 {
     unallocated_encoding(s);
diff --git a/target/arm/tcg/a32.decode b/target/arm/tcg/a32.decode
index f2ca480949..c7e8e9803e 100644
--- a/target/arm/tcg/a32.decode
+++ b/target/arm/tcg/a32.decode
@@ -425,7 +425,10 @@ BFCI             ---- 0111 110 msb:5 rd:4 lsb:5 001 rn:4      &bfi
 
 # While we could get UDEF by not including this, add the pattern for
 # documentation and to conflict with any other typos in this file.
-UDF              1110 0111 1111 ---- ---- ---- 1111 ----
+{
+  LINUX_BKPT     1110 0111 1111 0000 0000 0001 1111 0000
+  UDF            1110 0111 1111 ---- ---- ---- 1111 ----
+}
 
 # Parallel addition and subtraction
 
diff --git a/target/arm/tcg/t16.decode b/target/arm/tcg/t16.decode
index 778fbf1627..836e929684 100644
--- a/target/arm/tcg/t16.decode
+++ b/target/arm/tcg/t16.decode
@@ -263,6 +263,7 @@ LDM_t16         1011 110 ......... \
 %imm8_0x2       0:s8 !function=times_2
 
 {
+  LINUX_BKPT    1101 1110 0000 0001
   UDF           1101 1110 ---- ----
   SVC           1101 1111 imm:8                 &i
   B_cond_thumb  1101 cond:4 ........            &ci imm=%imm8_0x2
diff --git a/target/arm/tcg/t32.decode b/target/arm/tcg/t32.decode
index 49b8d0037e..05217da8b3 100644
--- a/target/arm/tcg/t32.decode
+++ b/target/arm/tcg/t32.decode
@@ -418,7 +418,10 @@ CLZ              1111 1010 1011 ---- 1111 .... 1000 ....      @rdm
     SMC          1111 0111 1111 imm:4 1000 0000 0000 0000     &i
     HVC          1111 0111 1110 ....  1000 .... .... ....     \
                  &i imm=%imm16_16_0
-    UDF          1111 0111 1111 ----  1010 ---- ---- ----
+    {
+      LINUX_BKPT 1111 0111 1111 0000  1010 0000 0000 0000
+      UDF        1111 0111 1111 ----  1010 ---- ---- ----
+    }
   ]
   B_cond_thumb   1111 0. cond:4 ...... 10.0 ............      &ci imm=%imm21
 }
-- 
2.43.0