xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/rseq/rseq-riscv.h (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
1*053f45beSAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*053f45beSAndroid Build Coastguard Worker /*
3*053f45beSAndroid Build Coastguard Worker  * Select the instruction "csrw mhartid, x0" as the RSEQ_SIG. Unlike
4*053f45beSAndroid Build Coastguard Worker  * other architectures, the ebreak instruction has no immediate field for
5*053f45beSAndroid Build Coastguard Worker  * distinguishing purposes. Hence, ebreak is not suitable as RSEQ_SIG.
6*053f45beSAndroid Build Coastguard Worker  * "csrw mhartid, x0" can also satisfy the RSEQ requirement because it
7*053f45beSAndroid Build Coastguard Worker  * is an uncommon instruction and will raise an illegal instruction
8*053f45beSAndroid Build Coastguard Worker  * exception when executed in all modes.
9*053f45beSAndroid Build Coastguard Worker  */
10*053f45beSAndroid Build Coastguard Worker #include <endian.h>
11*053f45beSAndroid Build Coastguard Worker 
12*053f45beSAndroid Build Coastguard Worker #if defined(__BYTE_ORDER) ? (__BYTE_ORDER == __LITTLE_ENDIAN) : defined(__LITTLE_ENDIAN)
13*053f45beSAndroid Build Coastguard Worker #define RSEQ_SIG   0xf1401073  /* csrr mhartid, x0 */
14*053f45beSAndroid Build Coastguard Worker #else
15*053f45beSAndroid Build Coastguard Worker #error "Currently, RSEQ only supports Little-Endian version"
16*053f45beSAndroid Build Coastguard Worker #endif
17*053f45beSAndroid Build Coastguard Worker 
18*053f45beSAndroid Build Coastguard Worker #if __riscv_xlen == 64
19*053f45beSAndroid Build Coastguard Worker #define __REG_SEL(a, b)	a
20*053f45beSAndroid Build Coastguard Worker #elif __riscv_xlen == 32
21*053f45beSAndroid Build Coastguard Worker #define __REG_SEL(a, b)	b
22*053f45beSAndroid Build Coastguard Worker #endif
23*053f45beSAndroid Build Coastguard Worker 
24*053f45beSAndroid Build Coastguard Worker #define REG_L	__REG_SEL("ld ", "lw ")
25*053f45beSAndroid Build Coastguard Worker #define REG_S	__REG_SEL("sd ", "sw ")
26*053f45beSAndroid Build Coastguard Worker 
27*053f45beSAndroid Build Coastguard Worker #define RISCV_FENCE(p, s) \
28*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ ("fence " #p "," #s : : : "memory")
29*053f45beSAndroid Build Coastguard Worker #define rseq_smp_mb()	RISCV_FENCE(rw, rw)
30*053f45beSAndroid Build Coastguard Worker #define rseq_smp_rmb()	RISCV_FENCE(r, r)
31*053f45beSAndroid Build Coastguard Worker #define rseq_smp_wmb()	RISCV_FENCE(w, w)
32*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_TMP_REG_1	"t6"
33*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_TMP_REG_2	"t5"
34*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_TMP_REG_3	"t4"
35*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_TMP_REG_4	"t3"
36*053f45beSAndroid Build Coastguard Worker 
37*053f45beSAndroid Build Coastguard Worker #define rseq_smp_load_acquire(p)					\
38*053f45beSAndroid Build Coastguard Worker __extension__ ({							\
39*053f45beSAndroid Build Coastguard Worker 	__typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p));			\
40*053f45beSAndroid Build Coastguard Worker 	RISCV_FENCE(r, rw)						\
41*053f45beSAndroid Build Coastguard Worker 	____p1;								\
42*053f45beSAndroid Build Coastguard Worker })
43*053f45beSAndroid Build Coastguard Worker 
44*053f45beSAndroid Build Coastguard Worker #define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_rmb()
45*053f45beSAndroid Build Coastguard Worker 
46*053f45beSAndroid Build Coastguard Worker #define rseq_smp_store_release(p, v)					\
47*053f45beSAndroid Build Coastguard Worker do {									\
48*053f45beSAndroid Build Coastguard Worker 	RISCV_FENCE(rw, w);						\
49*053f45beSAndroid Build Coastguard Worker 	RSEQ_WRITE_ONCE(*(p), v);						\
50*053f45beSAndroid Build Coastguard Worker } while (0)
51*053f45beSAndroid Build Coastguard Worker 
52*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_SKIP_FASTPATH
53*053f45beSAndroid Build Coastguard Worker #include "rseq-skip.h"
54*053f45beSAndroid Build Coastguard Worker #else /* !RSEQ_SKIP_FASTPATH */
55*053f45beSAndroid Build Coastguard Worker 
56*053f45beSAndroid Build Coastguard Worker #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip,	\
57*053f45beSAndroid Build Coastguard Worker 				post_commit_offset, abort_ip)		\
58*053f45beSAndroid Build Coastguard Worker 	".pushsection	__rseq_cs, \"aw\"\n"				\
59*053f45beSAndroid Build Coastguard Worker 	".balign	32\n"						\
60*053f45beSAndroid Build Coastguard Worker 	__rseq_str(label) ":\n"						\
61*053f45beSAndroid Build Coastguard Worker 	".long	" __rseq_str(version) ", " __rseq_str(flags) "\n"	\
62*053f45beSAndroid Build Coastguard Worker 	".quad	" __rseq_str(start_ip) ", "				\
63*053f45beSAndroid Build Coastguard Worker 			  __rseq_str(post_commit_offset) ", "		\
64*053f45beSAndroid Build Coastguard Worker 			  __rseq_str(abort_ip) "\n"			\
65*053f45beSAndroid Build Coastguard Worker 	".popsection\n\t"						\
66*053f45beSAndroid Build Coastguard Worker 	".pushsection __rseq_cs_ptr_array, \"aw\"\n"			\
67*053f45beSAndroid Build Coastguard Worker 	".quad " __rseq_str(label) "b\n"				\
68*053f45beSAndroid Build Coastguard Worker 	".popsection\n"
69*053f45beSAndroid Build Coastguard Worker 
70*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
71*053f45beSAndroid Build Coastguard Worker 	__RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,		 \
72*053f45beSAndroid Build Coastguard Worker 				((post_commit_ip) - (start_ip)), abort_ip)
73*053f45beSAndroid Build Coastguard Worker 
74*053f45beSAndroid Build Coastguard Worker /*
75*053f45beSAndroid Build Coastguard Worker  * Exit points of a rseq critical section consist of all instructions outside
76*053f45beSAndroid Build Coastguard Worker  * of the critical section where a critical section can either branch to or
77*053f45beSAndroid Build Coastguard Worker  * reach through the normal course of its execution. The abort IP and the
78*053f45beSAndroid Build Coastguard Worker  * post-commit IP are already part of the __rseq_cs section and should not be
79*053f45beSAndroid Build Coastguard Worker  * explicitly defined as additional exit points. Knowing all exit points is
80*053f45beSAndroid Build Coastguard Worker  * useful to assist debuggers stepping over the critical section.
81*053f45beSAndroid Build Coastguard Worker  */
82*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)			\
83*053f45beSAndroid Build Coastguard Worker 	".pushsection __rseq_exit_point_array, \"aw\"\n"		\
84*053f45beSAndroid Build Coastguard Worker 	".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n"	\
85*053f45beSAndroid Build Coastguard Worker 	".popsection\n"
86*053f45beSAndroid Build Coastguard Worker 
87*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)		\
88*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_ASM(1)						\
89*053f45beSAndroid Build Coastguard Worker 	"la	" RSEQ_ASM_TMP_REG_1 ", " __rseq_str(cs_label) "\n"	\
90*053f45beSAndroid Build Coastguard Worker 	REG_S	RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(rseq_cs) "]\n"	\
91*053f45beSAndroid Build Coastguard Worker 	__rseq_str(label) ":\n"
92*053f45beSAndroid Build Coastguard Worker 
93*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_ABORT(label, abort_label)			\
94*053f45beSAndroid Build Coastguard Worker 	"j	222f\n"							\
95*053f45beSAndroid Build Coastguard Worker 	".balign	4\n"						\
96*053f45beSAndroid Build Coastguard Worker 	".long "	__rseq_str(RSEQ_SIG) "\n"			\
97*053f45beSAndroid Build Coastguard Worker 	__rseq_str(label) ":\n"						\
98*053f45beSAndroid Build Coastguard Worker 	"j	%l[" __rseq_str(abort_label) "]\n"			\
99*053f45beSAndroid Build Coastguard Worker 	"222:\n"
100*053f45beSAndroid Build Coastguard Worker 
101*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_STORE(value, var)					\
102*053f45beSAndroid Build Coastguard Worker 	REG_S	"%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n"
103*053f45beSAndroid Build Coastguard Worker 
104*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_CMPEQ(var, expect, label)				\
105*053f45beSAndroid Build Coastguard Worker 	REG_L	RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"		\
106*053f45beSAndroid Build Coastguard Worker 	"bne	" RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "] ,"	\
107*053f45beSAndroid Build Coastguard Worker 		  __rseq_str(label) "\n"
108*053f45beSAndroid Build Coastguard Worker 
109*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_CMPEQ32(var, expect, label)				\
110*053f45beSAndroid Build Coastguard Worker 	"lw	" RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"	\
111*053f45beSAndroid Build Coastguard Worker 	"bne	" RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "] ,"	\
112*053f45beSAndroid Build Coastguard Worker 		  __rseq_str(label) "\n"
113*053f45beSAndroid Build Coastguard Worker 
114*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_CMPNE(var, expect, label)				\
115*053f45beSAndroid Build Coastguard Worker 	REG_L	RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"		\
116*053f45beSAndroid Build Coastguard Worker 	"beq	" RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "] ,"	\
117*053f45beSAndroid Build Coastguard Worker 		  __rseq_str(label) "\n"
118*053f45beSAndroid Build Coastguard Worker 
119*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)		\
120*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_ASM(2)						\
121*053f45beSAndroid Build Coastguard Worker 	RSEQ_ASM_OP_CMPEQ32(current_cpu_id, cpu_id, label)
122*053f45beSAndroid Build Coastguard Worker 
123*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_LOAD(var)						\
124*053f45beSAndroid Build Coastguard Worker 	REG_L	RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"
125*053f45beSAndroid Build Coastguard Worker 
126*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_STORE(var)					\
127*053f45beSAndroid Build Coastguard Worker 	REG_S	RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"
128*053f45beSAndroid Build Coastguard Worker 
129*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_LOAD_OFF(offset)					\
130*053f45beSAndroid Build Coastguard Worker 	"add	" RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(offset) "], "	\
131*053f45beSAndroid Build Coastguard Worker 		 RSEQ_ASM_TMP_REG_1 "\n"				\
132*053f45beSAndroid Build Coastguard Worker 	REG_L	RSEQ_ASM_TMP_REG_1 ", (" RSEQ_ASM_TMP_REG_1 ")\n"
133*053f45beSAndroid Build Coastguard Worker 
134*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_ADD(count)					\
135*053f45beSAndroid Build Coastguard Worker 	"add	" RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1		\
136*053f45beSAndroid Build Coastguard Worker 		", %[" __rseq_str(count) "]\n"
137*053f45beSAndroid Build Coastguard Worker 
138*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_FINAL_STORE(value, var, post_commit_label)		\
139*053f45beSAndroid Build Coastguard Worker 	RSEQ_ASM_OP_STORE(value, var)					\
140*053f45beSAndroid Build Coastguard Worker 	__rseq_str(post_commit_label) ":\n"
141*053f45beSAndroid Build Coastguard Worker 
142*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_FINAL_STORE_RELEASE(value, var, post_commit_label)	\
143*053f45beSAndroid Build Coastguard Worker 	"fence	rw, w\n"						\
144*053f45beSAndroid Build Coastguard Worker 	RSEQ_ASM_OP_STORE(value, var)					\
145*053f45beSAndroid Build Coastguard Worker 	__rseq_str(post_commit_label) ":\n"
146*053f45beSAndroid Build Coastguard Worker 
147*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label)		\
148*053f45beSAndroid Build Coastguard Worker 	REG_S	RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"		\
149*053f45beSAndroid Build Coastguard Worker 	__rseq_str(post_commit_label) ":\n"
150*053f45beSAndroid Build Coastguard Worker 
151*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)				\
152*053f45beSAndroid Build Coastguard Worker 	"beqz	%[" __rseq_str(len) "], 333f\n"				\
153*053f45beSAndroid Build Coastguard Worker 	"mv	" RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(len) "]\n"	\
154*053f45beSAndroid Build Coastguard Worker 	"mv	" RSEQ_ASM_TMP_REG_2 ", %[" __rseq_str(src) "]\n"	\
155*053f45beSAndroid Build Coastguard Worker 	"mv	" RSEQ_ASM_TMP_REG_3 ", %[" __rseq_str(dst) "]\n"	\
156*053f45beSAndroid Build Coastguard Worker 	"222:\n"							\
157*053f45beSAndroid Build Coastguard Worker 	"lb	" RSEQ_ASM_TMP_REG_4 ", 0(" RSEQ_ASM_TMP_REG_2 ")\n"	\
158*053f45beSAndroid Build Coastguard Worker 	"sb	" RSEQ_ASM_TMP_REG_4 ", 0(" RSEQ_ASM_TMP_REG_3 ")\n"	\
159*053f45beSAndroid Build Coastguard Worker 	"addi	" RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1 ", -1\n"	\
160*053f45beSAndroid Build Coastguard Worker 	"addi	" RSEQ_ASM_TMP_REG_2 ", " RSEQ_ASM_TMP_REG_2 ", 1\n"	\
161*053f45beSAndroid Build Coastguard Worker 	"addi	" RSEQ_ASM_TMP_REG_3 ", " RSEQ_ASM_TMP_REG_3 ", 1\n"	\
162*053f45beSAndroid Build Coastguard Worker 	"bnez	" RSEQ_ASM_TMP_REG_1 ", 222b\n"				\
163*053f45beSAndroid Build Coastguard Worker 	"333:\n"
164*053f45beSAndroid Build Coastguard Worker 
165*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, post_commit_label)		\
166*053f45beSAndroid Build Coastguard Worker 	"mv	" RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(ptr) "]\n"	\
167*053f45beSAndroid Build Coastguard Worker 	RSEQ_ASM_OP_R_ADD(off)						\
168*053f45beSAndroid Build Coastguard Worker 	REG_L	  RSEQ_ASM_TMP_REG_1 ", 0(" RSEQ_ASM_TMP_REG_1 ")\n"	\
169*053f45beSAndroid Build Coastguard Worker 	RSEQ_ASM_OP_R_ADD(inc)						\
170*053f45beSAndroid Build Coastguard Worker 	__rseq_str(post_commit_label) ":\n"
171*053f45beSAndroid Build Coastguard Worker 
172*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t newv,int cpu)173*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
174*053f45beSAndroid Build Coastguard Worker {
175*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
176*053f45beSAndroid Build Coastguard Worker 
177*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
178*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
179*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
180*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
181*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
182*053f45beSAndroid Build Coastguard Worker #endif
183*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
184*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
185*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
186*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
187*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
188*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
189*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
190*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
191*053f45beSAndroid Build Coastguard Worker #endif
192*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
193*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(5)
194*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
195*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
196*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
197*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
198*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
199*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
200*053f45beSAndroid Build Coastguard Worker 				    [expect]		"r" (expect),
201*053f45beSAndroid Build Coastguard Worker 				    [newv]		"r" (newv)
202*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
203*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1
204*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
205*053f45beSAndroid Build Coastguard Worker 				  : abort, cmpfail
206*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
207*053f45beSAndroid Build Coastguard Worker 				    , error1, error2
208*053f45beSAndroid Build Coastguard Worker #endif
209*053f45beSAndroid Build Coastguard Worker 	);
210*053f45beSAndroid Build Coastguard Worker 
211*053f45beSAndroid Build Coastguard Worker 	return 0;
212*053f45beSAndroid Build Coastguard Worker abort:
213*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
214*053f45beSAndroid Build Coastguard Worker 	return -1;
215*053f45beSAndroid Build Coastguard Worker cmpfail:
216*053f45beSAndroid Build Coastguard Worker 	return 1;
217*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
218*053f45beSAndroid Build Coastguard Worker error1:
219*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
220*053f45beSAndroid Build Coastguard Worker error2:
221*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
222*053f45beSAndroid Build Coastguard Worker #endif
223*053f45beSAndroid Build Coastguard Worker }
224*053f45beSAndroid Build Coastguard Worker 
225*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_cmpnev_storeoffp_load(intptr_t * v,intptr_t expectnot,off_t voffp,intptr_t * load,int cpu)226*053f45beSAndroid Build Coastguard Worker int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
227*053f45beSAndroid Build Coastguard Worker 			       off_t voffp, intptr_t *load, int cpu)
228*053f45beSAndroid Build Coastguard Worker {
229*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
230*053f45beSAndroid Build Coastguard Worker 
231*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
232*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
233*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
234*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
235*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
236*053f45beSAndroid Build Coastguard Worker #endif
237*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
238*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
239*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
240*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[cmpfail]")
241*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
242*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
243*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
244*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[error2]")
245*053f45beSAndroid Build Coastguard Worker #endif
246*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_LOAD(v)
247*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_STORE(load)
248*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_LOAD_OFF(voffp)
249*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
250*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(5)
251*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
252*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
253*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
254*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
255*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
256*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
257*053f45beSAndroid Build Coastguard Worker 				    [expectnot]		"r" (expectnot),
258*053f45beSAndroid Build Coastguard Worker 				    [load]		"m" (*load),
259*053f45beSAndroid Build Coastguard Worker 				    [voffp]		"r" (voffp)
260*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
261*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1
262*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
263*053f45beSAndroid Build Coastguard Worker 				  : abort, cmpfail
264*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
265*053f45beSAndroid Build Coastguard Worker 				    , error1, error2
266*053f45beSAndroid Build Coastguard Worker #endif
267*053f45beSAndroid Build Coastguard Worker 	);
268*053f45beSAndroid Build Coastguard Worker 	return 0;
269*053f45beSAndroid Build Coastguard Worker abort:
270*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
271*053f45beSAndroid Build Coastguard Worker 	return -1;
272*053f45beSAndroid Build Coastguard Worker cmpfail:
273*053f45beSAndroid Build Coastguard Worker 	return 1;
274*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
275*053f45beSAndroid Build Coastguard Worker error1:
276*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
277*053f45beSAndroid Build Coastguard Worker error2:
278*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
279*053f45beSAndroid Build Coastguard Worker #endif
280*053f45beSAndroid Build Coastguard Worker }
281*053f45beSAndroid Build Coastguard Worker 
282*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_addv(intptr_t * v,intptr_t count,int cpu)283*053f45beSAndroid Build Coastguard Worker int rseq_addv(intptr_t *v, intptr_t count, int cpu)
284*053f45beSAndroid Build Coastguard Worker {
285*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
286*053f45beSAndroid Build Coastguard Worker 
287*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
288*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
289*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
290*053f45beSAndroid Build Coastguard Worker #endif
291*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
292*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
293*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
294*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
295*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
296*053f45beSAndroid Build Coastguard Worker #endif
297*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_LOAD(v)
298*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_ADD(count)
299*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
300*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
301*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
302*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
303*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
304*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
305*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
306*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
307*053f45beSAndroid Build Coastguard Worker 				    [count]		"r" (count)
308*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
309*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1
310*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
311*053f45beSAndroid Build Coastguard Worker 				  : abort
312*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
313*053f45beSAndroid Build Coastguard Worker 				    , error1
314*053f45beSAndroid Build Coastguard Worker #endif
315*053f45beSAndroid Build Coastguard Worker 	);
316*053f45beSAndroid Build Coastguard Worker 	return 0;
317*053f45beSAndroid Build Coastguard Worker abort:
318*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
319*053f45beSAndroid Build Coastguard Worker 	return -1;
320*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
321*053f45beSAndroid Build Coastguard Worker error1:
322*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
323*053f45beSAndroid Build Coastguard Worker #endif
324*053f45beSAndroid Build Coastguard Worker }
325*053f45beSAndroid Build Coastguard Worker 
326*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_cmpeqv_trystorev_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)327*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
328*053f45beSAndroid Build Coastguard Worker 				 intptr_t *v2, intptr_t newv2,
329*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
330*053f45beSAndroid Build Coastguard Worker {
331*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
332*053f45beSAndroid Build Coastguard Worker 
333*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
334*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
335*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
336*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
337*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
338*053f45beSAndroid Build Coastguard Worker #endif
339*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
340*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
341*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
342*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
343*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
344*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
345*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
346*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
347*053f45beSAndroid Build Coastguard Worker #endif
348*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_STORE(newv2, v2)
349*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(5)
350*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
351*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(6)
352*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
353*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
354*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
355*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
356*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
357*053f45beSAndroid Build Coastguard Worker 				    [expect]		"r" (expect),
358*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
359*053f45beSAndroid Build Coastguard Worker 				    [newv]		"r" (newv),
360*053f45beSAndroid Build Coastguard Worker 				    [v2]			"m" (*v2),
361*053f45beSAndroid Build Coastguard Worker 				    [newv2]		"r" (newv2)
362*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
363*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1
364*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
365*053f45beSAndroid Build Coastguard Worker 				  : abort, cmpfail
366*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
367*053f45beSAndroid Build Coastguard Worker 				    , error1, error2
368*053f45beSAndroid Build Coastguard Worker #endif
369*053f45beSAndroid Build Coastguard Worker 	);
370*053f45beSAndroid Build Coastguard Worker 
371*053f45beSAndroid Build Coastguard Worker 	return 0;
372*053f45beSAndroid Build Coastguard Worker abort:
373*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
374*053f45beSAndroid Build Coastguard Worker 	return -1;
375*053f45beSAndroid Build Coastguard Worker cmpfail:
376*053f45beSAndroid Build Coastguard Worker 	return 1;
377*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
378*053f45beSAndroid Build Coastguard Worker error1:
379*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
380*053f45beSAndroid Build Coastguard Worker error2:
381*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
382*053f45beSAndroid Build Coastguard Worker #endif
383*053f45beSAndroid Build Coastguard Worker }
384*053f45beSAndroid Build Coastguard Worker 
385*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_cmpeqv_trystorev_storev_release(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)386*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
387*053f45beSAndroid Build Coastguard Worker 					 intptr_t *v2, intptr_t newv2,
388*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
389*053f45beSAndroid Build Coastguard Worker {
390*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
391*053f45beSAndroid Build Coastguard Worker 
392*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
393*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
394*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
395*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
396*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
397*053f45beSAndroid Build Coastguard Worker #endif
398*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
399*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
400*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
401*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
402*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
403*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
404*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
405*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
406*053f45beSAndroid Build Coastguard Worker #endif
407*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_STORE(newv2, v2)
408*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(5)
409*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
410*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(6)
411*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
412*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
413*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
414*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
415*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
416*053f45beSAndroid Build Coastguard Worker 				    [expect]		"r" (expect),
417*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
418*053f45beSAndroid Build Coastguard Worker 				    [newv]		"r" (newv),
419*053f45beSAndroid Build Coastguard Worker 				    [v2]			"m" (*v2),
420*053f45beSAndroid Build Coastguard Worker 				    [newv2]		"r" (newv2)
421*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
422*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1
423*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
424*053f45beSAndroid Build Coastguard Worker 				  : abort, cmpfail
425*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
426*053f45beSAndroid Build Coastguard Worker 				    , error1, error2
427*053f45beSAndroid Build Coastguard Worker #endif
428*053f45beSAndroid Build Coastguard Worker 	);
429*053f45beSAndroid Build Coastguard Worker 
430*053f45beSAndroid Build Coastguard Worker 	return 0;
431*053f45beSAndroid Build Coastguard Worker abort:
432*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
433*053f45beSAndroid Build Coastguard Worker 	return -1;
434*053f45beSAndroid Build Coastguard Worker cmpfail:
435*053f45beSAndroid Build Coastguard Worker 	return 1;
436*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
437*053f45beSAndroid Build Coastguard Worker error1:
438*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
439*053f45beSAndroid Build Coastguard Worker error2:
440*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
441*053f45beSAndroid Build Coastguard Worker #endif
442*053f45beSAndroid Build Coastguard Worker }
443*053f45beSAndroid Build Coastguard Worker 
444*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_cmpeqv_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t expect2,intptr_t newv,int cpu)445*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
446*053f45beSAndroid Build Coastguard Worker 			      intptr_t *v2, intptr_t expect2,
447*053f45beSAndroid Build Coastguard Worker 			      intptr_t newv, int cpu)
448*053f45beSAndroid Build Coastguard Worker {
449*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
450*053f45beSAndroid Build Coastguard Worker 
451*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
452*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
453*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
454*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
455*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
456*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error3]")
457*053f45beSAndroid Build Coastguard Worker #endif
458*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
459*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
460*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
461*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
462*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
463*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[cmpfail]")
464*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(5)
465*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
466*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
467*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
468*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[error3]")
469*053f45beSAndroid Build Coastguard Worker #endif
470*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
471*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(6)
472*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
473*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
474*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
475*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
476*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
477*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
478*053f45beSAndroid Build Coastguard Worker 				    [expect]		"r" (expect),
479*053f45beSAndroid Build Coastguard Worker 				    [v2]			"m" (*v2),
480*053f45beSAndroid Build Coastguard Worker 				    [expect2]		"r" (expect2),
481*053f45beSAndroid Build Coastguard Worker 				    [newv]		"r" (newv)
482*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
483*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1
484*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
485*053f45beSAndroid Build Coastguard Worker 				  : abort, cmpfail
486*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
487*053f45beSAndroid Build Coastguard Worker 				    , error1, error2, error3
488*053f45beSAndroid Build Coastguard Worker #endif
489*053f45beSAndroid Build Coastguard Worker 	);
490*053f45beSAndroid Build Coastguard Worker 
491*053f45beSAndroid Build Coastguard Worker 	return 0;
492*053f45beSAndroid Build Coastguard Worker abort:
493*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
494*053f45beSAndroid Build Coastguard Worker 	return -1;
495*053f45beSAndroid Build Coastguard Worker cmpfail:
496*053f45beSAndroid Build Coastguard Worker 	return 1;
497*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
498*053f45beSAndroid Build Coastguard Worker error1:
499*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
500*053f45beSAndroid Build Coastguard Worker error2:
501*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
502*053f45beSAndroid Build Coastguard Worker error3:
503*053f45beSAndroid Build Coastguard Worker 	rseq_bug("2nd expected value comparison failed");
504*053f45beSAndroid Build Coastguard Worker #endif
505*053f45beSAndroid Build Coastguard Worker }
506*053f45beSAndroid Build Coastguard Worker 
507*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_cmpeqv_trymemcpy_storev(intptr_t * v,intptr_t expect,void * dst,void * src,size_t len,intptr_t newv,int cpu)508*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
509*053f45beSAndroid Build Coastguard Worker 				 void *dst, void *src, size_t len,
510*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
511*053f45beSAndroid Build Coastguard Worker {
512*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
513*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
514*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
515*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
516*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
517*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
518*053f45beSAndroid Build Coastguard Worker #endif
519*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
520*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
521*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
522*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
523*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
524*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
525*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
526*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
527*053f45beSAndroid Build Coastguard Worker #endif
528*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
529*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(5)
530*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
531*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(6)
532*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
533*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
534*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
535*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
536*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
537*053f45beSAndroid Build Coastguard Worker 				    [expect]		"r" (expect),
538*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
539*053f45beSAndroid Build Coastguard Worker 				    [newv]		"r" (newv),
540*053f45beSAndroid Build Coastguard Worker 				    [dst]			"r" (dst),
541*053f45beSAndroid Build Coastguard Worker 				    [src]			"r" (src),
542*053f45beSAndroid Build Coastguard Worker 				    [len]			"r" (len)
543*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
544*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1, RSEQ_ASM_TMP_REG_2,
545*053f45beSAndroid Build Coastguard Worker 				    RSEQ_ASM_TMP_REG_3, RSEQ_ASM_TMP_REG_4
546*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
547*053f45beSAndroid Build Coastguard Worker 				  : abort, cmpfail
548*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
549*053f45beSAndroid Build Coastguard Worker 				    , error1, error2
550*053f45beSAndroid Build Coastguard Worker #endif
551*053f45beSAndroid Build Coastguard Worker 	);
552*053f45beSAndroid Build Coastguard Worker 
553*053f45beSAndroid Build Coastguard Worker 	return 0;
554*053f45beSAndroid Build Coastguard Worker abort:
555*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
556*053f45beSAndroid Build Coastguard Worker 	return -1;
557*053f45beSAndroid Build Coastguard Worker cmpfail:
558*053f45beSAndroid Build Coastguard Worker 	return 1;
559*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
560*053f45beSAndroid Build Coastguard Worker error1:
561*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
562*053f45beSAndroid Build Coastguard Worker error2:
563*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
564*053f45beSAndroid Build Coastguard Worker #endif
565*053f45beSAndroid Build Coastguard Worker }
566*053f45beSAndroid Build Coastguard Worker 
567*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_cmpeqv_trymemcpy_storev_release(intptr_t * v,intptr_t expect,void * dst,void * src,size_t len,intptr_t newv,int cpu)568*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
569*053f45beSAndroid Build Coastguard Worker 					 void *dst, void *src, size_t len,
570*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
571*053f45beSAndroid Build Coastguard Worker {
572*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
573*053f45beSAndroid Build Coastguard Worker 
574*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
575*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
576*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
577*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
578*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
579*053f45beSAndroid Build Coastguard Worker #endif
580*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
581*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
582*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
583*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
584*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
585*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
586*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
587*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
588*053f45beSAndroid Build Coastguard Worker #endif
589*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
590*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(5)
591*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
592*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(6)
593*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
594*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
595*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
596*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
597*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
598*053f45beSAndroid Build Coastguard Worker 				    [expect]		"r" (expect),
599*053f45beSAndroid Build Coastguard Worker 				    [v]			"m" (*v),
600*053f45beSAndroid Build Coastguard Worker 				    [newv]		"r" (newv),
601*053f45beSAndroid Build Coastguard Worker 				    [dst]			"r" (dst),
602*053f45beSAndroid Build Coastguard Worker 				    [src]			"r" (src),
603*053f45beSAndroid Build Coastguard Worker 				    [len]			"r" (len)
604*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
605*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1, RSEQ_ASM_TMP_REG_2,
606*053f45beSAndroid Build Coastguard Worker 				    RSEQ_ASM_TMP_REG_3, RSEQ_ASM_TMP_REG_4
607*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
608*053f45beSAndroid Build Coastguard Worker 				  : abort, cmpfail
609*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
610*053f45beSAndroid Build Coastguard Worker 				    , error1, error2
611*053f45beSAndroid Build Coastguard Worker #endif
612*053f45beSAndroid Build Coastguard Worker 	);
613*053f45beSAndroid Build Coastguard Worker 
614*053f45beSAndroid Build Coastguard Worker 	return 0;
615*053f45beSAndroid Build Coastguard Worker abort:
616*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
617*053f45beSAndroid Build Coastguard Worker 	return -1;
618*053f45beSAndroid Build Coastguard Worker cmpfail:
619*053f45beSAndroid Build Coastguard Worker 	return 1;
620*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
621*053f45beSAndroid Build Coastguard Worker error1:
622*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
623*053f45beSAndroid Build Coastguard Worker error2:
624*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
625*053f45beSAndroid Build Coastguard Worker #endif
626*053f45beSAndroid Build Coastguard Worker }
627*053f45beSAndroid Build Coastguard Worker 
628*053f45beSAndroid Build Coastguard Worker #define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
629*053f45beSAndroid Build Coastguard Worker 
630*053f45beSAndroid Build Coastguard Worker /*
631*053f45beSAndroid Build Coastguard Worker  *   pval = *(ptr+off)
632*053f45beSAndroid Build Coastguard Worker  *  *pval += inc;
633*053f45beSAndroid Build Coastguard Worker  */
634*053f45beSAndroid Build Coastguard Worker static inline __always_inline
rseq_offset_deref_addv(intptr_t * ptr,off_t off,intptr_t inc,int cpu)635*053f45beSAndroid Build Coastguard Worker int rseq_offset_deref_addv(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
636*053f45beSAndroid Build Coastguard Worker {
637*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
638*053f45beSAndroid Build Coastguard Worker 
639*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
640*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
641*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
642*053f45beSAndroid Build Coastguard Worker #endif
643*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
644*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
645*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(3)
646*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
647*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
648*053f45beSAndroid Build Coastguard Worker #endif
649*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, 3)
650*053f45beSAndroid Build Coastguard Worker 				  RSEQ_INJECT_ASM(4)
651*053f45beSAndroid Build Coastguard Worker 				  RSEQ_ASM_DEFINE_ABORT(4, abort)
652*053f45beSAndroid Build Coastguard Worker 				  : /* gcc asm goto does not allow outputs */
653*053f45beSAndroid Build Coastguard Worker 				  : [cpu_id]		"r" (cpu),
654*053f45beSAndroid Build Coastguard Worker 				    [current_cpu_id]      "m" (rseq_get_abi()->cpu_id),
655*053f45beSAndroid Build Coastguard Worker 				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
656*053f45beSAndroid Build Coastguard Worker 				    [ptr]			"r" (ptr),
657*053f45beSAndroid Build Coastguard Worker 				    [off]			"er" (off),
658*053f45beSAndroid Build Coastguard Worker 				    [inc]			"er" (inc)
659*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_INPUT
660*053f45beSAndroid Build Coastguard Worker 				  : "memory", RSEQ_ASM_TMP_REG_1
661*053f45beSAndroid Build Coastguard Worker 				    RSEQ_INJECT_CLOBBER
662*053f45beSAndroid Build Coastguard Worker 				  : abort
663*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
664*053f45beSAndroid Build Coastguard Worker 				    , error1
665*053f45beSAndroid Build Coastguard Worker #endif
666*053f45beSAndroid Build Coastguard Worker 	);
667*053f45beSAndroid Build Coastguard Worker 	return 0;
668*053f45beSAndroid Build Coastguard Worker abort:
669*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
670*053f45beSAndroid Build Coastguard Worker 	return -1;
671*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
672*053f45beSAndroid Build Coastguard Worker error1:
673*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
674*053f45beSAndroid Build Coastguard Worker #endif
675*053f45beSAndroid Build Coastguard Worker }
676*053f45beSAndroid Build Coastguard Worker 
677*053f45beSAndroid Build Coastguard Worker #endif /* !RSEQ_SKIP_FASTPATH */
678