xref: /linux/tools/testing/selftests/rseq/rseq-or1k-bits.h (revision 1260ed77798502de9c98020040d2995008de10cc)
1*ea1413e5SStafford Horne /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*ea1413e5SStafford Horne 
3*ea1413e5SStafford Horne #include "rseq-bits-template.h"
4*ea1413e5SStafford Horne 
5*ea1413e5SStafford Horne #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
6*ea1413e5SStafford Horne 	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
7*ea1413e5SStafford Horne 
8*ea1413e5SStafford Horne static inline __always_inline
9*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv,
10*ea1413e5SStafford Horne 				int cpu)
11*ea1413e5SStafford Horne {
12*ea1413e5SStafford Horne 	RSEQ_INJECT_C(9)
13*ea1413e5SStafford Horne 
14*ea1413e5SStafford Horne 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
15*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
16*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
17*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
18*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
19*ea1413e5SStafford Horne #endif
20*ea1413e5SStafford Horne 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
21*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
22*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(3)
23*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
24*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(4)
25*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
26*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
27*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
28*ea1413e5SStafford Horne #endif
29*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
30*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(5)
31*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
32*ea1413e5SStafford Horne 				  : /* gcc asm goto does not allow outputs */
33*ea1413e5SStafford Horne 				  : [cpu_id]		"r" (cpu),
34*ea1413e5SStafford Horne 				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
35*ea1413e5SStafford Horne 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
36*ea1413e5SStafford Horne 				    [v]			"m" (*v),
37*ea1413e5SStafford Horne 				    [expect]		"r" (expect),
38*ea1413e5SStafford Horne 				    [newv]		"r" (newv)
39*ea1413e5SStafford Horne 				    RSEQ_INJECT_INPUT
40*ea1413e5SStafford Horne 				  : "memory", RSEQ_ASM_TMP_REG_1
41*ea1413e5SStafford Horne 				    RSEQ_INJECT_CLOBBER
42*ea1413e5SStafford Horne 				  : abort, cmpfail
43*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
44*ea1413e5SStafford Horne 				    , error1, error2
45*ea1413e5SStafford Horne #endif
46*ea1413e5SStafford Horne 	);
47*ea1413e5SStafford Horne 
48*ea1413e5SStafford Horne 	return 0;
49*ea1413e5SStafford Horne abort:
50*ea1413e5SStafford Horne 	RSEQ_INJECT_FAILED
51*ea1413e5SStafford Horne 	return -1;
52*ea1413e5SStafford Horne cmpfail:
53*ea1413e5SStafford Horne 	return 1;
54*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
55*ea1413e5SStafford Horne error1:
56*ea1413e5SStafford Horne 	rseq_bug("cpu_id comparison failed");
57*ea1413e5SStafford Horne error2:
58*ea1413e5SStafford Horne 	rseq_bug("expected value comparison failed");
59*ea1413e5SStafford Horne #endif
60*ea1413e5SStafford Horne }
61*ea1413e5SStafford Horne 
62*ea1413e5SStafford Horne static inline __always_inline
63*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot,
64*ea1413e5SStafford Horne 			       off_t voffp, intptr_t *load, int cpu)
65*ea1413e5SStafford Horne {
66*ea1413e5SStafford Horne 	RSEQ_INJECT_C(9)
67*ea1413e5SStafford Horne 
68*ea1413e5SStafford Horne 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
69*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
70*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
71*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
72*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
73*ea1413e5SStafford Horne #endif
74*ea1413e5SStafford Horne 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
75*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
76*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(3)
77*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[cmpfail]")
78*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(4)
79*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
80*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
81*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[error2]")
82*ea1413e5SStafford Horne #endif
83*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_LOAD(v)
84*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_STORE(load)
85*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_LOAD_OFF(voffp)
86*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
87*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(5)
88*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
89*ea1413e5SStafford Horne 				  : /* gcc asm goto does not allow outputs */
90*ea1413e5SStafford Horne 				  : [cpu_id]		"r" (cpu),
91*ea1413e5SStafford Horne 				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
92*ea1413e5SStafford Horne 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
93*ea1413e5SStafford Horne 				    [v]			"m" (*v),
94*ea1413e5SStafford Horne 				    [expectnot]		"r" (expectnot),
95*ea1413e5SStafford Horne 				    [load]		"m" (*load),
96*ea1413e5SStafford Horne 				    [voffp]		"Ir" (voffp)
97*ea1413e5SStafford Horne 				    RSEQ_INJECT_INPUT
98*ea1413e5SStafford Horne 				  : "memory", RSEQ_ASM_TMP_REG_1
99*ea1413e5SStafford Horne 				    RSEQ_INJECT_CLOBBER
100*ea1413e5SStafford Horne 				  : abort, cmpfail
101*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
102*ea1413e5SStafford Horne 				    , error1, error2
103*ea1413e5SStafford Horne #endif
104*ea1413e5SStafford Horne 	);
105*ea1413e5SStafford Horne 	return 0;
106*ea1413e5SStafford Horne abort:
107*ea1413e5SStafford Horne 	RSEQ_INJECT_FAILED
108*ea1413e5SStafford Horne 	return -1;
109*ea1413e5SStafford Horne cmpfail:
110*ea1413e5SStafford Horne 	return 1;
111*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
112*ea1413e5SStafford Horne error1:
113*ea1413e5SStafford Horne 	rseq_bug("cpu_id comparison failed");
114*ea1413e5SStafford Horne error2:
115*ea1413e5SStafford Horne 	rseq_bug("expected value comparison failed");
116*ea1413e5SStafford Horne #endif
117*ea1413e5SStafford Horne }
118*ea1413e5SStafford Horne 
119*ea1413e5SStafford Horne static inline __always_inline
120*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu)
121*ea1413e5SStafford Horne {
122*ea1413e5SStafford Horne 	RSEQ_INJECT_C(9)
123*ea1413e5SStafford Horne 
124*ea1413e5SStafford Horne 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
125*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
126*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
127*ea1413e5SStafford Horne #endif
128*ea1413e5SStafford Horne 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
129*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
130*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(3)
131*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
132*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
133*ea1413e5SStafford Horne #endif
134*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_LOAD(v)
135*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_ADD(count)
136*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
137*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(4)
138*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
139*ea1413e5SStafford Horne 				  : /* gcc asm goto does not allow outputs */
140*ea1413e5SStafford Horne 				  : [cpu_id]		"r" (cpu),
141*ea1413e5SStafford Horne 				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
142*ea1413e5SStafford Horne 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
143*ea1413e5SStafford Horne 				    [v]			"m" (*v),
144*ea1413e5SStafford Horne 				    [count]		"r" (count)
145*ea1413e5SStafford Horne 				    RSEQ_INJECT_INPUT
146*ea1413e5SStafford Horne 				  : "memory", RSEQ_ASM_TMP_REG_1
147*ea1413e5SStafford Horne 				    RSEQ_INJECT_CLOBBER
148*ea1413e5SStafford Horne 				  : abort
149*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
150*ea1413e5SStafford Horne 				    , error1
151*ea1413e5SStafford Horne #endif
152*ea1413e5SStafford Horne 	);
153*ea1413e5SStafford Horne 	return 0;
154*ea1413e5SStafford Horne abort:
155*ea1413e5SStafford Horne 	RSEQ_INJECT_FAILED
156*ea1413e5SStafford Horne 	return -1;
157*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
158*ea1413e5SStafford Horne error1:
159*ea1413e5SStafford Horne 	rseq_bug("cpu_id comparison failed");
160*ea1413e5SStafford Horne #endif
161*ea1413e5SStafford Horne }
162*ea1413e5SStafford Horne 
163*ea1413e5SStafford Horne static inline __always_inline
164*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect,
165*ea1413e5SStafford Horne 			      intptr_t *v2, intptr_t expect2,
166*ea1413e5SStafford Horne 			      intptr_t newv, int cpu)
167*ea1413e5SStafford Horne {
168*ea1413e5SStafford Horne 	RSEQ_INJECT_C(9)
169*ea1413e5SStafford Horne 
170*ea1413e5SStafford Horne 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
171*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
172*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
173*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
174*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
175*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error3]")
176*ea1413e5SStafford Horne #endif
177*ea1413e5SStafford Horne 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
178*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
179*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(3)
180*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
181*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(4)
182*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[cmpfail]")
183*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(5)
184*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
185*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
186*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
187*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[error3]")
188*ea1413e5SStafford Horne #endif
189*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
190*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(6)
191*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
192*ea1413e5SStafford Horne 				  : /* gcc asm goto does not allow outputs */
193*ea1413e5SStafford Horne 				  : [cpu_id]		"r" (cpu),
194*ea1413e5SStafford Horne 				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
195*ea1413e5SStafford Horne 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
196*ea1413e5SStafford Horne 				    [v]			"m" (*v),
197*ea1413e5SStafford Horne 				    [expect]		"r" (expect),
198*ea1413e5SStafford Horne 				    [v2]		"m" (*v2),
199*ea1413e5SStafford Horne 				    [expect2]		"r" (expect2),
200*ea1413e5SStafford Horne 				    [newv]		"r" (newv)
201*ea1413e5SStafford Horne 				    RSEQ_INJECT_INPUT
202*ea1413e5SStafford Horne 				  : "memory", RSEQ_ASM_TMP_REG_1
203*ea1413e5SStafford Horne 				    RSEQ_INJECT_CLOBBER
204*ea1413e5SStafford Horne 				  : abort, cmpfail
205*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
206*ea1413e5SStafford Horne 				    , error1, error2, error3
207*ea1413e5SStafford Horne #endif
208*ea1413e5SStafford Horne 	);
209*ea1413e5SStafford Horne 
210*ea1413e5SStafford Horne 	return 0;
211*ea1413e5SStafford Horne abort:
212*ea1413e5SStafford Horne 	RSEQ_INJECT_FAILED
213*ea1413e5SStafford Horne 	return -1;
214*ea1413e5SStafford Horne cmpfail:
215*ea1413e5SStafford Horne 	return 1;
216*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
217*ea1413e5SStafford Horne error1:
218*ea1413e5SStafford Horne 	rseq_bug("cpu_id comparison failed");
219*ea1413e5SStafford Horne error2:
220*ea1413e5SStafford Horne 	rseq_bug("expected value comparison failed");
221*ea1413e5SStafford Horne error3:
222*ea1413e5SStafford Horne 	rseq_bug("2nd expected value comparison failed");
223*ea1413e5SStafford Horne #endif
224*ea1413e5SStafford Horne }
225*ea1413e5SStafford Horne 
226*ea1413e5SStafford Horne #define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
227*ea1413e5SStafford Horne 
228*ea1413e5SStafford Horne /*
229*ea1413e5SStafford Horne  *   pval = *(ptr+off)
230*ea1413e5SStafford Horne  *  *pval += inc;
231*ea1413e5SStafford Horne  */
232*ea1413e5SStafford Horne static inline __always_inline
233*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_offset_deref_addv)(intptr_t *ptr, off_t off, intptr_t inc,
234*ea1413e5SStafford Horne 				int cpu)
235*ea1413e5SStafford Horne {
236*ea1413e5SStafford Horne 	RSEQ_INJECT_C(9)
237*ea1413e5SStafford Horne 
238*ea1413e5SStafford Horne 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
239*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
240*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
241*ea1413e5SStafford Horne #endif
242*ea1413e5SStafford Horne 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
243*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
244*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(3)
245*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
246*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
247*ea1413e5SStafford Horne #endif
248*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, inc, 3)
249*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(4)
250*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
251*ea1413e5SStafford Horne 				  : /* gcc asm goto does not allow outputs */
252*ea1413e5SStafford Horne 				  : [cpu_id]		"r" (cpu),
253*ea1413e5SStafford Horne 				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
254*ea1413e5SStafford Horne 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
255*ea1413e5SStafford Horne 				    [ptr]		"r" (ptr),
256*ea1413e5SStafford Horne 				    [off]		"r" (off),
257*ea1413e5SStafford Horne 				    [inc]		"r" (inc)
258*ea1413e5SStafford Horne 				    RSEQ_INJECT_INPUT
259*ea1413e5SStafford Horne 				  : "memory", RSEQ_ASM_TMP_REG_1
260*ea1413e5SStafford Horne 				    RSEQ_INJECT_CLOBBER
261*ea1413e5SStafford Horne 				  : abort
262*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
263*ea1413e5SStafford Horne 				    , error1
264*ea1413e5SStafford Horne #endif
265*ea1413e5SStafford Horne 	);
266*ea1413e5SStafford Horne 	return 0;
267*ea1413e5SStafford Horne abort:
268*ea1413e5SStafford Horne 	RSEQ_INJECT_FAILED
269*ea1413e5SStafford Horne 	return -1;
270*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
271*ea1413e5SStafford Horne error1:
272*ea1413e5SStafford Horne 	rseq_bug("cpu_id comparison failed");
273*ea1413e5SStafford Horne #endif
274*ea1413e5SStafford Horne }
275*ea1413e5SStafford Horne 
276*ea1413e5SStafford Horne #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
277*ea1413e5SStafford Horne 	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
278*ea1413e5SStafford Horne 
279*ea1413e5SStafford Horne #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
280*ea1413e5SStafford Horne 	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
281*ea1413e5SStafford Horne 
282*ea1413e5SStafford Horne static inline __always_inline
283*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect,
284*ea1413e5SStafford Horne 				 intptr_t *v2, intptr_t newv2,
285*ea1413e5SStafford Horne 				 intptr_t newv, int cpu)
286*ea1413e5SStafford Horne {
287*ea1413e5SStafford Horne 	RSEQ_INJECT_C(9)
288*ea1413e5SStafford Horne 
289*ea1413e5SStafford Horne 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
290*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
291*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
292*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
293*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
294*ea1413e5SStafford Horne #endif
295*ea1413e5SStafford Horne 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
296*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
297*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(3)
298*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
299*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(4)
300*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
301*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
302*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
303*ea1413e5SStafford Horne #endif
304*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_STORE(v2, newv2)
305*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(5)
306*ea1413e5SStafford Horne #ifdef RSEQ_TEMPLATE_MO_RELEASE
307*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_FINAL_STORE_RELEASE(v, newv, 3)
308*ea1413e5SStafford Horne #else
309*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
310*ea1413e5SStafford Horne #endif
311*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(6)
312*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
313*ea1413e5SStafford Horne 				  : /* gcc asm goto does not allow outputs */
314*ea1413e5SStafford Horne 				  : [cpu_id]		"r" (cpu),
315*ea1413e5SStafford Horne 				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
316*ea1413e5SStafford Horne 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
317*ea1413e5SStafford Horne 				    [expect]		"r" (expect),
318*ea1413e5SStafford Horne 				    [v]			"m" (*v),
319*ea1413e5SStafford Horne 				    [newv]		"r" (newv),
320*ea1413e5SStafford Horne 				    [v2]		"m" (*v2),
321*ea1413e5SStafford Horne 				    [newv2]		"r" (newv2)
322*ea1413e5SStafford Horne 				    RSEQ_INJECT_INPUT
323*ea1413e5SStafford Horne 				  : "memory", RSEQ_ASM_TMP_REG_1
324*ea1413e5SStafford Horne 				    RSEQ_INJECT_CLOBBER
325*ea1413e5SStafford Horne 				  : abort, cmpfail
326*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
327*ea1413e5SStafford Horne 				    , error1, error2
328*ea1413e5SStafford Horne #endif
329*ea1413e5SStafford Horne 	);
330*ea1413e5SStafford Horne 
331*ea1413e5SStafford Horne 	return 0;
332*ea1413e5SStafford Horne abort:
333*ea1413e5SStafford Horne 	RSEQ_INJECT_FAILED
334*ea1413e5SStafford Horne 	return -1;
335*ea1413e5SStafford Horne cmpfail:
336*ea1413e5SStafford Horne 	return 1;
337*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
338*ea1413e5SStafford Horne error1:
339*ea1413e5SStafford Horne 	rseq_bug("cpu_id comparison failed");
340*ea1413e5SStafford Horne error2:
341*ea1413e5SStafford Horne 	rseq_bug("expected value comparison failed");
342*ea1413e5SStafford Horne #endif
343*ea1413e5SStafford Horne }
344*ea1413e5SStafford Horne 
345*ea1413e5SStafford Horne static inline __always_inline
346*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect,
347*ea1413e5SStafford Horne 				 void *dst, void *src, size_t len,
348*ea1413e5SStafford Horne 				 intptr_t newv, int cpu)
349*ea1413e5SStafford Horne {
350*ea1413e5SStafford Horne 	RSEQ_INJECT_C(9)
351*ea1413e5SStafford Horne 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
352*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
353*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
354*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
355*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
356*ea1413e5SStafford Horne #endif
357*ea1413e5SStafford Horne 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
358*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
359*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(3)
360*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
361*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(4)
362*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
363*ea1413e5SStafford Horne 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
364*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
365*ea1413e5SStafford Horne #endif
366*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
367*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(5)
368*ea1413e5SStafford Horne #ifdef RSEQ_TEMPLATE_MO_RELEASE
369*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_FINAL_STORE_RELEASE(v, newv, 3)
370*ea1413e5SStafford Horne #else
371*ea1413e5SStafford Horne 				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
372*ea1413e5SStafford Horne #endif
373*ea1413e5SStafford Horne 				  RSEQ_INJECT_ASM(6)
374*ea1413e5SStafford Horne 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
375*ea1413e5SStafford Horne 				  : /* gcc asm goto does not allow outputs */
376*ea1413e5SStafford Horne 				  : [cpu_id]		"r" (cpu),
377*ea1413e5SStafford Horne 				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
378*ea1413e5SStafford Horne 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
379*ea1413e5SStafford Horne 				    [expect]		"r" (expect),
380*ea1413e5SStafford Horne 				    [v]			"m" (*v),
381*ea1413e5SStafford Horne 				    [newv]		"r" (newv),
382*ea1413e5SStafford Horne 				    [dst]		"r" (dst),
383*ea1413e5SStafford Horne 				    [src]		"r" (src),
384*ea1413e5SStafford Horne 				    [len]		"r" (len)
385*ea1413e5SStafford Horne 				    RSEQ_INJECT_INPUT
386*ea1413e5SStafford Horne 				  : "memory", RSEQ_ASM_TMP_REG_1, RSEQ_ASM_TMP_REG_2,
387*ea1413e5SStafford Horne 				    RSEQ_ASM_TMP_REG_3, RSEQ_ASM_TMP_REG_4
388*ea1413e5SStafford Horne 				    RSEQ_INJECT_CLOBBER
389*ea1413e5SStafford Horne 				  : abort, cmpfail
390*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
391*ea1413e5SStafford Horne 				    , error1, error2
392*ea1413e5SStafford Horne #endif
393*ea1413e5SStafford Horne 	);
394*ea1413e5SStafford Horne 
395*ea1413e5SStafford Horne 	return 0;
396*ea1413e5SStafford Horne abort:
397*ea1413e5SStafford Horne 	RSEQ_INJECT_FAILED
398*ea1413e5SStafford Horne 	return -1;
399*ea1413e5SStafford Horne cmpfail:
400*ea1413e5SStafford Horne 	return 1;
401*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE
402*ea1413e5SStafford Horne error1:
403*ea1413e5SStafford Horne 	rseq_bug("cpu_id comparison failed");
404*ea1413e5SStafford Horne error2:
405*ea1413e5SStafford Horne 	rseq_bug("expected value comparison failed");
406*ea1413e5SStafford Horne #endif
407*ea1413e5SStafford Horne }
408*ea1413e5SStafford Horne 
409*ea1413e5SStafford Horne #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
410*ea1413e5SStafford Horne 	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
411*ea1413e5SStafford Horne 
412*ea1413e5SStafford Horne #include "rseq-bits-reset.h"
413