1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
3 #include "rseq-bits-template.h"
5 #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
6 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
8 static inline __always_inline
9 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev
)(intptr_t *v
, intptr_t expect
, intptr_t newv
, int cpu
)
13 __asm__ __volatile__
goto(RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
14 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[cmpfail]")
15 #ifdef RSEQ_COMPARE_TWICE
16 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error1]")
17 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error2]")
19 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
20 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
22 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[cmpfail]")
24 #ifdef RSEQ_COMPARE_TWICE
25 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, "%l[error1]")
26 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[error2]")
28 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
30 RSEQ_ASM_DEFINE_ABORT(4, abort
)
31 : /* gcc asm goto does not allow outputs */
33 [current_cpu_id
] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
34 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
36 [expect
] "r" (expect
),
39 : "memory", RSEQ_ASM_TMP_REG_1
42 #ifdef RSEQ_COMPARE_TWICE
53 #ifdef RSEQ_COMPARE_TWICE
55 rseq_bug("cpu_id comparison failed");
57 rseq_bug("expected value comparison failed");
61 static inline __always_inline
62 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load
)(intptr_t *v
, intptr_t expectnot
,
63 off_t voffp
, intptr_t *load
, int cpu
)
67 __asm__ __volatile__
goto(RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
68 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[cmpfail]")
69 #ifdef RSEQ_COMPARE_TWICE
70 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error1]")
71 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error2]")
73 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
74 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
76 RSEQ_ASM_OP_CMPNE(v
, expectnot
, "%l[cmpfail]")
78 #ifdef RSEQ_COMPARE_TWICE
79 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, "%l[error1]")
80 RSEQ_ASM_OP_CMPNE(v
, expectnot
, "%l[error2]")
83 RSEQ_ASM_OP_R_STORE(load
)
84 RSEQ_ASM_OP_R_LOAD_OFF(voffp
)
85 RSEQ_ASM_OP_R_FINAL_STORE(v
, 3)
87 RSEQ_ASM_DEFINE_ABORT(4, abort
)
88 : /* gcc asm goto does not allow outputs */
90 [current_cpu_id
] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
91 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
93 [expectnot
] "r" (expectnot
),
97 : "memory", RSEQ_ASM_TMP_REG_1
100 #ifdef RSEQ_COMPARE_TWICE
110 #ifdef RSEQ_COMPARE_TWICE
112 rseq_bug("cpu_id comparison failed");
114 rseq_bug("expected value comparison failed");
118 static inline __always_inline
119 int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv
)(intptr_t *v
, intptr_t count
, int cpu
)
123 __asm__ __volatile__
goto(RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
124 #ifdef RSEQ_COMPARE_TWICE
125 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error1]")
127 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
128 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
130 #ifdef RSEQ_COMPARE_TWICE
131 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, "%l[error1]")
133 RSEQ_ASM_OP_R_LOAD(v
)
134 RSEQ_ASM_OP_R_ADD(count
)
135 RSEQ_ASM_OP_R_FINAL_STORE(v
, 3)
137 RSEQ_ASM_DEFINE_ABORT(4, abort
)
138 : /* gcc asm goto does not allow outputs */
139 : [cpu_id
] "r" (cpu
),
140 [current_cpu_id
] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
141 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
145 : "memory", RSEQ_ASM_TMP_REG_1
148 #ifdef RSEQ_COMPARE_TWICE
156 #ifdef RSEQ_COMPARE_TWICE
158 rseq_bug("cpu_id comparison failed");
162 static inline __always_inline
163 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev
)(intptr_t *v
, intptr_t expect
,
164 intptr_t *v2
, intptr_t expect2
,
165 intptr_t newv
, int cpu
)
169 __asm__ __volatile__
goto(RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
170 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[cmpfail]")
171 #ifdef RSEQ_COMPARE_TWICE
172 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error1]")
173 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error2]")
174 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error3]")
176 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
177 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
179 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[cmpfail]")
181 RSEQ_ASM_OP_CMPEQ(v2
, expect2
, "%l[cmpfail]")
183 #ifdef RSEQ_COMPARE_TWICE
184 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, "%l[error1]")
185 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[error2]")
186 RSEQ_ASM_OP_CMPEQ(v2
, expect2
, "%l[error3]")
188 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
190 RSEQ_ASM_DEFINE_ABORT(4, abort
)
191 : /* gcc asm goto does not allow outputs */
192 : [cpu_id
] "r" (cpu
),
193 [current_cpu_id
] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
194 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
196 [expect
] "r" (expect
),
198 [expect2
] "r" (expect2
),
201 : "memory", RSEQ_ASM_TMP_REG_1
204 #ifdef RSEQ_COMPARE_TWICE
205 , error1
, error2
, error3
215 #ifdef RSEQ_COMPARE_TWICE
217 rseq_bug("cpu_id comparison failed");
219 rseq_bug("expected value comparison failed");
221 rseq_bug("2nd expected value comparison failed");
225 #define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
231 static inline __always_inline
232 int RSEQ_TEMPLATE_IDENTIFIER(rseq_offset_deref_addv
)(intptr_t *ptr
, off_t off
, intptr_t inc
, int cpu
)
236 __asm__ __volatile__
goto(RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
237 #ifdef RSEQ_COMPARE_TWICE
238 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error1]")
240 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
241 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
243 #ifdef RSEQ_COMPARE_TWICE
244 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, "%l[error1]")
246 RSEQ_ASM_OP_R_DEREF_ADDV(ptr
, off
, 3)
248 RSEQ_ASM_DEFINE_ABORT(4, abort
)
249 : /* gcc asm goto does not allow outputs */
250 : [cpu_id
] "r" (cpu
),
251 [current_cpu_id
] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
252 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
257 : "memory", RSEQ_ASM_TMP_REG_1
260 #ifdef RSEQ_COMPARE_TWICE
268 #ifdef RSEQ_COMPARE_TWICE
270 rseq_bug("cpu_id comparison failed");
274 #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
275 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
277 #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
278 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
280 static inline __always_inline
281 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev
)(intptr_t *v
, intptr_t expect
,
282 intptr_t *v2
, intptr_t newv2
,
283 intptr_t newv
, int cpu
)
287 __asm__ __volatile__
goto(RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
288 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[cmpfail]")
289 #ifdef RSEQ_COMPARE_TWICE
290 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error1]")
291 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error2]")
293 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
294 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
296 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[cmpfail]")
298 #ifdef RSEQ_COMPARE_TWICE
299 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, "%l[error1]")
300 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[error2]")
302 RSEQ_ASM_OP_STORE(newv2
, v2
)
304 #ifdef RSEQ_TEMPLATE_MO_RELEASE
305 RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv
, v
, 3)
307 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
310 RSEQ_ASM_DEFINE_ABORT(4, abort
)
311 : /* gcc asm goto does not allow outputs */
312 : [cpu_id
] "r" (cpu
),
313 [current_cpu_id
] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
314 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
315 [expect
] "r" (expect
),
321 : "memory", RSEQ_ASM_TMP_REG_1
324 #ifdef RSEQ_COMPARE_TWICE
335 #ifdef RSEQ_COMPARE_TWICE
337 rseq_bug("cpu_id comparison failed");
339 rseq_bug("expected value comparison failed");
343 static inline __always_inline
344 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev
)(intptr_t *v
, intptr_t expect
,
345 void *dst
, void *src
, size_t len
,
346 intptr_t newv
, int cpu
)
349 __asm__ __volatile__
goto(RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
350 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[cmpfail]")
351 #ifdef RSEQ_COMPARE_TWICE
352 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error1]")
353 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, "%l[error2]")
355 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
356 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
358 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[cmpfail]")
360 #ifdef RSEQ_COMPARE_TWICE
361 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, "%l[error1]")
362 RSEQ_ASM_OP_CMPEQ(v
, expect
, "%l[error2]")
364 RSEQ_ASM_OP_R_BAD_MEMCPY(dst
, src
, len
)
366 #ifdef RSEQ_TEMPLATE_MO_RELEASE
367 RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv
, v
, 3)
369 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
372 RSEQ_ASM_DEFINE_ABORT(4, abort
)
373 : /* gcc asm goto does not allow outputs */
374 : [cpu_id
] "r" (cpu
),
375 [current_cpu_id
] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
376 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
377 [expect
] "r" (expect
),
384 : "memory", RSEQ_ASM_TMP_REG_1
, RSEQ_ASM_TMP_REG_2
,
385 RSEQ_ASM_TMP_REG_3
, RSEQ_ASM_TMP_REG_4
388 #ifdef RSEQ_COMPARE_TWICE
399 #ifdef RSEQ_COMPARE_TWICE
401 rseq_bug("cpu_id comparison failed");
403 rseq_bug("expected value comparison failed");
407 #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
408 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
410 #include "rseq-bits-reset.h"