xref: /openbmc/qemu/accel/tcg/atomic_common.c.inc (revision 4921d0a7)
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/*
23 * Atomic helpers callable from TCG.
24 * These have a common interface and all defer to cpu_atomic_*
25 * using the host return address from GETPC().
26 */
27
28#define CMPXCHG_HELPER(OP, TYPE) \
29    TYPE HELPER(atomic_##OP)(CPUArchState *env, uint64_t addr,      \
30                             TYPE oldv, TYPE newv, uint32_t oi)     \
31    { return cpu_atomic_##OP##_mmu(env, addr, oldv, newv, oi, GETPC()); }
32
33CMPXCHG_HELPER(cmpxchgb, uint32_t)
34CMPXCHG_HELPER(cmpxchgw_be, uint32_t)
35CMPXCHG_HELPER(cmpxchgw_le, uint32_t)
36CMPXCHG_HELPER(cmpxchgl_be, uint32_t)
37CMPXCHG_HELPER(cmpxchgl_le, uint32_t)
38
39#ifdef CONFIG_ATOMIC64
40CMPXCHG_HELPER(cmpxchgq_be, uint64_t)
41CMPXCHG_HELPER(cmpxchgq_le, uint64_t)
42#endif
43
44#if HAVE_CMPXCHG128
45CMPXCHG_HELPER(cmpxchgo_be, Int128)
46CMPXCHG_HELPER(cmpxchgo_le, Int128)
47#endif
48
49#undef CMPXCHG_HELPER
50
51Int128 HELPER(nonatomic_cmpxchgo)(CPUArchState *env, uint64_t addr,
52                                  Int128 cmpv, Int128 newv, uint32_t oi)
53{
54#if TCG_TARGET_REG_BITS == 32
55    uintptr_t ra = GETPC();
56    Int128 oldv;
57
58    oldv = cpu_ld16_mmu(env, addr, oi, ra);
59    if (int128_eq(oldv, cmpv)) {
60        cpu_st16_mmu(env, addr, newv, oi, ra);
61    } else {
62        /* Even with comparison failure, still need a write cycle. */
63        probe_write(env, addr, 16, get_mmuidx(oi), ra);
64    }
65    return oldv;
66#else
67    g_assert_not_reached();
68#endif
69}
70
71#define ATOMIC_HELPER(OP, TYPE) \
72    TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, uint64_t addr,  \
73                                  TYPE val, uint32_t oi)                 \
74    { return glue(glue(cpu_atomic_,OP),_mmu)(env, addr, val, oi, GETPC()); }
75
76#ifdef CONFIG_ATOMIC64
77#define GEN_ATOMIC_HELPERS(OP)              \
78    ATOMIC_HELPER(glue(OP,b), uint32_t)     \
79    ATOMIC_HELPER(glue(OP,w_be), uint32_t)  \
80    ATOMIC_HELPER(glue(OP,w_le), uint32_t)  \
81    ATOMIC_HELPER(glue(OP,l_be), uint32_t)  \
82    ATOMIC_HELPER(glue(OP,l_le), uint32_t)  \
83    ATOMIC_HELPER(glue(OP,q_be), uint64_t)  \
84    ATOMIC_HELPER(glue(OP,q_le), uint64_t)
85#else
86#define GEN_ATOMIC_HELPERS(OP)              \
87    ATOMIC_HELPER(glue(OP,b), uint32_t)     \
88    ATOMIC_HELPER(glue(OP,w_be), uint32_t)  \
89    ATOMIC_HELPER(glue(OP,w_le), uint32_t)  \
90    ATOMIC_HELPER(glue(OP,l_be), uint32_t)  \
91    ATOMIC_HELPER(glue(OP,l_le), uint32_t)
92#endif
93
94GEN_ATOMIC_HELPERS(fetch_add)
95GEN_ATOMIC_HELPERS(fetch_and)
96GEN_ATOMIC_HELPERS(fetch_or)
97GEN_ATOMIC_HELPERS(fetch_xor)
98GEN_ATOMIC_HELPERS(fetch_smin)
99GEN_ATOMIC_HELPERS(fetch_umin)
100GEN_ATOMIC_HELPERS(fetch_smax)
101GEN_ATOMIC_HELPERS(fetch_umax)
102
103GEN_ATOMIC_HELPERS(add_fetch)
104GEN_ATOMIC_HELPERS(and_fetch)
105GEN_ATOMIC_HELPERS(or_fetch)
106GEN_ATOMIC_HELPERS(xor_fetch)
107GEN_ATOMIC_HELPERS(smin_fetch)
108GEN_ATOMIC_HELPERS(umin_fetch)
109GEN_ATOMIC_HELPERS(smax_fetch)
110GEN_ATOMIC_HELPERS(umax_fetch)
111
112GEN_ATOMIC_HELPERS(xchg)
113
114#undef ATOMIC_HELPER
115#undef GEN_ATOMIC_HELPERS
116