diff mbox

[RFC] disable execution of SWP/SWPB

Message ID CABtrw+ORds75FyUH+E0k2dqQuDfFXvhi8Fobmf=V+Qa_Xo0WtQ@mail.gmail.com
State New
Headers show

Commit Message

Alexey Starikovskiy April 17, 2012, 9:53 a.m. UTC
Hi,

I was wondering how to implement disabling of SWP/SWPB execution if
they are not enabled in SCTLR.SW bit.
One way to do this is to intercept writes to SCTLR, do tb_flush and
make SWP [un]defined for any following translations depending on the
c1_sys state
during the translation.
The other way would be to dynamically define/undefine these
instructions without tb_flush. In this particular case of deprecated
instruction which would be enabled once per OS boot, tb_flush will not
make any performance impact, but there may be other instructions,
which would benefit from the second approach...

Please comment,
Alex.

Comments

Peter Maydell April 17, 2012, 10:19 a.m. UTC | #1
On 17 April 2012 10:53, Alexey Starikovskiy <aystarik@gmail.com> wrote:
> I was wondering how to implement disabling of SWP/SWPB execution if
> they are not enabled in SCTLR.SW bit.
> One way to do this is to intercept writes to SCTLR, do tb_flush and
> make SWP [un]defined for any following translations depending on the
> c1_sys state during the translation.

This is the right way to do this. The standard use case is that this
SCTLR bit will never be touched by anybody and will retain its reset
value. The less common case is that the OS will set it once on startup.
Changing the value more often than that is basically vanishingly
unlikely, and so trying to dynamically emit code that looks at the
SCTLR is needless complication and slows down the case where you
actually are using SWP.

-- PMM
diff mbox

Patch

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 7a3c7d6..a54b436 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7415,7 +7415,12 @@  static void disas_arm_insn(CPUARMState * env, DisasContex
                         }
                         tcg_temp_free(addr);
                     } else {
-                        /* SWP instruction */
+                        /* SWP/SWPB instruction */
+                        TCGv sctlr = load_cpu_field(cp15.c1_sys);
+                        int fail_label = gen_new_label();
+                        int done_label = gen_new_label();
+                        tcg_gen_andi_i32(sctlr, sctlr, 1 << 10); /* Check if SW
+                        tcg_gen_brcondi_i32(TCG_COND_EQ, sctlr, 0, fail_label);
                         rm = (insn) & 0xf;

                         /* ??? This is not really atomic.  However we know
@@ -7432,6 +7437,11 @@  static void disas_arm_insn(CPUARMState * env, DisasContex
                         }
                         tcg_temp_free_i32(addr);
                         store_reg(s, rd, tmp2);
+                        tcg_gen_br(done_label);
+                        gen_set_label(fail_label);
+                        gen_exception(EXCP_UDEF);
+                        gen_set_label(done_label);
+                        tcg_temp_free_i32(sctlr);
                     }
                 }
             } else {