xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/rseq/rseq-x86.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  * rseq-x86.h
4*053f45beSAndroid Build Coastguard Worker  *
5*053f45beSAndroid Build Coastguard Worker  * (C) Copyright 2016-2018 - Mathieu Desnoyers <[email protected]>
6*053f45beSAndroid Build Coastguard Worker  */
7*053f45beSAndroid Build Coastguard Worker 
8*053f45beSAndroid Build Coastguard Worker #include <stdint.h>
9*053f45beSAndroid Build Coastguard Worker 
10*053f45beSAndroid Build Coastguard Worker /*
11*053f45beSAndroid Build Coastguard Worker  * RSEQ_SIG is used with the following reserved undefined instructions, which
12*053f45beSAndroid Build Coastguard Worker  * trap in user-space:
13*053f45beSAndroid Build Coastguard Worker  *
14*053f45beSAndroid Build Coastguard Worker  * x86-32:    0f b9 3d 53 30 05 53      ud1    0x53053053,%edi
15*053f45beSAndroid Build Coastguard Worker  * x86-64:    0f b9 3d 53 30 05 53      ud1    0x53053053(%rip),%edi
16*053f45beSAndroid Build Coastguard Worker  */
17*053f45beSAndroid Build Coastguard Worker #define RSEQ_SIG	0x53053053
18*053f45beSAndroid Build Coastguard Worker 
19*053f45beSAndroid Build Coastguard Worker /*
20*053f45beSAndroid Build Coastguard Worker  * Due to a compiler optimization bug in gcc-8 with asm goto and TLS asm input
21*053f45beSAndroid Build Coastguard Worker  * operands, we cannot use "m" input operands, and rather pass the __rseq_abi
22*053f45beSAndroid Build Coastguard Worker  * address through a "r" input operand.
23*053f45beSAndroid Build Coastguard Worker  */
24*053f45beSAndroid Build Coastguard Worker 
25*053f45beSAndroid Build Coastguard Worker /* Offset of cpu_id and rseq_cs fields in struct rseq. */
26*053f45beSAndroid Build Coastguard Worker #define RSEQ_CPU_ID_OFFSET	4
27*053f45beSAndroid Build Coastguard Worker #define RSEQ_CS_OFFSET		8
28*053f45beSAndroid Build Coastguard Worker 
29*053f45beSAndroid Build Coastguard Worker #ifdef __x86_64__
30*053f45beSAndroid Build Coastguard Worker 
31*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_TP_SEGMENT	%%fs
32*053f45beSAndroid Build Coastguard Worker 
33*053f45beSAndroid Build Coastguard Worker #define rseq_smp_mb()	\
34*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ ("lock; addl $0,-128(%%rsp)" ::: "memory", "cc")
35*053f45beSAndroid Build Coastguard Worker #define rseq_smp_rmb()	rseq_barrier()
36*053f45beSAndroid Build Coastguard Worker #define rseq_smp_wmb()	rseq_barrier()
37*053f45beSAndroid Build Coastguard Worker 
38*053f45beSAndroid Build Coastguard Worker #define rseq_smp_load_acquire(p)					\
39*053f45beSAndroid Build Coastguard Worker __extension__ ({							\
40*053f45beSAndroid Build Coastguard Worker 	__typeof(*p) ____p1 = RSEQ_READ_ONCE(*p);			\
41*053f45beSAndroid Build Coastguard Worker 	rseq_barrier();							\
42*053f45beSAndroid Build Coastguard Worker 	____p1;								\
43*053f45beSAndroid Build Coastguard Worker })
44*053f45beSAndroid Build Coastguard Worker 
45*053f45beSAndroid Build Coastguard Worker #define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_rmb()
46*053f45beSAndroid Build Coastguard Worker 
47*053f45beSAndroid Build Coastguard Worker #define rseq_smp_store_release(p, v)					\
48*053f45beSAndroid Build Coastguard Worker do {									\
49*053f45beSAndroid Build Coastguard Worker 	rseq_barrier();							\
50*053f45beSAndroid Build Coastguard Worker 	RSEQ_WRITE_ONCE(*p, v);						\
51*053f45beSAndroid Build Coastguard Worker } while (0)
52*053f45beSAndroid Build Coastguard Worker 
53*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_SKIP_FASTPATH
54*053f45beSAndroid Build Coastguard Worker #include "rseq-skip.h"
55*053f45beSAndroid Build Coastguard Worker #else /* !RSEQ_SKIP_FASTPATH */
56*053f45beSAndroid Build Coastguard Worker 
57*053f45beSAndroid Build Coastguard Worker #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,			\
58*053f45beSAndroid Build Coastguard Worker 				start_ip, post_commit_offset, abort_ip)	\
59*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs, \"aw\"\n\t"			\
60*053f45beSAndroid Build Coastguard Worker 		".balign 32\n\t"					\
61*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"				\
62*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
63*053f45beSAndroid Build Coastguard Worker 		".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
64*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"					\
65*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"		\
66*053f45beSAndroid Build Coastguard Worker 		".quad " __rseq_str(label) "b\n\t"			\
67*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
68*053f45beSAndroid Build Coastguard Worker 
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\t"	\
84*053f45beSAndroid Build Coastguard Worker 		".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \
85*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
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 		"leaq " __rseq_str(cs_label) "(%%rip), %%rax\n\t"	\
90*053f45beSAndroid Build Coastguard Worker 		"movq %%rax, " __rseq_str(rseq_cs) "\n\t"		\
91*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"
92*053f45beSAndroid Build Coastguard Worker 
93*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)		\
94*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(2)					\
95*053f45beSAndroid Build Coastguard Worker 		"cmpl %[" __rseq_str(cpu_id) "], " __rseq_str(current_cpu_id) "\n\t" \
96*053f45beSAndroid Build Coastguard Worker 		"jnz " __rseq_str(label) "\n\t"
97*053f45beSAndroid Build Coastguard Worker 
98*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)		\
99*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_failure, \"ax\"\n\t"		\
100*053f45beSAndroid Build Coastguard Worker 		/* Disassembler-friendly signature: ud1 <sig>(%rip),%edi. */ \
101*053f45beSAndroid Build Coastguard Worker 		".byte 0x0f, 0xb9, 0x3d\n\t"				\
102*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(RSEQ_SIG) "\n\t"			\
103*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"				\
104*053f45beSAndroid Build Coastguard Worker 		teardown						\
105*053f45beSAndroid Build Coastguard Worker 		"jmp %l[" __rseq_str(abort_label) "]\n\t"		\
106*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
107*053f45beSAndroid Build Coastguard Worker 
108*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label)		\
109*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_failure, \"ax\"\n\t"		\
110*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"				\
111*053f45beSAndroid Build Coastguard Worker 		teardown						\
112*053f45beSAndroid Build Coastguard Worker 		"jmp %l[" __rseq_str(cmpfail_label) "]\n\t"		\
113*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
114*053f45beSAndroid Build Coastguard Worker 
115*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t newv,int cpu)116*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
117*053f45beSAndroid Build Coastguard Worker {
118*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
119*053f45beSAndroid Build Coastguard Worker 
120*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
121*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
122*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
123*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
124*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
125*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
126*053f45beSAndroid Build Coastguard Worker #endif
127*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
128*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
129*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
130*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
131*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
132*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
133*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
134*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
135*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
136*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
137*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error2]\n\t"
138*053f45beSAndroid Build Coastguard Worker #endif
139*053f45beSAndroid Build Coastguard Worker 		/* final store */
140*053f45beSAndroid Build Coastguard Worker 		"movq %[newv], %[v]\n\t"
141*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
142*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
143*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
144*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
145*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
146*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
147*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
148*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
149*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
150*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "rax"
151*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
152*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
153*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
154*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
155*053f45beSAndroid Build Coastguard Worker #endif
156*053f45beSAndroid Build Coastguard Worker 	);
157*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
158*053f45beSAndroid Build Coastguard Worker 	return 0;
159*053f45beSAndroid Build Coastguard Worker abort:
160*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
161*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
162*053f45beSAndroid Build Coastguard Worker 	return -1;
163*053f45beSAndroid Build Coastguard Worker cmpfail:
164*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
165*053f45beSAndroid Build Coastguard Worker 	return 1;
166*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
167*053f45beSAndroid Build Coastguard Worker error1:
168*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
169*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
170*053f45beSAndroid Build Coastguard Worker error2:
171*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
172*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
173*053f45beSAndroid Build Coastguard Worker #endif
174*053f45beSAndroid Build Coastguard Worker }
175*053f45beSAndroid Build Coastguard Worker 
176*053f45beSAndroid Build Coastguard Worker /*
177*053f45beSAndroid Build Coastguard Worker  * Compare @v against @expectnot. When it does _not_ match, load @v
178*053f45beSAndroid Build Coastguard Worker  * into @load, and store the content of *@v + voffp into @v.
179*053f45beSAndroid Build Coastguard Worker  */
180*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpnev_storeoffp_load(intptr_t * v,intptr_t expectnot,long voffp,intptr_t * load,int cpu)181*053f45beSAndroid Build Coastguard Worker int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
182*053f45beSAndroid Build Coastguard Worker 			       long voffp, intptr_t *load, int cpu)
183*053f45beSAndroid Build Coastguard Worker {
184*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
185*053f45beSAndroid Build Coastguard Worker 
186*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
187*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
188*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
189*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
190*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
191*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
192*053f45beSAndroid Build Coastguard Worker #endif
193*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
194*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
195*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
196*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
197*053f45beSAndroid Build Coastguard Worker 		"movq %[v], %%rbx\n\t"
198*053f45beSAndroid Build Coastguard Worker 		"cmpq %%rbx, %[expectnot]\n\t"
199*053f45beSAndroid Build Coastguard Worker 		"je %l[cmpfail]\n\t"
200*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
201*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
202*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
203*053f45beSAndroid Build Coastguard Worker 		"movq %[v], %%rbx\n\t"
204*053f45beSAndroid Build Coastguard Worker 		"cmpq %%rbx, %[expectnot]\n\t"
205*053f45beSAndroid Build Coastguard Worker 		"je %l[error2]\n\t"
206*053f45beSAndroid Build Coastguard Worker #endif
207*053f45beSAndroid Build Coastguard Worker 		"movq %%rbx, %[load]\n\t"
208*053f45beSAndroid Build Coastguard Worker 		"addq %[voffp], %%rbx\n\t"
209*053f45beSAndroid Build Coastguard Worker 		"movq (%%rbx), %%rbx\n\t"
210*053f45beSAndroid Build Coastguard Worker 		/* final store */
211*053f45beSAndroid Build Coastguard Worker 		"movq %%rbx, %[v]\n\t"
212*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
213*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
214*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
215*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
216*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
217*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
218*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
219*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
220*053f45beSAndroid Build Coastguard Worker 		  [expectnot]		"r" (expectnot),
221*053f45beSAndroid Build Coastguard Worker 		  [voffp]		"er" (voffp),
222*053f45beSAndroid Build Coastguard Worker 		  [load]		"m" (*load)
223*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "rax", "rbx"
224*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
225*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
226*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
227*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
228*053f45beSAndroid Build Coastguard Worker #endif
229*053f45beSAndroid Build Coastguard Worker 	);
230*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
231*053f45beSAndroid Build Coastguard Worker 	return 0;
232*053f45beSAndroid Build Coastguard Worker abort:
233*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
234*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
235*053f45beSAndroid Build Coastguard Worker 	return -1;
236*053f45beSAndroid Build Coastguard Worker cmpfail:
237*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
238*053f45beSAndroid Build Coastguard Worker 	return 1;
239*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
240*053f45beSAndroid Build Coastguard Worker error1:
241*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
242*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
243*053f45beSAndroid Build Coastguard Worker error2:
244*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
245*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
246*053f45beSAndroid Build Coastguard Worker #endif
247*053f45beSAndroid Build Coastguard Worker }
248*053f45beSAndroid Build Coastguard Worker 
249*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_addv(intptr_t * v,intptr_t count,int cpu)250*053f45beSAndroid Build Coastguard Worker int rseq_addv(intptr_t *v, intptr_t count, int cpu)
251*053f45beSAndroid Build Coastguard Worker {
252*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
253*053f45beSAndroid Build Coastguard Worker 
254*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
255*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
256*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
257*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
258*053f45beSAndroid Build Coastguard Worker #endif
259*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
260*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
261*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
262*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
263*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
264*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
265*053f45beSAndroid Build Coastguard Worker #endif
266*053f45beSAndroid Build Coastguard Worker 		/* final store */
267*053f45beSAndroid Build Coastguard Worker 		"addq %[count], %[v]\n\t"
268*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
269*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
270*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
271*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
272*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
273*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
274*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
275*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
276*053f45beSAndroid Build Coastguard Worker 		  [count]		"er" (count)
277*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "rax"
278*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
279*053f45beSAndroid Build Coastguard Worker 		: abort
280*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
281*053f45beSAndroid Build Coastguard Worker 		  , error1
282*053f45beSAndroid Build Coastguard Worker #endif
283*053f45beSAndroid Build Coastguard Worker 	);
284*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
285*053f45beSAndroid Build Coastguard Worker 	return 0;
286*053f45beSAndroid Build Coastguard Worker abort:
287*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
288*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
289*053f45beSAndroid Build Coastguard Worker 	return -1;
290*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
291*053f45beSAndroid Build Coastguard Worker error1:
292*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
293*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
294*053f45beSAndroid Build Coastguard Worker #endif
295*053f45beSAndroid Build Coastguard Worker }
296*053f45beSAndroid Build Coastguard Worker 
297*053f45beSAndroid Build Coastguard Worker #define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
298*053f45beSAndroid Build Coastguard Worker 
299*053f45beSAndroid Build Coastguard Worker /*
300*053f45beSAndroid Build Coastguard Worker  *   pval = *(ptr+off)
301*053f45beSAndroid Build Coastguard Worker  *  *pval += inc;
302*053f45beSAndroid Build Coastguard Worker  */
303*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_offset_deref_addv(intptr_t * ptr,long off,intptr_t inc,int cpu)304*053f45beSAndroid Build Coastguard Worker int rseq_offset_deref_addv(intptr_t *ptr, long off, intptr_t inc, int cpu)
305*053f45beSAndroid Build Coastguard Worker {
306*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
307*053f45beSAndroid Build Coastguard Worker 
308*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
309*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
310*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
311*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
312*053f45beSAndroid Build Coastguard Worker #endif
313*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
314*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
315*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
316*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
317*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
318*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
319*053f45beSAndroid Build Coastguard Worker #endif
320*053f45beSAndroid Build Coastguard Worker 		/* get p+v */
321*053f45beSAndroid Build Coastguard Worker 		"movq %[ptr], %%rbx\n\t"
322*053f45beSAndroid Build Coastguard Worker 		"addq %[off], %%rbx\n\t"
323*053f45beSAndroid Build Coastguard Worker 		/* get pv */
324*053f45beSAndroid Build Coastguard Worker 		"movq (%%rbx), %%rcx\n\t"
325*053f45beSAndroid Build Coastguard Worker 		/* *pv += inc */
326*053f45beSAndroid Build Coastguard Worker 		"addq %[inc], (%%rcx)\n\t"
327*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
328*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
329*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
330*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
331*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
332*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
333*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
334*053f45beSAndroid Build Coastguard Worker 		  [ptr]			"m" (*ptr),
335*053f45beSAndroid Build Coastguard Worker 		  [off]			"er" (off),
336*053f45beSAndroid Build Coastguard Worker 		  [inc]			"er" (inc)
337*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "rax", "rbx", "rcx"
338*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
339*053f45beSAndroid Build Coastguard Worker 		: abort
340*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
341*053f45beSAndroid Build Coastguard Worker 		  , error1
342*053f45beSAndroid Build Coastguard Worker #endif
343*053f45beSAndroid Build Coastguard Worker 	);
344*053f45beSAndroid Build Coastguard Worker 	return 0;
345*053f45beSAndroid Build Coastguard Worker abort:
346*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
347*053f45beSAndroid Build Coastguard Worker 	return -1;
348*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
349*053f45beSAndroid Build Coastguard Worker error1:
350*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
351*053f45beSAndroid Build Coastguard Worker #endif
352*053f45beSAndroid Build Coastguard Worker }
353*053f45beSAndroid Build Coastguard Worker 
354*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trystorev_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)355*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
356*053f45beSAndroid Build Coastguard Worker 				 intptr_t *v2, intptr_t newv2,
357*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
358*053f45beSAndroid Build Coastguard Worker {
359*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
360*053f45beSAndroid Build Coastguard Worker 
361*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
362*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
363*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
364*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
365*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
366*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
367*053f45beSAndroid Build Coastguard Worker #endif
368*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
369*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
370*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
371*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
372*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
373*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
374*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
375*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
376*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
377*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
378*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error2]\n\t"
379*053f45beSAndroid Build Coastguard Worker #endif
380*053f45beSAndroid Build Coastguard Worker 		/* try store */
381*053f45beSAndroid Build Coastguard Worker 		"movq %[newv2], %[v2]\n\t"
382*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
383*053f45beSAndroid Build Coastguard Worker 		/* final store */
384*053f45beSAndroid Build Coastguard Worker 		"movq %[newv], %[v]\n\t"
385*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
386*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
387*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
388*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
389*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
390*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
391*053f45beSAndroid Build Coastguard Worker 		  /* try store input */
392*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
393*053f45beSAndroid Build Coastguard Worker 		  [newv2]		"r" (newv2),
394*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
395*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
396*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
397*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
398*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "rax"
399*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
400*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
401*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
402*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
403*053f45beSAndroid Build Coastguard Worker #endif
404*053f45beSAndroid Build Coastguard Worker 	);
405*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
406*053f45beSAndroid Build Coastguard Worker 	return 0;
407*053f45beSAndroid Build Coastguard Worker abort:
408*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
409*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
410*053f45beSAndroid Build Coastguard Worker 	return -1;
411*053f45beSAndroid Build Coastguard Worker cmpfail:
412*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
413*053f45beSAndroid Build Coastguard Worker 	return 1;
414*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
415*053f45beSAndroid Build Coastguard Worker error1:
416*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
417*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
418*053f45beSAndroid Build Coastguard Worker error2:
419*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
420*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
421*053f45beSAndroid Build Coastguard Worker #endif
422*053f45beSAndroid Build Coastguard Worker }
423*053f45beSAndroid Build Coastguard Worker 
424*053f45beSAndroid Build Coastguard Worker /* x86-64 is TSO. */
425*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trystorev_storev_release(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)426*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
427*053f45beSAndroid Build Coastguard Worker 					 intptr_t *v2, intptr_t newv2,
428*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
429*053f45beSAndroid Build Coastguard Worker {
430*053f45beSAndroid Build Coastguard Worker 	return rseq_cmpeqv_trystorev_storev(v, expect, v2, newv2, newv, cpu);
431*053f45beSAndroid Build Coastguard Worker }
432*053f45beSAndroid Build Coastguard Worker 
433*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t expect2,intptr_t newv,int cpu)434*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
435*053f45beSAndroid Build Coastguard Worker 			      intptr_t *v2, intptr_t expect2,
436*053f45beSAndroid Build Coastguard Worker 			      intptr_t newv, int cpu)
437*053f45beSAndroid Build Coastguard Worker {
438*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
439*053f45beSAndroid Build Coastguard Worker 
440*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
441*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
442*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
443*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
444*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
445*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
446*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
447*053f45beSAndroid Build Coastguard Worker #endif
448*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
449*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
450*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
451*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
452*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
453*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
454*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
455*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v2], %[expect2]\n\t"
456*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
457*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
458*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
459*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
460*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
461*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error2]\n\t"
462*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v2], %[expect2]\n\t"
463*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error3]\n\t"
464*053f45beSAndroid Build Coastguard Worker #endif
465*053f45beSAndroid Build Coastguard Worker 		/* final store */
466*053f45beSAndroid Build Coastguard Worker 		"movq %[newv], %[v]\n\t"
467*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
468*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
469*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
470*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
471*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
472*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
473*053f45beSAndroid Build Coastguard Worker 		  /* cmp2 input */
474*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
475*053f45beSAndroid Build Coastguard Worker 		  [expect2]		"r" (expect2),
476*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
477*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
478*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
479*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
480*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "rax"
481*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
482*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
483*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
484*053f45beSAndroid Build Coastguard Worker 		  , error1, error2, error3
485*053f45beSAndroid Build Coastguard Worker #endif
486*053f45beSAndroid Build Coastguard Worker 	);
487*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
488*053f45beSAndroid Build Coastguard Worker 	return 0;
489*053f45beSAndroid Build Coastguard Worker abort:
490*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
491*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
492*053f45beSAndroid Build Coastguard Worker 	return -1;
493*053f45beSAndroid Build Coastguard Worker cmpfail:
494*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
495*053f45beSAndroid Build Coastguard Worker 	return 1;
496*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
497*053f45beSAndroid Build Coastguard Worker error1:
498*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
499*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
500*053f45beSAndroid Build Coastguard Worker error2:
501*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
502*053f45beSAndroid Build Coastguard Worker 	rseq_bug("1st expected value comparison failed");
503*053f45beSAndroid Build Coastguard Worker error3:
504*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
505*053f45beSAndroid Build Coastguard Worker 	rseq_bug("2nd expected value comparison failed");
506*053f45beSAndroid Build Coastguard Worker #endif
507*053f45beSAndroid Build Coastguard Worker }
508*053f45beSAndroid Build Coastguard Worker 
509*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trymemcpy_storev(intptr_t * v,intptr_t expect,void * dst,void * src,size_t len,intptr_t newv,int cpu)510*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
511*053f45beSAndroid Build Coastguard Worker 				 void *dst, void *src, size_t len,
512*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
513*053f45beSAndroid Build Coastguard Worker {
514*053f45beSAndroid Build Coastguard Worker 	uint64_t rseq_scratch[3];
515*053f45beSAndroid Build Coastguard Worker 
516*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
517*053f45beSAndroid Build Coastguard Worker 
518*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
519*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
520*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
521*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
522*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
523*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
524*053f45beSAndroid Build Coastguard Worker #endif
525*053f45beSAndroid Build Coastguard Worker 		"movq %[src], %[rseq_scratch0]\n\t"
526*053f45beSAndroid Build Coastguard Worker 		"movq %[dst], %[rseq_scratch1]\n\t"
527*053f45beSAndroid Build Coastguard Worker 		"movq %[len], %[rseq_scratch2]\n\t"
528*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
529*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
530*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
531*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
532*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
533*053f45beSAndroid Build Coastguard Worker 		"jnz 5f\n\t"
534*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
535*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
536*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
537*053f45beSAndroid Build Coastguard Worker 		"cmpq %[v], %[expect]\n\t"
538*053f45beSAndroid Build Coastguard Worker 		"jnz 7f\n\t"
539*053f45beSAndroid Build Coastguard Worker #endif
540*053f45beSAndroid Build Coastguard Worker 		/* try memcpy */
541*053f45beSAndroid Build Coastguard Worker 		"test %[len], %[len]\n\t" \
542*053f45beSAndroid Build Coastguard Worker 		"jz 333f\n\t" \
543*053f45beSAndroid Build Coastguard Worker 		"222:\n\t" \
544*053f45beSAndroid Build Coastguard Worker 		"movb (%[src]), %%al\n\t" \
545*053f45beSAndroid Build Coastguard Worker 		"movb %%al, (%[dst])\n\t" \
546*053f45beSAndroid Build Coastguard Worker 		"inc %[src]\n\t" \
547*053f45beSAndroid Build Coastguard Worker 		"inc %[dst]\n\t" \
548*053f45beSAndroid Build Coastguard Worker 		"dec %[len]\n\t" \
549*053f45beSAndroid Build Coastguard Worker 		"jnz 222b\n\t" \
550*053f45beSAndroid Build Coastguard Worker 		"333:\n\t" \
551*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
552*053f45beSAndroid Build Coastguard Worker 		/* final store */
553*053f45beSAndroid Build Coastguard Worker 		"movq %[newv], %[v]\n\t"
554*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
555*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
556*053f45beSAndroid Build Coastguard Worker 		/* teardown */
557*053f45beSAndroid Build Coastguard Worker 		"movq %[rseq_scratch2], %[len]\n\t"
558*053f45beSAndroid Build Coastguard Worker 		"movq %[rseq_scratch1], %[dst]\n\t"
559*053f45beSAndroid Build Coastguard Worker 		"movq %[rseq_scratch0], %[src]\n\t"
560*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4,
561*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch2], %[len]\n\t"
562*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch1], %[dst]\n\t"
563*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch0], %[src]\n\t",
564*053f45beSAndroid Build Coastguard Worker 			abort)
565*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(5,
566*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch2], %[len]\n\t"
567*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch1], %[dst]\n\t"
568*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch0], %[src]\n\t",
569*053f45beSAndroid Build Coastguard Worker 			cmpfail)
570*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
571*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(6,
572*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch2], %[len]\n\t"
573*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch1], %[dst]\n\t"
574*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch0], %[src]\n\t",
575*053f45beSAndroid Build Coastguard Worker 			error1)
576*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(7,
577*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch2], %[len]\n\t"
578*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch1], %[dst]\n\t"
579*053f45beSAndroid Build Coastguard Worker 			"movq %[rseq_scratch0], %[src]\n\t",
580*053f45beSAndroid Build Coastguard Worker 			error2)
581*053f45beSAndroid Build Coastguard Worker #endif
582*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
583*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
584*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
585*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
586*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
587*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
588*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv),
589*053f45beSAndroid Build Coastguard Worker 		  /* try memcpy input */
590*053f45beSAndroid Build Coastguard Worker 		  [dst]			"r" (dst),
591*053f45beSAndroid Build Coastguard Worker 		  [src]			"r" (src),
592*053f45beSAndroid Build Coastguard Worker 		  [len]			"r" (len),
593*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch0]	"m" (rseq_scratch[0]),
594*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch1]	"m" (rseq_scratch[1]),
595*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch2]	"m" (rseq_scratch[2])
596*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "rax"
597*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
598*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
599*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
600*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
601*053f45beSAndroid Build Coastguard Worker #endif
602*053f45beSAndroid Build Coastguard Worker 	);
603*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
604*053f45beSAndroid Build Coastguard Worker 	return 0;
605*053f45beSAndroid Build Coastguard Worker abort:
606*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
607*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
608*053f45beSAndroid Build Coastguard Worker 	return -1;
609*053f45beSAndroid Build Coastguard Worker cmpfail:
610*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
611*053f45beSAndroid Build Coastguard Worker 	return 1;
612*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
613*053f45beSAndroid Build Coastguard Worker error1:
614*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
615*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
616*053f45beSAndroid Build Coastguard Worker error2:
617*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
618*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
619*053f45beSAndroid Build Coastguard Worker #endif
620*053f45beSAndroid Build Coastguard Worker }
621*053f45beSAndroid Build Coastguard Worker 
622*053f45beSAndroid Build Coastguard Worker /* x86-64 is TSO. */
623*053f45beSAndroid Build Coastguard Worker static inline __attribute__((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)624*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
625*053f45beSAndroid Build Coastguard Worker 					 void *dst, void *src, size_t len,
626*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
627*053f45beSAndroid Build Coastguard Worker {
628*053f45beSAndroid Build Coastguard Worker 	return rseq_cmpeqv_trymemcpy_storev(v, expect, dst, src, len,
629*053f45beSAndroid Build Coastguard Worker 					    newv, cpu);
630*053f45beSAndroid Build Coastguard Worker }
631*053f45beSAndroid Build Coastguard Worker 
632*053f45beSAndroid Build Coastguard Worker #endif /* !RSEQ_SKIP_FASTPATH */
633*053f45beSAndroid Build Coastguard Worker 
634*053f45beSAndroid Build Coastguard Worker #elif defined(__i386__)
635*053f45beSAndroid Build Coastguard Worker 
636*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_TP_SEGMENT	%%gs
637*053f45beSAndroid Build Coastguard Worker 
638*053f45beSAndroid Build Coastguard Worker #define rseq_smp_mb()	\
639*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
640*053f45beSAndroid Build Coastguard Worker #define rseq_smp_rmb()	\
641*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
642*053f45beSAndroid Build Coastguard Worker #define rseq_smp_wmb()	\
643*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
644*053f45beSAndroid Build Coastguard Worker 
645*053f45beSAndroid Build Coastguard Worker #define rseq_smp_load_acquire(p)					\
646*053f45beSAndroid Build Coastguard Worker __extension__ ({							\
647*053f45beSAndroid Build Coastguard Worker 	__typeof(*p) ____p1 = RSEQ_READ_ONCE(*p);			\
648*053f45beSAndroid Build Coastguard Worker 	rseq_smp_mb();							\
649*053f45beSAndroid Build Coastguard Worker 	____p1;								\
650*053f45beSAndroid Build Coastguard Worker })
651*053f45beSAndroid Build Coastguard Worker 
652*053f45beSAndroid Build Coastguard Worker #define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_rmb()
653*053f45beSAndroid Build Coastguard Worker 
654*053f45beSAndroid Build Coastguard Worker #define rseq_smp_store_release(p, v)					\
655*053f45beSAndroid Build Coastguard Worker do {									\
656*053f45beSAndroid Build Coastguard Worker 	rseq_smp_mb();							\
657*053f45beSAndroid Build Coastguard Worker 	RSEQ_WRITE_ONCE(*p, v);						\
658*053f45beSAndroid Build Coastguard Worker } while (0)
659*053f45beSAndroid Build Coastguard Worker 
660*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_SKIP_FASTPATH
661*053f45beSAndroid Build Coastguard Worker #include "rseq-skip.h"
662*053f45beSAndroid Build Coastguard Worker #else /* !RSEQ_SKIP_FASTPATH */
663*053f45beSAndroid Build Coastguard Worker 
664*053f45beSAndroid Build Coastguard Worker /*
665*053f45beSAndroid Build Coastguard Worker  * Use eax as scratch register and take memory operands as input to
666*053f45beSAndroid Build Coastguard Worker  * lessen register pressure. Especially needed when compiling in O0.
667*053f45beSAndroid Build Coastguard Worker  */
668*053f45beSAndroid Build Coastguard Worker #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,			\
669*053f45beSAndroid Build Coastguard Worker 				start_ip, post_commit_offset, abort_ip)	\
670*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs, \"aw\"\n\t"			\
671*053f45beSAndroid Build Coastguard Worker 		".balign 32\n\t"					\
672*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"				\
673*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
674*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
675*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"					\
676*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"		\
677*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(label) "b, 0x0\n\t"			\
678*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
679*053f45beSAndroid Build Coastguard Worker 
680*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
681*053f45beSAndroid Build Coastguard Worker 	__RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,		\
682*053f45beSAndroid Build Coastguard Worker 				(post_commit_ip - start_ip), abort_ip)
683*053f45beSAndroid Build Coastguard Worker 
684*053f45beSAndroid Build Coastguard Worker /*
685*053f45beSAndroid Build Coastguard Worker  * Exit points of a rseq critical section consist of all instructions outside
686*053f45beSAndroid Build Coastguard Worker  * of the critical section where a critical section can either branch to or
687*053f45beSAndroid Build Coastguard Worker  * reach through the normal course of its execution. The abort IP and the
688*053f45beSAndroid Build Coastguard Worker  * post-commit IP are already part of the __rseq_cs section and should not be
689*053f45beSAndroid Build Coastguard Worker  * explicitly defined as additional exit points. Knowing all exit points is
690*053f45beSAndroid Build Coastguard Worker  * useful to assist debuggers stepping over the critical section.
691*053f45beSAndroid Build Coastguard Worker  */
692*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)			\
693*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_exit_point_array, \"aw\"\n\t"	\
694*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) ", 0x0\n\t" \
695*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
696*053f45beSAndroid Build Coastguard Worker 
697*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)		\
698*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(1)					\
699*053f45beSAndroid Build Coastguard Worker 		"movl $" __rseq_str(cs_label) ", " __rseq_str(rseq_cs) "\n\t"	\
700*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"
701*053f45beSAndroid Build Coastguard Worker 
702*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)		\
703*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(2)					\
704*053f45beSAndroid Build Coastguard Worker 		"cmpl %[" __rseq_str(cpu_id) "], " __rseq_str(current_cpu_id) "\n\t" \
705*053f45beSAndroid Build Coastguard Worker 		"jnz " __rseq_str(label) "\n\t"
706*053f45beSAndroid Build Coastguard Worker 
707*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)		\
708*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_failure, \"ax\"\n\t"		\
709*053f45beSAndroid Build Coastguard Worker 		/* Disassembler-friendly signature: ud1 <sig>,%edi. */	\
710*053f45beSAndroid Build Coastguard Worker 		".byte 0x0f, 0xb9, 0x3d\n\t"				\
711*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(RSEQ_SIG) "\n\t"			\
712*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"				\
713*053f45beSAndroid Build Coastguard Worker 		teardown						\
714*053f45beSAndroid Build Coastguard Worker 		"jmp %l[" __rseq_str(abort_label) "]\n\t"		\
715*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
716*053f45beSAndroid Build Coastguard Worker 
717*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label)		\
718*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_failure, \"ax\"\n\t"		\
719*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"				\
720*053f45beSAndroid Build Coastguard Worker 		teardown						\
721*053f45beSAndroid Build Coastguard Worker 		"jmp %l[" __rseq_str(cmpfail_label) "]\n\t"		\
722*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
723*053f45beSAndroid Build Coastguard Worker 
724*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t newv,int cpu)725*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
726*053f45beSAndroid Build Coastguard Worker {
727*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
728*053f45beSAndroid Build Coastguard Worker 
729*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
730*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
731*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
732*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
733*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
734*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
735*053f45beSAndroid Build Coastguard Worker #endif
736*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
737*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
738*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
739*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
740*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %[expect]\n\t"
741*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
742*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
743*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
744*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
745*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %[expect]\n\t"
746*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error2]\n\t"
747*053f45beSAndroid Build Coastguard Worker #endif
748*053f45beSAndroid Build Coastguard Worker 		/* final store */
749*053f45beSAndroid Build Coastguard Worker 		"movl %[newv], %[v]\n\t"
750*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
751*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
752*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
753*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
754*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
755*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
756*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
757*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
758*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
759*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax"
760*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
761*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
762*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
763*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
764*053f45beSAndroid Build Coastguard Worker #endif
765*053f45beSAndroid Build Coastguard Worker 	);
766*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
767*053f45beSAndroid Build Coastguard Worker 	return 0;
768*053f45beSAndroid Build Coastguard Worker abort:
769*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
770*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
771*053f45beSAndroid Build Coastguard Worker 	return -1;
772*053f45beSAndroid Build Coastguard Worker cmpfail:
773*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
774*053f45beSAndroid Build Coastguard Worker 	return 1;
775*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
776*053f45beSAndroid Build Coastguard Worker error1:
777*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
778*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
779*053f45beSAndroid Build Coastguard Worker error2:
780*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
781*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
782*053f45beSAndroid Build Coastguard Worker #endif
783*053f45beSAndroid Build Coastguard Worker }
784*053f45beSAndroid Build Coastguard Worker 
785*053f45beSAndroid Build Coastguard Worker /*
786*053f45beSAndroid Build Coastguard Worker  * Compare @v against @expectnot. When it does _not_ match, load @v
787*053f45beSAndroid Build Coastguard Worker  * into @load, and store the content of *@v + voffp into @v.
788*053f45beSAndroid Build Coastguard Worker  */
789*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpnev_storeoffp_load(intptr_t * v,intptr_t expectnot,long voffp,intptr_t * load,int cpu)790*053f45beSAndroid Build Coastguard Worker int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
791*053f45beSAndroid Build Coastguard Worker 			       long voffp, intptr_t *load, int cpu)
792*053f45beSAndroid Build Coastguard Worker {
793*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
794*053f45beSAndroid Build Coastguard Worker 
795*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
796*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
797*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
798*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
799*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
800*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
801*053f45beSAndroid Build Coastguard Worker #endif
802*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
803*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
804*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
805*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
806*053f45beSAndroid Build Coastguard Worker 		"movl %[v], %%ebx\n\t"
807*053f45beSAndroid Build Coastguard Worker 		"cmpl %%ebx, %[expectnot]\n\t"
808*053f45beSAndroid Build Coastguard Worker 		"je %l[cmpfail]\n\t"
809*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
810*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
811*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
812*053f45beSAndroid Build Coastguard Worker 		"movl %[v], %%ebx\n\t"
813*053f45beSAndroid Build Coastguard Worker 		"cmpl %%ebx, %[expectnot]\n\t"
814*053f45beSAndroid Build Coastguard Worker 		"je %l[error2]\n\t"
815*053f45beSAndroid Build Coastguard Worker #endif
816*053f45beSAndroid Build Coastguard Worker 		"movl %%ebx, %[load]\n\t"
817*053f45beSAndroid Build Coastguard Worker 		"addl %[voffp], %%ebx\n\t"
818*053f45beSAndroid Build Coastguard Worker 		"movl (%%ebx), %%ebx\n\t"
819*053f45beSAndroid Build Coastguard Worker 		/* final store */
820*053f45beSAndroid Build Coastguard Worker 		"movl %%ebx, %[v]\n\t"
821*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
822*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
823*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
824*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
825*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
826*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
827*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
828*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
829*053f45beSAndroid Build Coastguard Worker 		  [expectnot]		"r" (expectnot),
830*053f45beSAndroid Build Coastguard Worker 		  [voffp]		"ir" (voffp),
831*053f45beSAndroid Build Coastguard Worker 		  [load]		"m" (*load)
832*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax", "ebx"
833*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
834*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
835*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
836*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
837*053f45beSAndroid Build Coastguard Worker #endif
838*053f45beSAndroid Build Coastguard Worker 	);
839*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
840*053f45beSAndroid Build Coastguard Worker 	return 0;
841*053f45beSAndroid Build Coastguard Worker abort:
842*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
843*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
844*053f45beSAndroid Build Coastguard Worker 	return -1;
845*053f45beSAndroid Build Coastguard Worker cmpfail:
846*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
847*053f45beSAndroid Build Coastguard Worker 	return 1;
848*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
849*053f45beSAndroid Build Coastguard Worker error1:
850*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
851*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
852*053f45beSAndroid Build Coastguard Worker error2:
853*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
854*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
855*053f45beSAndroid Build Coastguard Worker #endif
856*053f45beSAndroid Build Coastguard Worker }
857*053f45beSAndroid Build Coastguard Worker 
858*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_addv(intptr_t * v,intptr_t count,int cpu)859*053f45beSAndroid Build Coastguard Worker int rseq_addv(intptr_t *v, intptr_t count, int cpu)
860*053f45beSAndroid Build Coastguard Worker {
861*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
862*053f45beSAndroid Build Coastguard Worker 
863*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
864*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
865*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
866*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
867*053f45beSAndroid Build Coastguard Worker #endif
868*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
869*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
870*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
871*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
872*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
873*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
874*053f45beSAndroid Build Coastguard Worker #endif
875*053f45beSAndroid Build Coastguard Worker 		/* final store */
876*053f45beSAndroid Build Coastguard Worker 		"addl %[count], %[v]\n\t"
877*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
878*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
879*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
880*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
881*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
882*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
883*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
884*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
885*053f45beSAndroid Build Coastguard Worker 		  [count]		"ir" (count)
886*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax"
887*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
888*053f45beSAndroid Build Coastguard Worker 		: abort
889*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
890*053f45beSAndroid Build Coastguard Worker 		  , error1
891*053f45beSAndroid Build Coastguard Worker #endif
892*053f45beSAndroid Build Coastguard Worker 	);
893*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
894*053f45beSAndroid Build Coastguard Worker 	return 0;
895*053f45beSAndroid Build Coastguard Worker abort:
896*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
897*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
898*053f45beSAndroid Build Coastguard Worker 	return -1;
899*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
900*053f45beSAndroid Build Coastguard Worker error1:
901*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
902*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
903*053f45beSAndroid Build Coastguard Worker #endif
904*053f45beSAndroid Build Coastguard Worker }
905*053f45beSAndroid Build Coastguard Worker 
906*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trystorev_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)907*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
908*053f45beSAndroid Build Coastguard Worker 				 intptr_t *v2, intptr_t newv2,
909*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
910*053f45beSAndroid Build Coastguard Worker {
911*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
912*053f45beSAndroid Build Coastguard Worker 
913*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
914*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
915*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
916*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
917*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
918*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
919*053f45beSAndroid Build Coastguard Worker #endif
920*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
921*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
922*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
923*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
924*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %[expect]\n\t"
925*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
926*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
927*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
928*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
929*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %[expect]\n\t"
930*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error2]\n\t"
931*053f45beSAndroid Build Coastguard Worker #endif
932*053f45beSAndroid Build Coastguard Worker 		/* try store */
933*053f45beSAndroid Build Coastguard Worker 		"movl %[newv2], %%eax\n\t"
934*053f45beSAndroid Build Coastguard Worker 		"movl %%eax, %[v2]\n\t"
935*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
936*053f45beSAndroid Build Coastguard Worker 		/* final store */
937*053f45beSAndroid Build Coastguard Worker 		"movl %[newv], %[v]\n\t"
938*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
939*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
940*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
941*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
942*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
943*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
944*053f45beSAndroid Build Coastguard Worker 		  /* try store input */
945*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
946*053f45beSAndroid Build Coastguard Worker 		  [newv2]		"m" (newv2),
947*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
948*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
949*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
950*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
951*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax"
952*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
953*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
954*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
955*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
956*053f45beSAndroid Build Coastguard Worker #endif
957*053f45beSAndroid Build Coastguard Worker 	);
958*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
959*053f45beSAndroid Build Coastguard Worker 	return 0;
960*053f45beSAndroid Build Coastguard Worker abort:
961*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
962*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
963*053f45beSAndroid Build Coastguard Worker 	return -1;
964*053f45beSAndroid Build Coastguard Worker cmpfail:
965*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
966*053f45beSAndroid Build Coastguard Worker 	return 1;
967*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
968*053f45beSAndroid Build Coastguard Worker error1:
969*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
970*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
971*053f45beSAndroid Build Coastguard Worker error2:
972*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
973*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
974*053f45beSAndroid Build Coastguard Worker #endif
975*053f45beSAndroid Build Coastguard Worker }
976*053f45beSAndroid Build Coastguard Worker 
977*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trystorev_storev_release(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)978*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
979*053f45beSAndroid Build Coastguard Worker 					 intptr_t *v2, intptr_t newv2,
980*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
981*053f45beSAndroid Build Coastguard Worker {
982*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
983*053f45beSAndroid Build Coastguard Worker 
984*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
985*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
986*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
987*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
988*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
989*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
990*053f45beSAndroid Build Coastguard Worker #endif
991*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
992*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
993*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
994*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
995*053f45beSAndroid Build Coastguard Worker 		"movl %[expect], %%eax\n\t"
996*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %%eax\n\t"
997*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
998*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
999*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1000*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
1001*053f45beSAndroid Build Coastguard Worker 		"movl %[expect], %%eax\n\t"
1002*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %%eax\n\t"
1003*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error2]\n\t"
1004*053f45beSAndroid Build Coastguard Worker #endif
1005*053f45beSAndroid Build Coastguard Worker 		/* try store */
1006*053f45beSAndroid Build Coastguard Worker 		"movl %[newv2], %[v2]\n\t"
1007*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
1008*053f45beSAndroid Build Coastguard Worker 		"lock; addl $0,-128(%%esp)\n\t"
1009*053f45beSAndroid Build Coastguard Worker 		/* final store */
1010*053f45beSAndroid Build Coastguard Worker 		"movl %[newv], %[v]\n\t"
1011*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
1012*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
1013*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
1014*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
1015*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
1016*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
1017*053f45beSAndroid Build Coastguard Worker 		  /* try store input */
1018*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
1019*053f45beSAndroid Build Coastguard Worker 		  [newv2]		"r" (newv2),
1020*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
1021*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
1022*053f45beSAndroid Build Coastguard Worker 		  [expect]		"m" (expect),
1023*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
1024*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax"
1025*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
1026*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
1027*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1028*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
1029*053f45beSAndroid Build Coastguard Worker #endif
1030*053f45beSAndroid Build Coastguard Worker 	);
1031*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1032*053f45beSAndroid Build Coastguard Worker 	return 0;
1033*053f45beSAndroid Build Coastguard Worker abort:
1034*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1035*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
1036*053f45beSAndroid Build Coastguard Worker 	return -1;
1037*053f45beSAndroid Build Coastguard Worker cmpfail:
1038*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1039*053f45beSAndroid Build Coastguard Worker 	return 1;
1040*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1041*053f45beSAndroid Build Coastguard Worker error1:
1042*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1043*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
1044*053f45beSAndroid Build Coastguard Worker error2:
1045*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1046*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
1047*053f45beSAndroid Build Coastguard Worker #endif
1048*053f45beSAndroid Build Coastguard Worker 
1049*053f45beSAndroid Build Coastguard Worker }
1050*053f45beSAndroid Build Coastguard Worker 
1051*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t expect2,intptr_t newv,int cpu)1052*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
1053*053f45beSAndroid Build Coastguard Worker 			      intptr_t *v2, intptr_t expect2,
1054*053f45beSAndroid Build Coastguard Worker 			      intptr_t newv, int cpu)
1055*053f45beSAndroid Build Coastguard Worker {
1056*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
1057*053f45beSAndroid Build Coastguard Worker 
1058*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
1059*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
1060*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
1061*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1062*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
1063*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
1064*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
1065*053f45beSAndroid Build Coastguard Worker #endif
1066*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
1067*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
1068*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
1069*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
1070*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %[expect]\n\t"
1071*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
1072*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
1073*053f45beSAndroid Build Coastguard Worker 		"cmpl %[expect2], %[v2]\n\t"
1074*053f45beSAndroid Build Coastguard Worker 		"jnz %l[cmpfail]\n\t"
1075*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
1076*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1077*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
1078*053f45beSAndroid Build Coastguard Worker 		"cmpl %[v], %[expect]\n\t"
1079*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error2]\n\t"
1080*053f45beSAndroid Build Coastguard Worker 		"cmpl %[expect2], %[v2]\n\t"
1081*053f45beSAndroid Build Coastguard Worker 		"jnz %l[error3]\n\t"
1082*053f45beSAndroid Build Coastguard Worker #endif
1083*053f45beSAndroid Build Coastguard Worker 		"movl %[newv], %%eax\n\t"
1084*053f45beSAndroid Build Coastguard Worker 		/* final store */
1085*053f45beSAndroid Build Coastguard Worker 		"movl %%eax, %[v]\n\t"
1086*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
1087*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
1088*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
1089*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
1090*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
1091*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
1092*053f45beSAndroid Build Coastguard Worker 		  /* cmp2 input */
1093*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
1094*053f45beSAndroid Build Coastguard Worker 		  [expect2]		"r" (expect2),
1095*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
1096*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
1097*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
1098*053f45beSAndroid Build Coastguard Worker 		  [newv]		"m" (newv)
1099*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax"
1100*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
1101*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
1102*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1103*053f45beSAndroid Build Coastguard Worker 		  , error1, error2, error3
1104*053f45beSAndroid Build Coastguard Worker #endif
1105*053f45beSAndroid Build Coastguard Worker 	);
1106*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1107*053f45beSAndroid Build Coastguard Worker 	return 0;
1108*053f45beSAndroid Build Coastguard Worker abort:
1109*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1110*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
1111*053f45beSAndroid Build Coastguard Worker 	return -1;
1112*053f45beSAndroid Build Coastguard Worker cmpfail:
1113*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1114*053f45beSAndroid Build Coastguard Worker 	return 1;
1115*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1116*053f45beSAndroid Build Coastguard Worker error1:
1117*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1118*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
1119*053f45beSAndroid Build Coastguard Worker error2:
1120*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1121*053f45beSAndroid Build Coastguard Worker 	rseq_bug("1st expected value comparison failed");
1122*053f45beSAndroid Build Coastguard Worker error3:
1123*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1124*053f45beSAndroid Build Coastguard Worker 	rseq_bug("2nd expected value comparison failed");
1125*053f45beSAndroid Build Coastguard Worker #endif
1126*053f45beSAndroid Build Coastguard Worker }
1127*053f45beSAndroid Build Coastguard Worker 
1128*053f45beSAndroid Build Coastguard Worker /* TODO: implement a faster memcpy. */
1129*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trymemcpy_storev(intptr_t * v,intptr_t expect,void * dst,void * src,size_t len,intptr_t newv,int cpu)1130*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
1131*053f45beSAndroid Build Coastguard Worker 				 void *dst, void *src, size_t len,
1132*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
1133*053f45beSAndroid Build Coastguard Worker {
1134*053f45beSAndroid Build Coastguard Worker 	uint32_t rseq_scratch[3];
1135*053f45beSAndroid Build Coastguard Worker 
1136*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
1137*053f45beSAndroid Build Coastguard Worker 
1138*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
1139*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
1140*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
1141*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1142*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
1143*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
1144*053f45beSAndroid Build Coastguard Worker #endif
1145*053f45beSAndroid Build Coastguard Worker 		"movl %[src], %[rseq_scratch0]\n\t"
1146*053f45beSAndroid Build Coastguard Worker 		"movl %[dst], %[rseq_scratch1]\n\t"
1147*053f45beSAndroid Build Coastguard Worker 		"movl %[len], %[rseq_scratch2]\n\t"
1148*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
1149*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
1150*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
1151*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
1152*053f45beSAndroid Build Coastguard Worker 		"movl %[expect], %%eax\n\t"
1153*053f45beSAndroid Build Coastguard Worker 		"cmpl %%eax, %[v]\n\t"
1154*053f45beSAndroid Build Coastguard Worker 		"jnz 5f\n\t"
1155*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
1156*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1157*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
1158*053f45beSAndroid Build Coastguard Worker 		"movl %[expect], %%eax\n\t"
1159*053f45beSAndroid Build Coastguard Worker 		"cmpl %%eax, %[v]\n\t"
1160*053f45beSAndroid Build Coastguard Worker 		"jnz 7f\n\t"
1161*053f45beSAndroid Build Coastguard Worker #endif
1162*053f45beSAndroid Build Coastguard Worker 		/* try memcpy */
1163*053f45beSAndroid Build Coastguard Worker 		"test %[len], %[len]\n\t" \
1164*053f45beSAndroid Build Coastguard Worker 		"jz 333f\n\t" \
1165*053f45beSAndroid Build Coastguard Worker 		"222:\n\t" \
1166*053f45beSAndroid Build Coastguard Worker 		"movb (%[src]), %%al\n\t" \
1167*053f45beSAndroid Build Coastguard Worker 		"movb %%al, (%[dst])\n\t" \
1168*053f45beSAndroid Build Coastguard Worker 		"inc %[src]\n\t" \
1169*053f45beSAndroid Build Coastguard Worker 		"inc %[dst]\n\t" \
1170*053f45beSAndroid Build Coastguard Worker 		"dec %[len]\n\t" \
1171*053f45beSAndroid Build Coastguard Worker 		"jnz 222b\n\t" \
1172*053f45beSAndroid Build Coastguard Worker 		"333:\n\t" \
1173*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
1174*053f45beSAndroid Build Coastguard Worker 		"movl %[newv], %%eax\n\t"
1175*053f45beSAndroid Build Coastguard Worker 		/* final store */
1176*053f45beSAndroid Build Coastguard Worker 		"movl %%eax, %[v]\n\t"
1177*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
1178*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
1179*053f45beSAndroid Build Coastguard Worker 		/* teardown */
1180*053f45beSAndroid Build Coastguard Worker 		"movl %[rseq_scratch2], %[len]\n\t"
1181*053f45beSAndroid Build Coastguard Worker 		"movl %[rseq_scratch1], %[dst]\n\t"
1182*053f45beSAndroid Build Coastguard Worker 		"movl %[rseq_scratch0], %[src]\n\t"
1183*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4,
1184*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1185*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1186*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1187*053f45beSAndroid Build Coastguard Worker 			abort)
1188*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(5,
1189*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1190*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1191*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1192*053f45beSAndroid Build Coastguard Worker 			cmpfail)
1193*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1194*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(6,
1195*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1196*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1197*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1198*053f45beSAndroid Build Coastguard Worker 			error1)
1199*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(7,
1200*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1201*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1202*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1203*053f45beSAndroid Build Coastguard Worker 			error2)
1204*053f45beSAndroid Build Coastguard Worker #endif
1205*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
1206*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
1207*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
1208*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
1209*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
1210*053f45beSAndroid Build Coastguard Worker 		  [expect]		"m" (expect),
1211*053f45beSAndroid Build Coastguard Worker 		  [newv]		"m" (newv),
1212*053f45beSAndroid Build Coastguard Worker 		  /* try memcpy input */
1213*053f45beSAndroid Build Coastguard Worker 		  [dst]			"r" (dst),
1214*053f45beSAndroid Build Coastguard Worker 		  [src]			"r" (src),
1215*053f45beSAndroid Build Coastguard Worker 		  [len]			"r" (len),
1216*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch0]	"m" (rseq_scratch[0]),
1217*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch1]	"m" (rseq_scratch[1]),
1218*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch2]	"m" (rseq_scratch[2])
1219*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax"
1220*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
1221*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
1222*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1223*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
1224*053f45beSAndroid Build Coastguard Worker #endif
1225*053f45beSAndroid Build Coastguard Worker 	);
1226*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1227*053f45beSAndroid Build Coastguard Worker 	return 0;
1228*053f45beSAndroid Build Coastguard Worker abort:
1229*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1230*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
1231*053f45beSAndroid Build Coastguard Worker 	return -1;
1232*053f45beSAndroid Build Coastguard Worker cmpfail:
1233*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1234*053f45beSAndroid Build Coastguard Worker 	return 1;
1235*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1236*053f45beSAndroid Build Coastguard Worker error1:
1237*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1238*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
1239*053f45beSAndroid Build Coastguard Worker error2:
1240*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1241*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
1242*053f45beSAndroid Build Coastguard Worker #endif
1243*053f45beSAndroid Build Coastguard Worker }
1244*053f45beSAndroid Build Coastguard Worker 
1245*053f45beSAndroid Build Coastguard Worker /* TODO: implement a faster memcpy. */
1246*053f45beSAndroid Build Coastguard Worker static inline __attribute__((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)1247*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
1248*053f45beSAndroid Build Coastguard Worker 					 void *dst, void *src, size_t len,
1249*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
1250*053f45beSAndroid Build Coastguard Worker {
1251*053f45beSAndroid Build Coastguard Worker 	uint32_t rseq_scratch[3];
1252*053f45beSAndroid Build Coastguard Worker 
1253*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
1254*053f45beSAndroid Build Coastguard Worker 
1255*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
1256*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
1257*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
1258*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1259*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
1260*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
1261*053f45beSAndroid Build Coastguard Worker #endif
1262*053f45beSAndroid Build Coastguard Worker 		"movl %[src], %[rseq_scratch0]\n\t"
1263*053f45beSAndroid Build Coastguard Worker 		"movl %[dst], %[rseq_scratch1]\n\t"
1264*053f45beSAndroid Build Coastguard Worker 		"movl %[len], %[rseq_scratch2]\n\t"
1265*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
1266*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
1267*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
1268*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
1269*053f45beSAndroid Build Coastguard Worker 		"movl %[expect], %%eax\n\t"
1270*053f45beSAndroid Build Coastguard Worker 		"cmpl %%eax, %[v]\n\t"
1271*053f45beSAndroid Build Coastguard Worker 		"jnz 5f\n\t"
1272*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
1273*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1274*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
1275*053f45beSAndroid Build Coastguard Worker 		"movl %[expect], %%eax\n\t"
1276*053f45beSAndroid Build Coastguard Worker 		"cmpl %%eax, %[v]\n\t"
1277*053f45beSAndroid Build Coastguard Worker 		"jnz 7f\n\t"
1278*053f45beSAndroid Build Coastguard Worker #endif
1279*053f45beSAndroid Build Coastguard Worker 		/* try memcpy */
1280*053f45beSAndroid Build Coastguard Worker 		"test %[len], %[len]\n\t" \
1281*053f45beSAndroid Build Coastguard Worker 		"jz 333f\n\t" \
1282*053f45beSAndroid Build Coastguard Worker 		"222:\n\t" \
1283*053f45beSAndroid Build Coastguard Worker 		"movb (%[src]), %%al\n\t" \
1284*053f45beSAndroid Build Coastguard Worker 		"movb %%al, (%[dst])\n\t" \
1285*053f45beSAndroid Build Coastguard Worker 		"inc %[src]\n\t" \
1286*053f45beSAndroid Build Coastguard Worker 		"inc %[dst]\n\t" \
1287*053f45beSAndroid Build Coastguard Worker 		"dec %[len]\n\t" \
1288*053f45beSAndroid Build Coastguard Worker 		"jnz 222b\n\t" \
1289*053f45beSAndroid Build Coastguard Worker 		"333:\n\t" \
1290*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
1291*053f45beSAndroid Build Coastguard Worker 		"lock; addl $0,-128(%%esp)\n\t"
1292*053f45beSAndroid Build Coastguard Worker 		"movl %[newv], %%eax\n\t"
1293*053f45beSAndroid Build Coastguard Worker 		/* final store */
1294*053f45beSAndroid Build Coastguard Worker 		"movl %%eax, %[v]\n\t"
1295*053f45beSAndroid Build Coastguard Worker 		"2:\n\t"
1296*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
1297*053f45beSAndroid Build Coastguard Worker 		/* teardown */
1298*053f45beSAndroid Build Coastguard Worker 		"movl %[rseq_scratch2], %[len]\n\t"
1299*053f45beSAndroid Build Coastguard Worker 		"movl %[rseq_scratch1], %[dst]\n\t"
1300*053f45beSAndroid Build Coastguard Worker 		"movl %[rseq_scratch0], %[src]\n\t"
1301*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4,
1302*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1303*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1304*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1305*053f45beSAndroid Build Coastguard Worker 			abort)
1306*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(5,
1307*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1308*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1309*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1310*053f45beSAndroid Build Coastguard Worker 			cmpfail)
1311*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1312*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(6,
1313*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1314*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1315*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1316*053f45beSAndroid Build Coastguard Worker 			error1)
1317*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_CMPFAIL(7,
1318*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch2], %[len]\n\t"
1319*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch1], %[dst]\n\t"
1320*053f45beSAndroid Build Coastguard Worker 			"movl %[rseq_scratch0], %[src]\n\t",
1321*053f45beSAndroid Build Coastguard Worker 			error2)
1322*053f45beSAndroid Build Coastguard Worker #endif
1323*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
1324*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
1325*053f45beSAndroid Build Coastguard Worker 		  [rseq_offset]		"r" (rseq_offset),
1326*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
1327*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
1328*053f45beSAndroid Build Coastguard Worker 		  [expect]		"m" (expect),
1329*053f45beSAndroid Build Coastguard Worker 		  [newv]		"m" (newv),
1330*053f45beSAndroid Build Coastguard Worker 		  /* try memcpy input */
1331*053f45beSAndroid Build Coastguard Worker 		  [dst]			"r" (dst),
1332*053f45beSAndroid Build Coastguard Worker 		  [src]			"r" (src),
1333*053f45beSAndroid Build Coastguard Worker 		  [len]			"r" (len),
1334*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch0]	"m" (rseq_scratch[0]),
1335*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch1]	"m" (rseq_scratch[1]),
1336*053f45beSAndroid Build Coastguard Worker 		  [rseq_scratch2]	"m" (rseq_scratch[2])
1337*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "eax"
1338*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
1339*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
1340*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1341*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
1342*053f45beSAndroid Build Coastguard Worker #endif
1343*053f45beSAndroid Build Coastguard Worker 	);
1344*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1345*053f45beSAndroid Build Coastguard Worker 	return 0;
1346*053f45beSAndroid Build Coastguard Worker abort:
1347*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1348*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
1349*053f45beSAndroid Build Coastguard Worker 	return -1;
1350*053f45beSAndroid Build Coastguard Worker cmpfail:
1351*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1352*053f45beSAndroid Build Coastguard Worker 	return 1;
1353*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
1354*053f45beSAndroid Build Coastguard Worker error1:
1355*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1356*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
1357*053f45beSAndroid Build Coastguard Worker error2:
1358*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
1359*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
1360*053f45beSAndroid Build Coastguard Worker #endif
1361*053f45beSAndroid Build Coastguard Worker }
1362*053f45beSAndroid Build Coastguard Worker 
1363*053f45beSAndroid Build Coastguard Worker #endif /* !RSEQ_SKIP_FASTPATH */
1364*053f45beSAndroid Build Coastguard Worker 
1365*053f45beSAndroid Build Coastguard Worker #endif
1366