| 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 | |
| 16 | static 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 | |
| 44 | CMPXCHG_HELPER(cmpxchgb, uint32_t) |
| 45 | CMPXCHG_HELPER(cmpxchgw_be, uint32_t) |
| 46 | CMPXCHG_HELPER(cmpxchgw_le, uint32_t) |
| 47 | CMPXCHG_HELPER(cmpxchgl_be, uint32_t) |
| 48 | CMPXCHG_HELPER(cmpxchgl_le, uint32_t) |
| 49 | CMPXCHG_HELPER(cmpxchgq_be, uint64_t) |
| 50 | CMPXCHG_HELPER(cmpxchgq_le, uint64_t) |
| 51 | |
| 52 | #if HAVE_CMPXCHG128 |
| 53 | CMPXCHG_HELPER(cmpxchgo_be, Int128) |
| 54 | CMPXCHG_HELPER(cmpxchgo_le, Int128) |
| 55 | #endif |
| 56 | |
| 57 | #undef CMPXCHG_HELPER |
| 58 | |
| 59 | #define ATOMIC_HELPER(OP, TYPE) \ |
| 60 | TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, uint64_t addr, \ |
| 61 | TYPE val, uint32_t oi) \ |
| 62 | { return glue(glue(cpu_atomic_,OP),_mmu)(env, addr, val, oi, GETPC()); } |
| 63 | |
| 64 | #define GEN_ATOMIC_HELPERS(OP) \ |
| 65 | ATOMIC_HELPER(glue(OP,b), uint32_t) \ |
| 66 | ATOMIC_HELPER(glue(OP,w_be), uint32_t) \ |
| 67 | ATOMIC_HELPER(glue(OP,w_le), uint32_t) \ |
| 68 | ATOMIC_HELPER(glue(OP,l_be), uint32_t) \ |
| 69 | ATOMIC_HELPER(glue(OP,l_le), uint32_t) \ |
| 70 | ATOMIC_HELPER(glue(OP,q_be), uint64_t) \ |
| 71 | ATOMIC_HELPER(glue(OP,q_le), uint64_t) |
| 72 | |
| 73 | GEN_ATOMIC_HELPERS(fetch_add) |
| 74 | GEN_ATOMIC_HELPERS(fetch_and) |
| 75 | GEN_ATOMIC_HELPERS(fetch_or) |
| 76 | GEN_ATOMIC_HELPERS(fetch_xor) |
| 77 | GEN_ATOMIC_HELPERS(fetch_smin) |
| 78 | GEN_ATOMIC_HELPERS(fetch_umin) |
| 79 | GEN_ATOMIC_HELPERS(fetch_smax) |
| 80 | GEN_ATOMIC_HELPERS(fetch_umax) |
| 81 | |
| 82 | GEN_ATOMIC_HELPERS(add_fetch) |
| 83 | GEN_ATOMIC_HELPERS(and_fetch) |
| 84 | GEN_ATOMIC_HELPERS(or_fetch) |
| 85 | GEN_ATOMIC_HELPERS(xor_fetch) |
| 86 | GEN_ATOMIC_HELPERS(smin_fetch) |
| 87 | GEN_ATOMIC_HELPERS(umin_fetch) |
| 88 | GEN_ATOMIC_HELPERS(smax_fetch) |
| 89 | GEN_ATOMIC_HELPERS(umax_fetch) |
| 90 | |
| 91 | GEN_ATOMIC_HELPERS(xchg) |
| 92 | |
| 93 | #if HAVE_CMPXCHG128 |
| 94 | ATOMIC_HELPER(xchgo_be, Int128) |
| 95 | ATOMIC_HELPER(xchgo_le, Int128) |
| 96 | ATOMIC_HELPER(fetch_ando_be, Int128) |
| 97 | ATOMIC_HELPER(fetch_ando_le, Int128) |
| 98 | ATOMIC_HELPER(fetch_oro_be, Int128) |
| 99 | ATOMIC_HELPER(fetch_oro_le, Int128) |
| 100 | #endif |
| 101 | |
| 102 | #undef ATOMIC_HELPER |
| 103 | #undef GEN_ATOMIC_HELPERS |