TODO: convert paired atomics as well. Signed-off-by: Emilio G. Cota <c...@braap.org> --- cpu-exec.c | 4 ++++ target-arm/helper-a64.c | 31 +++++++++++++++++++++++++++++++ target-arm/helper-a64.h | 4 ++++ target-arm/op_helper.c | 4 ++++ target-arm/translate-a64.c | 16 ++++++++++------ 5 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c index 8f1adc4..6e2531f 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -26,6 +26,7 @@ #include "sysemu/qtest.h" #include "qemu/timer.h" #include "exec/address-spaces.h" +#include "qemu/htm.h" #include "qemu/rcu.h" #include "exec/tb-hash.h" #include "exec/log.h" @@ -651,6 +652,9 @@ int cpu_exec(CPUState *cpu) cpu->can_do_io = 1; stop_the_world_reset(); tb_lock_reset(); + if (unlikely(htm_test())) { + htm_end(); + } } } /* for(;;) */ diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index 6f3fd17..741e6de 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -25,6 +25,7 @@ #include "qemu/log.h" #include "sysemu/sysemu.h" #include "qemu/bitops.h" +#include "qemu/htm.h" #include "internals.h" #include "qemu/crc32c.h" #include "exec/exec-all.h" @@ -579,3 +580,33 @@ uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr, return !success; } + +void HELPER(xbegin)(CPUARMState *env) +{ + int status; + int retries = 100; + + retry: + status = htm_begin(); + if (unlikely(status != HTM_OK)) { + if ((status & HTM_ABORT_RETRY) && retries) { + retries--; + goto retry; + } + stop_the_world_lock(ENV_GET_CPU(env)); + } +} + +void HELPER(xend)(void) +{ + if (likely(htm_test())) { + htm_end(); + } else { + stop_the_world_unlock(); + } +} + +uint64_t HELPER(x_ok)(void) +{ + return likely(htm_test()) || stw_held; +} diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h index dd32000..e7ede43 100644 --- a/target-arm/helper-a64.h +++ b/target-arm/helper-a64.h @@ -48,3 +48,7 @@ DEF_HELPER_FLAGS_3(crc32_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32) DEF_HELPER_FLAGS_3(crc32c_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32) DEF_HELPER_FLAGS_4(paired_cmpxchg64_le, TCG_CALL_NO_WG, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(paired_cmpxchg64_be, TCG_CALL_NO_WG, i64, env, i64, i64, i64) + +DEF_HELPER_1(xbegin, void, env) +DEF_HELPER_0(x_ok, i64) +DEF_HELPER_0(xend, void) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 73da759..91b1413 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" +#include "qemu/htm.h" #include "cpu.h" #include "exec/helper-proto.h" #include "internals.h" @@ -31,6 +32,9 @@ static void raise_exception(CPUARMState *env, uint32_t excp, { CPUState *cs = CPU(arm_env_get_cpu(env)); + if (unlikely(htm_test())) { + htm_end(); + } assert(!excp_is_internal(excp)); cs->exception_index = excp; env->exception.syndrome = syndrome; diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 450c359..cc3baa0 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -1760,6 +1760,8 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, TCGv_i64 tmp = tcg_temp_new_i64(); TCGMemOp be = s->be_data; + gen_helper_xbegin(cpu_env); + g_assert(size <= 3); if (is_pair) { TCGv_i64 hitmp = tcg_temp_new_i64(); @@ -1825,6 +1827,10 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label); tmp = tcg_temp_new_i64(); + /* strex without a prior ldrex should just fail */ + gen_helper_x_ok(tmp); + tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, fail_label); + if (is_pair) { if (size == 2) { TCGv_i64 val = tcg_temp_new_i64(); @@ -1844,16 +1850,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, } } else { TCGv_i64 val = cpu_reg(s, rt); - tcg_gen_atomic_cmpxchg_i64(tmp, addr, cpu_exclusive_val, val, - get_mem_index(s), - size | MO_ALIGN | s->be_data); - tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val); + tcg_gen_qemu_st_i64(val, addr, get_mem_index(s), s->be_data + size); } tcg_temp_free_i64(addr); - - tcg_gen_mov_i64(cpu_reg(s, rd), tmp); tcg_temp_free_i64(tmp); + + tcg_gen_movi_i64(cpu_reg(s, rd), 0); + gen_helper_xend(); tcg_gen_br(done_label); gen_set_label(fail_label); -- 2.5.0