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 MemOpIdx oi) 18{ 19 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW); 20} 21 22#if HAVE_ATOMIC128 23static void atomic_trace_ld_post(CPUArchState *env, uint64_t addr, 24 MemOpIdx oi) 25{ 26 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R); 27} 28 29static void atomic_trace_st_post(CPUArchState *env, uint64_t addr, 30 MemOpIdx oi) 31{ 32 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W); 33} 34#endif 35 36/* 37 * Atomic helpers callable from TCG. 38 * These have a common interface and all defer to cpu_atomic_* 39 * using the host return address from GETPC(). 40 */ 41 42#define CMPXCHG_HELPER(OP, TYPE) \ 43 TYPE HELPER(atomic_##OP)(CPUArchState *env, uint64_t addr, \ 44 TYPE oldv, TYPE newv, uint32_t oi) \ 45 { return cpu_atomic_##OP##_mmu(env, addr, oldv, newv, oi, GETPC()); } 46 47CMPXCHG_HELPER(cmpxchgb, uint32_t) 48CMPXCHG_HELPER(cmpxchgw_be, uint32_t) 49CMPXCHG_HELPER(cmpxchgw_le, uint32_t) 50CMPXCHG_HELPER(cmpxchgl_be, uint32_t) 51CMPXCHG_HELPER(cmpxchgl_le, uint32_t) 52 53#ifdef CONFIG_ATOMIC64 54CMPXCHG_HELPER(cmpxchgq_be, uint64_t) 55CMPXCHG_HELPER(cmpxchgq_le, uint64_t) 56#endif 57 58#ifdef CONFIG_CMPXCHG128 59CMPXCHG_HELPER(cmpxchgo_be, Int128) 60CMPXCHG_HELPER(cmpxchgo_le, Int128) 61#endif 62 63#undef CMPXCHG_HELPER 64 65Int128 HELPER(nonatomic_cmpxchgo_be)(CPUArchState *env, uint64_t addr, 66 Int128 cmpv, Int128 newv, uint32_t oi) 67{ 68#if TCG_TARGET_REG_BITS == 32 69 uintptr_t ra = GETPC(); 70 Int128 oldv; 71 72 oldv = cpu_ld16_be_mmu(env, addr, oi, ra); 73 if (int128_eq(oldv, cmpv)) { 74 cpu_st16_be_mmu(env, addr, newv, oi, ra); 75 } else { 76 /* Even with comparison failure, still need a write cycle. */ 77 probe_write(env, addr, 16, get_mmuidx(oi), ra); 78 } 79 return oldv; 80#else 81 g_assert_not_reached(); 82#endif 83} 84 85Int128 HELPER(nonatomic_cmpxchgo_le)(CPUArchState *env, uint64_t addr, 86 Int128 cmpv, Int128 newv, uint32_t oi) 87{ 88#if TCG_TARGET_REG_BITS == 32 89 uintptr_t ra = GETPC(); 90 Int128 oldv; 91 92 oldv = cpu_ld16_le_mmu(env, addr, oi, ra); 93 if (int128_eq(oldv, cmpv)) { 94 cpu_st16_le_mmu(env, addr, newv, oi, ra); 95 } else { 96 /* Even with comparison failure, still need a write cycle. */ 97 probe_write(env, addr, 16, get_mmuidx(oi), ra); 98 } 99 return oldv; 100#else 101 g_assert_not_reached(); 102#endif 103} 104 105#define ATOMIC_HELPER(OP, TYPE) \ 106 TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, uint64_t addr, \ 107 TYPE val, uint32_t oi) \ 108 { return glue(glue(cpu_atomic_,OP),_mmu)(env, addr, val, oi, GETPC()); } 109 110#ifdef CONFIG_ATOMIC64 111#define GEN_ATOMIC_HELPERS(OP) \ 112 ATOMIC_HELPER(glue(OP,b), uint32_t) \ 113 ATOMIC_HELPER(glue(OP,w_be), uint32_t) \ 114 ATOMIC_HELPER(glue(OP,w_le), uint32_t) \ 115 ATOMIC_HELPER(glue(OP,l_be), uint32_t) \ 116 ATOMIC_HELPER(glue(OP,l_le), uint32_t) \ 117 ATOMIC_HELPER(glue(OP,q_be), uint64_t) \ 118 ATOMIC_HELPER(glue(OP,q_le), uint64_t) 119#else 120#define GEN_ATOMIC_HELPERS(OP) \ 121 ATOMIC_HELPER(glue(OP,b), uint32_t) \ 122 ATOMIC_HELPER(glue(OP,w_be), uint32_t) \ 123 ATOMIC_HELPER(glue(OP,w_le), uint32_t) \ 124 ATOMIC_HELPER(glue(OP,l_be), uint32_t) \ 125 ATOMIC_HELPER(glue(OP,l_le), uint32_t) 126#endif 127 128GEN_ATOMIC_HELPERS(fetch_add) 129GEN_ATOMIC_HELPERS(fetch_and) 130GEN_ATOMIC_HELPERS(fetch_or) 131GEN_ATOMIC_HELPERS(fetch_xor) 132GEN_ATOMIC_HELPERS(fetch_smin) 133GEN_ATOMIC_HELPERS(fetch_umin) 134GEN_ATOMIC_HELPERS(fetch_smax) 135GEN_ATOMIC_HELPERS(fetch_umax) 136 137GEN_ATOMIC_HELPERS(add_fetch) 138GEN_ATOMIC_HELPERS(and_fetch) 139GEN_ATOMIC_HELPERS(or_fetch) 140GEN_ATOMIC_HELPERS(xor_fetch) 141GEN_ATOMIC_HELPERS(smin_fetch) 142GEN_ATOMIC_HELPERS(umin_fetch) 143GEN_ATOMIC_HELPERS(smax_fetch) 144GEN_ATOMIC_HELPERS(umax_fetch) 145 146GEN_ATOMIC_HELPERS(xchg) 147 148#undef ATOMIC_HELPER 149#undef GEN_ATOMIC_HELPERS 150