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 uint16_t atomic_trace_rmw_pre(CPUArchState *env, target_ulong addr, 17 TCGMemOpIdx oi) 18{ 19 CPUState *cpu = env_cpu(env); 20 uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false); 21 22 trace_guest_mem_before_exec(cpu, addr, info); 23 trace_guest_mem_before_exec(cpu, addr, info | TRACE_MEM_ST); 24 25 return info; 26} 27 28static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr, 29 uint16_t info) 30{ 31 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info); 32 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info | TRACE_MEM_ST); 33} 34 35#if HAVE_ATOMIC128 36static uint16_t atomic_trace_ld_pre(CPUArchState *env, target_ulong addr, 37 TCGMemOpIdx oi) 38{ 39 uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false); 40 41 trace_guest_mem_before_exec(env_cpu(env), addr, info); 42 43 return info; 44} 45 46static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr, 47 uint16_t info) 48{ 49 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info); 50} 51 52static uint16_t atomic_trace_st_pre(CPUArchState *env, target_ulong addr, 53 TCGMemOpIdx oi) 54{ 55 uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), true); 56 57 trace_guest_mem_before_exec(env_cpu(env), addr, info); 58 59 return info; 60} 61 62static void atomic_trace_st_post(CPUArchState *env, target_ulong addr, 63 uint16_t info) 64{ 65 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info); 66} 67#endif 68 69/* 70 * Atomic helpers callable from TCG. 71 * These have a common interface and all defer to cpu_atomic_* 72 * using the host return address from GETPC(). 73 */ 74 75#define CMPXCHG_HELPER(OP, TYPE) \ 76 TYPE HELPER(atomic_##OP)(CPUArchState *env, target_ulong addr, \ 77 TYPE oldv, TYPE newv, uint32_t oi) \ 78 { return cpu_atomic_##OP##_mmu(env, addr, oldv, newv, oi, GETPC()); } 79 80CMPXCHG_HELPER(cmpxchgb, uint32_t) 81CMPXCHG_HELPER(cmpxchgw_be, uint32_t) 82CMPXCHG_HELPER(cmpxchgw_le, uint32_t) 83CMPXCHG_HELPER(cmpxchgl_be, uint32_t) 84CMPXCHG_HELPER(cmpxchgl_le, uint32_t) 85 86#ifdef CONFIG_ATOMIC64 87CMPXCHG_HELPER(cmpxchgq_be, uint64_t) 88CMPXCHG_HELPER(cmpxchgq_le, uint64_t) 89#endif 90 91#undef CMPXCHG_HELPER 92 93#define ATOMIC_HELPER(OP, TYPE) \ 94 TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, target_ulong addr, \ 95 TYPE val, uint32_t oi) \ 96 { return glue(glue(cpu_atomic_,OP),_mmu)(env, addr, val, oi, GETPC()); } 97 98#ifdef CONFIG_ATOMIC64 99#define GEN_ATOMIC_HELPERS(OP) \ 100 ATOMIC_HELPER(glue(OP,b), uint32_t) \ 101 ATOMIC_HELPER(glue(OP,w_be), uint32_t) \ 102 ATOMIC_HELPER(glue(OP,w_le), uint32_t) \ 103 ATOMIC_HELPER(glue(OP,l_be), uint32_t) \ 104 ATOMIC_HELPER(glue(OP,l_le), uint32_t) \ 105 ATOMIC_HELPER(glue(OP,q_be), uint64_t) \ 106 ATOMIC_HELPER(glue(OP,q_le), uint64_t) 107#else 108#define GEN_ATOMIC_HELPERS(OP) \ 109 ATOMIC_HELPER(glue(OP,b), uint32_t) \ 110 ATOMIC_HELPER(glue(OP,w_be), uint32_t) \ 111 ATOMIC_HELPER(glue(OP,w_le), uint32_t) \ 112 ATOMIC_HELPER(glue(OP,l_be), uint32_t) \ 113 ATOMIC_HELPER(glue(OP,l_le), uint32_t) 114#endif 115 116GEN_ATOMIC_HELPERS(fetch_add) 117GEN_ATOMIC_HELPERS(fetch_and) 118GEN_ATOMIC_HELPERS(fetch_or) 119GEN_ATOMIC_HELPERS(fetch_xor) 120GEN_ATOMIC_HELPERS(fetch_smin) 121GEN_ATOMIC_HELPERS(fetch_umin) 122GEN_ATOMIC_HELPERS(fetch_smax) 123GEN_ATOMIC_HELPERS(fetch_umax) 124 125GEN_ATOMIC_HELPERS(add_fetch) 126GEN_ATOMIC_HELPERS(and_fetch) 127GEN_ATOMIC_HELPERS(or_fetch) 128GEN_ATOMIC_HELPERS(xor_fetch) 129GEN_ATOMIC_HELPERS(smin_fetch) 130GEN_ATOMIC_HELPERS(umin_fetch) 131GEN_ATOMIC_HELPERS(smax_fetch) 132GEN_ATOMIC_HELPERS(umax_fetch) 133 134GEN_ATOMIC_HELPERS(xchg) 135 136#undef ATOMIC_HELPER 137#undef GEN_ATOMIC_HELPERS 138