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