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