]>
Commit | Line | Data |
---|---|---|
cfec3885 EC |
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 | ||
f3e182b1 | 16 | static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr, |
c3e83e37 | 17 | MemOpIdx oi) |
cfec3885 | 18 | { |
37aff087 | 19 | qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW); |
cfec3885 EC |
20 | } |
21 | ||
f3e182b1 | 22 | #if HAVE_ATOMIC128 |
f3e182b1 | 23 | static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr, |
c3e83e37 | 24 | MemOpIdx oi) |
cfec3885 | 25 | { |
37aff087 | 26 | qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R); |
cfec3885 EC |
27 | } |
28 | ||
f3e182b1 | 29 | static void atomic_trace_st_post(CPUArchState *env, target_ulong addr, |
c3e83e37 | 30 | MemOpIdx oi) |
cfec3885 | 31 | { |
37aff087 | 32 | qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W); |
cfec3885 | 33 | } |
f3e182b1 | 34 | #endif |
e28a8664 RH |
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, target_ulong addr, \ | |
44 | TYPE oldv, TYPE newv, uint32_t oi) \ | |
45 | { return cpu_atomic_##OP##_mmu(env, addr, oldv, newv, oi, GETPC()); } | |
46 | ||
47 | CMPXCHG_HELPER(cmpxchgb, uint32_t) | |
48 | CMPXCHG_HELPER(cmpxchgw_be, uint32_t) | |
49 | CMPXCHG_HELPER(cmpxchgw_le, uint32_t) | |
50 | CMPXCHG_HELPER(cmpxchgl_be, uint32_t) | |
51 | CMPXCHG_HELPER(cmpxchgl_le, uint32_t) | |
52 | ||
53 | #ifdef CONFIG_ATOMIC64 | |
54 | CMPXCHG_HELPER(cmpxchgq_be, uint64_t) | |
55 | CMPXCHG_HELPER(cmpxchgq_le, uint64_t) | |
56 | #endif | |
57 | ||
123ae568 RH |
58 | #ifdef CONFIG_CMPXCHG128 |
59 | CMPXCHG_HELPER(cmpxchgo_be, Int128) | |
60 | CMPXCHG_HELPER(cmpxchgo_le, Int128) | |
61 | #endif | |
62 | ||
e28a8664 RH |
63 | #undef CMPXCHG_HELPER |
64 | ||
123ae568 RH |
65 | Int128 HELPER(nonatomic_cmpxchgo_be)(CPUArchState *env, target_ulong 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 | ||
85 | Int128 HELPER(nonatomic_cmpxchgo_le)(CPUArchState *env, target_ulong 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 | ||
e28a8664 RH |
105 | #define ATOMIC_HELPER(OP, TYPE) \ |
106 | TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, target_ulong 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 | ||
128 | GEN_ATOMIC_HELPERS(fetch_add) | |
129 | GEN_ATOMIC_HELPERS(fetch_and) | |
130 | GEN_ATOMIC_HELPERS(fetch_or) | |
131 | GEN_ATOMIC_HELPERS(fetch_xor) | |
132 | GEN_ATOMIC_HELPERS(fetch_smin) | |
133 | GEN_ATOMIC_HELPERS(fetch_umin) | |
134 | GEN_ATOMIC_HELPERS(fetch_smax) | |
135 | GEN_ATOMIC_HELPERS(fetch_umax) | |
136 | ||
137 | GEN_ATOMIC_HELPERS(add_fetch) | |
138 | GEN_ATOMIC_HELPERS(and_fetch) | |
139 | GEN_ATOMIC_HELPERS(or_fetch) | |
140 | GEN_ATOMIC_HELPERS(xor_fetch) | |
141 | GEN_ATOMIC_HELPERS(smin_fetch) | |
142 | GEN_ATOMIC_HELPERS(umin_fetch) | |
143 | GEN_ATOMIC_HELPERS(smax_fetch) | |
144 | GEN_ATOMIC_HELPERS(umax_fetch) | |
145 | ||
146 | GEN_ATOMIC_HELPERS(xchg) | |
147 | ||
148 | #undef ATOMIC_HELPER | |
149 | #undef GEN_ATOMIC_HELPERS |