1/* 2 * Common Atomic Helper Functions 3 * 4 * This file should be included before the various instantiations of 5 * the atomic_template.h helpers. 6 * 7 * Copyright (c) 2019 Linaro 8 * Written by Alex Bennée <alex.bennee@linaro.org> 9 * 10 * SPDX-License-Identifier: GPL-2.0-or-later 11 * 12 * This work is licensed under the terms of the GNU GPL, version 2 or later. 13 * See the COPYING file in the top-level directory. 14 */ 15 16static void atomic_trace_rmw_post(CPUArchState *env, uint64_t addr, 17 uint64_t read_value_low, 18 uint64_t read_value_high, 19 uint64_t write_value_low, 20 uint64_t write_value_high, 21 MemOpIdx oi) 22{ 23 if (cpu_plugin_mem_cbs_enabled(env_cpu(env))) { 24 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, 25 read_value_low, read_value_high, 26 oi, QEMU_PLUGIN_MEM_R); 27 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, 28 write_value_low, write_value_high, 29 oi, QEMU_PLUGIN_MEM_W); 30 } 31} 32 33/* 34 * Atomic helpers callable from TCG. 35 * These have a common interface and all defer to cpu_atomic_* 36 * using the host return address from GETPC(). 37 */ 38 39#define CMPXCHG_HELPER(OP, TYPE) \ 40 TYPE HELPER(atomic_##OP)(CPUArchState *env, uint64_t addr, \ 41 TYPE oldv, TYPE newv, uint32_t oi) \ 42 { return cpu_atomic_##OP##_mmu(env, addr, oldv, newv, oi, GETPC()); } 43 44CMPXCHG_HELPER(cmpxchgb, uint32_t) 45CMPXCHG_HELPER(cmpxchgw_be, uint32_t) 46CMPXCHG_HELPER(cmpxchgw_le, uint32_t) 47CMPXCHG_HELPER(cmpxchgl_be, uint32_t) 48CMPXCHG_HELPER(cmpxchgl_le, uint32_t) 49 50#ifdef CONFIG_ATOMIC64 51CMPXCHG_HELPER(cmpxchgq_be, uint64_t) 52CMPXCHG_HELPER(cmpxchgq_le, uint64_t) 53#endif 54 55#if HAVE_CMPXCHG128 56CMPXCHG_HELPER(cmpxchgo_be, Int128) 57CMPXCHG_HELPER(cmpxchgo_le, Int128) 58#endif 59 60#undef CMPXCHG_HELPER 61 62Int128 HELPER(nonatomic_cmpxchgo)(CPUArchState *env, uint64_t addr, 63 Int128 cmpv, Int128 newv, uint32_t oi) 64{ 65#if TCG_TARGET_REG_BITS == 32 66 uintptr_t ra = GETPC(); 67 Int128 oldv; 68 69 oldv = cpu_ld16_mmu(env, addr, oi, ra); 70 if (int128_eq(oldv, cmpv)) { 71 cpu_st16_mmu(env, addr, newv, oi, ra); 72 } else { 73 /* Even with comparison failure, still need a write cycle. */ 74 probe_write(env, addr, 16, get_mmuidx(oi), ra); 75 } 76 return oldv; 77#else 78 g_assert_not_reached(); 79#endif 80} 81 82#define ATOMIC_HELPER(OP, TYPE) \ 83 TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, uint64_t addr, \ 84 TYPE val, uint32_t oi) \ 85 { return glue(glue(cpu_atomic_,OP),_mmu)(env, addr, val, oi, GETPC()); } 86 87#ifdef CONFIG_ATOMIC64 88#define GEN_ATOMIC_HELPERS(OP) \ 89 ATOMIC_HELPER(glue(OP,b), uint32_t) \ 90 ATOMIC_HELPER(glue(OP,w_be), uint32_t) \ 91 ATOMIC_HELPER(glue(OP,w_le), uint32_t) \ 92 ATOMIC_HELPER(glue(OP,l_be), uint32_t) \ 93 ATOMIC_HELPER(glue(OP,l_le), uint32_t) \ 94 ATOMIC_HELPER(glue(OP,q_be), uint64_t) \ 95 ATOMIC_HELPER(glue(OP,q_le), uint64_t) 96#else 97#define GEN_ATOMIC_HELPERS(OP) \ 98 ATOMIC_HELPER(glue(OP,b), uint32_t) \ 99 ATOMIC_HELPER(glue(OP,w_be), uint32_t) \ 100 ATOMIC_HELPER(glue(OP,w_le), uint32_t) \ 101 ATOMIC_HELPER(glue(OP,l_be), uint32_t) \ 102 ATOMIC_HELPER(glue(OP,l_le), uint32_t) 103#endif 104 105GEN_ATOMIC_HELPERS(fetch_add) 106GEN_ATOMIC_HELPERS(fetch_and) 107GEN_ATOMIC_HELPERS(fetch_or) 108GEN_ATOMIC_HELPERS(fetch_xor) 109GEN_ATOMIC_HELPERS(fetch_smin) 110GEN_ATOMIC_HELPERS(fetch_umin) 111GEN_ATOMIC_HELPERS(fetch_smax) 112GEN_ATOMIC_HELPERS(fetch_umax) 113 114GEN_ATOMIC_HELPERS(add_fetch) 115GEN_ATOMIC_HELPERS(and_fetch) 116GEN_ATOMIC_HELPERS(or_fetch) 117GEN_ATOMIC_HELPERS(xor_fetch) 118GEN_ATOMIC_HELPERS(smin_fetch) 119GEN_ATOMIC_HELPERS(umin_fetch) 120GEN_ATOMIC_HELPERS(smax_fetch) 121GEN_ATOMIC_HELPERS(umax_fetch) 122 123GEN_ATOMIC_HELPERS(xchg) 124 125#undef ATOMIC_HELPER 126#undef GEN_ATOMIC_HELPERS 127