1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
5 * (C) Copyright 2016-2022 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * (C) Copyright 2018 - Will Deacon <will.deacon@arm.com>
9 #include "rseq-bits-template.h"
11 #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
12 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
14 static inline __attribute__((always_inline
))
15 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev
)(intptr_t *v
, intptr_t expect
, intptr_t newv
, int cpu
)
19 __asm__ __volatile__
goto (
20 RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
21 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[cmpfail
])
22 #ifdef RSEQ_COMPARE_TWICE
23 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error1
])
24 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error2
])
26 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
27 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
29 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[cmpfail
])
31 #ifdef RSEQ_COMPARE_TWICE
32 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, %l
[error1
])
33 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[error2
])
35 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
37 RSEQ_ASM_DEFINE_ABORT(4, abort
)
38 : /* gcc asm goto does not allow outputs */
40 [current_cpu_id
] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
41 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
43 [expect
] "r" (expect
),
46 : "memory", RSEQ_ASM_TMP_REG
48 #ifdef RSEQ_COMPARE_TWICE
52 rseq_after_asm_goto();
55 rseq_after_asm_goto();
59 rseq_after_asm_goto();
61 #ifdef RSEQ_COMPARE_TWICE
63 rseq_after_asm_goto();
64 rseq_bug("cpu_id comparison failed");
66 rseq_after_asm_goto();
67 rseq_bug("expected value comparison failed");
71 static inline __attribute__((always_inline
))
72 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load
)(intptr_t *v
, intptr_t expectnot
,
73 long voffp
, intptr_t *load
, int cpu
)
77 __asm__ __volatile__
goto (
78 RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
79 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[cmpfail
])
80 #ifdef RSEQ_COMPARE_TWICE
81 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error1
])
82 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error2
])
84 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
85 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
87 RSEQ_ASM_OP_CMPNE(v
, expectnot
, %l
[cmpfail
])
89 #ifdef RSEQ_COMPARE_TWICE
90 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, %l
[error1
])
91 RSEQ_ASM_OP_CMPNE(v
, expectnot
, %l
[error2
])
94 RSEQ_ASM_OP_R_STORE(load
)
95 RSEQ_ASM_OP_R_LOAD_OFF(voffp
)
96 RSEQ_ASM_OP_R_FINAL_STORE(v
, 3)
98 RSEQ_ASM_DEFINE_ABORT(4, abort
)
99 : /* gcc asm goto does not allow outputs */
100 : [cpu_id
] "r" (cpu
),
101 [current_cpu_id
] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
102 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
104 [expectnot
] "r" (expectnot
),
108 : "memory", RSEQ_ASM_TMP_REG
110 #ifdef RSEQ_COMPARE_TWICE
114 rseq_after_asm_goto();
117 rseq_after_asm_goto();
121 rseq_after_asm_goto();
123 #ifdef RSEQ_COMPARE_TWICE
125 rseq_after_asm_goto();
126 rseq_bug("cpu_id comparison failed");
128 rseq_after_asm_goto();
129 rseq_bug("expected value comparison failed");
133 static inline __attribute__((always_inline
))
134 int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv
)(intptr_t *v
, intptr_t count
, int cpu
)
138 __asm__ __volatile__
goto (
139 RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
140 #ifdef RSEQ_COMPARE_TWICE
141 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error1
])
143 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
144 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
146 #ifdef RSEQ_COMPARE_TWICE
147 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, %l
[error1
])
149 RSEQ_ASM_OP_R_LOAD(v
)
150 RSEQ_ASM_OP_R_ADD(count
)
151 RSEQ_ASM_OP_R_FINAL_STORE(v
, 3)
153 RSEQ_ASM_DEFINE_ABORT(4, abort
)
154 : /* gcc asm goto does not allow outputs */
155 : [cpu_id
] "r" (cpu
),
156 [current_cpu_id
] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
157 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
161 : "memory", RSEQ_ASM_TMP_REG
163 #ifdef RSEQ_COMPARE_TWICE
167 rseq_after_asm_goto();
170 rseq_after_asm_goto();
173 #ifdef RSEQ_COMPARE_TWICE
175 rseq_after_asm_goto();
176 rseq_bug("cpu_id comparison failed");
180 static inline __attribute__((always_inline
))
181 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev
)(intptr_t *v
, intptr_t expect
,
182 intptr_t *v2
, intptr_t expect2
,
183 intptr_t newv
, int cpu
)
187 __asm__ __volatile__
goto (
188 RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
189 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[cmpfail
])
190 #ifdef RSEQ_COMPARE_TWICE
191 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error1
])
192 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error2
])
193 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error3
])
195 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
196 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
198 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[cmpfail
])
200 RSEQ_ASM_OP_CMPEQ(v2
, expect2
, %l
[cmpfail
])
202 #ifdef RSEQ_COMPARE_TWICE
203 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, %l
[error1
])
204 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[error2
])
205 RSEQ_ASM_OP_CMPEQ(v2
, expect2
, %l
[error3
])
207 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
209 RSEQ_ASM_DEFINE_ABORT(4, abort
)
210 : /* gcc asm goto does not allow outputs */
211 : [cpu_id
] "r" (cpu
),
212 [current_cpu_id
] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
213 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
215 [expect
] "r" (expect
),
217 [expect2
] "r" (expect2
),
220 : "memory", RSEQ_ASM_TMP_REG
222 #ifdef RSEQ_COMPARE_TWICE
223 , error1
, error2
, error3
226 rseq_after_asm_goto();
229 rseq_after_asm_goto();
233 rseq_after_asm_goto();
235 #ifdef RSEQ_COMPARE_TWICE
237 rseq_after_asm_goto();
238 rseq_bug("cpu_id comparison failed");
240 rseq_after_asm_goto();
241 rseq_bug("expected value comparison failed");
243 rseq_after_asm_goto();
244 rseq_bug("2nd expected value comparison failed");
248 #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
249 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
251 #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
252 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
254 static inline __attribute__((always_inline
))
255 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev
)(intptr_t *v
, intptr_t expect
,
256 intptr_t *v2
, intptr_t newv2
,
257 intptr_t newv
, int cpu
)
261 __asm__ __volatile__
goto (
262 RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
263 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[cmpfail
])
264 #ifdef RSEQ_COMPARE_TWICE
265 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error1
])
266 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error2
])
268 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
269 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
271 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[cmpfail
])
273 #ifdef RSEQ_COMPARE_TWICE
274 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, %l
[error1
])
275 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[error2
])
277 RSEQ_ASM_OP_STORE(newv2
, v2
)
279 #ifdef RSEQ_TEMPLATE_MO_RELEASE
280 RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv
, v
, 3)
282 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
285 RSEQ_ASM_DEFINE_ABORT(4, abort
)
286 : /* gcc asm goto does not allow outputs */
287 : [cpu_id
] "r" (cpu
),
288 [current_cpu_id
] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
289 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
290 [expect
] "r" (expect
),
296 : "memory", RSEQ_ASM_TMP_REG
298 #ifdef RSEQ_COMPARE_TWICE
302 rseq_after_asm_goto();
305 rseq_after_asm_goto();
309 rseq_after_asm_goto();
311 #ifdef RSEQ_COMPARE_TWICE
313 rseq_after_asm_goto();
314 rseq_bug("cpu_id comparison failed");
316 rseq_after_asm_goto();
317 rseq_bug("expected value comparison failed");
321 static inline __attribute__((always_inline
))
322 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev
)(intptr_t *v
, intptr_t expect
,
323 void *dst
, void *src
, size_t len
,
324 intptr_t newv
, int cpu
)
328 __asm__ __volatile__
goto (
329 RSEQ_ASM_DEFINE_TABLE(1, 2f
, 3f
, 4f
)
330 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[cmpfail
])
331 #ifdef RSEQ_COMPARE_TWICE
332 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error1
])
333 RSEQ_ASM_DEFINE_EXIT_POINT(2f
, %l
[error2
])
335 RSEQ_ASM_STORE_RSEQ_CS(2, 1b
, rseq_cs
)
336 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, 4f
)
338 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[cmpfail
])
340 #ifdef RSEQ_COMPARE_TWICE
341 RSEQ_ASM_CMP_CPU_ID(cpu_id
, current_cpu_id
, %l
[error1
])
342 RSEQ_ASM_OP_CMPEQ(v
, expect
, %l
[error2
])
344 RSEQ_ASM_OP_R_BAD_MEMCPY(dst
, src
, len
)
346 #ifdef RSEQ_TEMPLATE_MO_RELEASE
347 RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv
, v
, 3)
349 RSEQ_ASM_OP_FINAL_STORE(newv
, v
, 3)
352 RSEQ_ASM_DEFINE_ABORT(4, abort
)
353 : /* gcc asm goto does not allow outputs */
354 : [cpu_id
] "r" (cpu
),
355 [current_cpu_id
] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD
),
356 [rseq_cs
] "m" (rseq_get_abi()->rseq_cs
.arch
.ptr
),
357 [expect
] "r" (expect
),
364 : "memory", RSEQ_ASM_TMP_REG
, RSEQ_ASM_TMP_REG_2
366 #ifdef RSEQ_COMPARE_TWICE
370 rseq_after_asm_goto();
373 rseq_after_asm_goto();
377 rseq_after_asm_goto();
379 #ifdef RSEQ_COMPARE_TWICE
381 rseq_after_asm_goto();
382 rseq_bug("cpu_id comparison failed");
384 rseq_after_asm_goto();
385 rseq_bug("expected value comparison failed");
389 #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
390 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
392 #include "rseq-bits-reset.h"