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