]> Git Repo - J-linux.git/blob - tools/testing/selftests/rseq/rseq-arm-bits.h
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.git] / tools / testing / selftests / rseq / rseq-arm-bits.h
1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2 /*
3  * rseq-arm-bits.h
4  *
5  * (C) Copyright 2016-2022 - Mathieu Desnoyers <[email protected]>
6  */
7
8 #include "rseq-bits-template.h"
9
10 #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
11         (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
12
13 static inline __attribute__((always_inline))
14 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
15 {
16         RSEQ_INJECT_C(9)
17
18         __asm__ __volatile__ goto (
19                 RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
20                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
21 #ifdef RSEQ_COMPARE_TWICE
22                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
23                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
24 #endif
25                 /* Start rseq by storing table entry pointer into rseq_cs. */
26                 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
27                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
28                 RSEQ_INJECT_ASM(3)
29                 "ldr r0, %[v]\n\t"
30                 "cmp %[expect], r0\n\t"
31                 "bne %l[cmpfail]\n\t"
32                 RSEQ_INJECT_ASM(4)
33 #ifdef RSEQ_COMPARE_TWICE
34                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
35                 "ldr r0, %[v]\n\t"
36                 "cmp %[expect], r0\n\t"
37                 "bne %l[error2]\n\t"
38 #endif
39                 /* final store */
40                 "str %[newv], %[v]\n\t"
41                 "2:\n\t"
42                 RSEQ_INJECT_ASM(5)
43                 "b 5f\n\t"
44                 RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
45                 "5:\n\t"
46                 : /* gcc asm goto does not allow outputs */
47                 : [cpu_id]              "r" (cpu),
48                   [current_cpu_id]      "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
49                   [rseq_cs]             "m" (rseq_get_abi()->rseq_cs.arch.ptr),
50                   [v]                   "m" (*v),
51                   [expect]              "r" (expect),
52                   [newv]                "r" (newv)
53                   RSEQ_INJECT_INPUT
54                 : "r0", "memory", "cc"
55                   RSEQ_INJECT_CLOBBER
56                 : abort, cmpfail
57 #ifdef RSEQ_COMPARE_TWICE
58                   , error1, error2
59 #endif
60         );
61         rseq_after_asm_goto();
62         return 0;
63 abort:
64         rseq_after_asm_goto();
65         RSEQ_INJECT_FAILED
66         return -1;
67 cmpfail:
68         rseq_after_asm_goto();
69         return 1;
70 #ifdef RSEQ_COMPARE_TWICE
71 error1:
72         rseq_after_asm_goto();
73         rseq_bug("cpu_id comparison failed");
74 error2:
75         rseq_after_asm_goto();
76         rseq_bug("expected value comparison failed");
77 #endif
78 }
79
80 static inline __attribute__((always_inline))
81 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot,
82                                long voffp, intptr_t *load, int cpu)
83 {
84         RSEQ_INJECT_C(9)
85
86         __asm__ __volatile__ goto (
87                 RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
88                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
89 #ifdef RSEQ_COMPARE_TWICE
90                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
91                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
92 #endif
93                 /* Start rseq by storing table entry pointer into rseq_cs. */
94                 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
95                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
96                 RSEQ_INJECT_ASM(3)
97                 "ldr r0, %[v]\n\t"
98                 "cmp %[expectnot], r0\n\t"
99                 "beq %l[cmpfail]\n\t"
100                 RSEQ_INJECT_ASM(4)
101 #ifdef RSEQ_COMPARE_TWICE
102                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
103                 "ldr r0, %[v]\n\t"
104                 "cmp %[expectnot], r0\n\t"
105                 "beq %l[error2]\n\t"
106 #endif
107                 "str r0, %[load]\n\t"
108                 "add r0, %[voffp]\n\t"
109                 "ldr r0, [r0]\n\t"
110                 /* final store */
111                 "str r0, %[v]\n\t"
112                 "2:\n\t"
113                 RSEQ_INJECT_ASM(5)
114                 "b 5f\n\t"
115                 RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
116                 "5:\n\t"
117                 : /* gcc asm goto does not allow outputs */
118                 : [cpu_id]              "r" (cpu),
119                   [current_cpu_id]      "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
120                   [rseq_cs]             "m" (rseq_get_abi()->rseq_cs.arch.ptr),
121                   /* final store input */
122                   [v]                   "m" (*v),
123                   [expectnot]           "r" (expectnot),
124                   [voffp]               "Ir" (voffp),
125                   [load]                "m" (*load)
126                   RSEQ_INJECT_INPUT
127                 : "r0", "memory", "cc"
128                   RSEQ_INJECT_CLOBBER
129                 : abort, cmpfail
130 #ifdef RSEQ_COMPARE_TWICE
131                   , error1, error2
132 #endif
133         );
134         rseq_after_asm_goto();
135         return 0;
136 abort:
137         rseq_after_asm_goto();
138         RSEQ_INJECT_FAILED
139         return -1;
140 cmpfail:
141         rseq_after_asm_goto();
142         return 1;
143 #ifdef RSEQ_COMPARE_TWICE
144 error1:
145         rseq_after_asm_goto();
146         rseq_bug("cpu_id comparison failed");
147 error2:
148         rseq_after_asm_goto();
149         rseq_bug("expected value comparison failed");
150 #endif
151 }
152
153 static inline __attribute__((always_inline))
154 int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu)
155 {
156         RSEQ_INJECT_C(9)
157
158         __asm__ __volatile__ goto (
159                 RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
160 #ifdef RSEQ_COMPARE_TWICE
161                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
162 #endif
163                 /* Start rseq by storing table entry pointer into rseq_cs. */
164                 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
165                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
166                 RSEQ_INJECT_ASM(3)
167 #ifdef RSEQ_COMPARE_TWICE
168                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
169 #endif
170                 "ldr r0, %[v]\n\t"
171                 "add r0, %[count]\n\t"
172                 /* final store */
173                 "str r0, %[v]\n\t"
174                 "2:\n\t"
175                 RSEQ_INJECT_ASM(4)
176                 "b 5f\n\t"
177                 RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
178                 "5:\n\t"
179                 : /* gcc asm goto does not allow outputs */
180                 : [cpu_id]              "r" (cpu),
181                   [current_cpu_id]      "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
182                   [rseq_cs]             "m" (rseq_get_abi()->rseq_cs.arch.ptr),
183                   [v]                   "m" (*v),
184                   [count]               "Ir" (count)
185                   RSEQ_INJECT_INPUT
186                 : "r0", "memory", "cc"
187                   RSEQ_INJECT_CLOBBER
188                 : abort
189 #ifdef RSEQ_COMPARE_TWICE
190                   , error1
191 #endif
192         );
193         rseq_after_asm_goto();
194         return 0;
195 abort:
196         rseq_after_asm_goto();
197         RSEQ_INJECT_FAILED
198         return -1;
199 #ifdef RSEQ_COMPARE_TWICE
200 error1:
201         rseq_after_asm_goto();
202         rseq_bug("cpu_id comparison failed");
203 #endif
204 }
205
206 static inline __attribute__((always_inline))
207 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect,
208                               intptr_t *v2, intptr_t expect2,
209                               intptr_t newv, int cpu)
210 {
211         RSEQ_INJECT_C(9)
212
213         __asm__ __volatile__ goto (
214                 RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
215                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
216 #ifdef RSEQ_COMPARE_TWICE
217                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
218                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
219                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
220 #endif
221                 /* Start rseq by storing table entry pointer into rseq_cs. */
222                 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
223                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
224                 RSEQ_INJECT_ASM(3)
225                 "ldr r0, %[v]\n\t"
226                 "cmp %[expect], r0\n\t"
227                 "bne %l[cmpfail]\n\t"
228                 RSEQ_INJECT_ASM(4)
229                 "ldr r0, %[v2]\n\t"
230                 "cmp %[expect2], r0\n\t"
231                 "bne %l[cmpfail]\n\t"
232                 RSEQ_INJECT_ASM(5)
233 #ifdef RSEQ_COMPARE_TWICE
234                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
235                 "ldr r0, %[v]\n\t"
236                 "cmp %[expect], r0\n\t"
237                 "bne %l[error2]\n\t"
238                 "ldr r0, %[v2]\n\t"
239                 "cmp %[expect2], r0\n\t"
240                 "bne %l[error3]\n\t"
241 #endif
242                 /* final store */
243                 "str %[newv], %[v]\n\t"
244                 "2:\n\t"
245                 RSEQ_INJECT_ASM(6)
246                 "b 5f\n\t"
247                 RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
248                 "5:\n\t"
249                 : /* gcc asm goto does not allow outputs */
250                 : [cpu_id]              "r" (cpu),
251                   [current_cpu_id]      "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
252                   [rseq_cs]             "m" (rseq_get_abi()->rseq_cs.arch.ptr),
253                   /* cmp2 input */
254                   [v2]                  "m" (*v2),
255                   [expect2]             "r" (expect2),
256                   /* final store input */
257                   [v]                   "m" (*v),
258                   [expect]              "r" (expect),
259                   [newv]                "r" (newv)
260                   RSEQ_INJECT_INPUT
261                 : "r0", "memory", "cc"
262                   RSEQ_INJECT_CLOBBER
263                 : abort, cmpfail
264 #ifdef RSEQ_COMPARE_TWICE
265                   , error1, error2, error3
266 #endif
267         );
268         rseq_after_asm_goto();
269         return 0;
270 abort:
271         rseq_after_asm_goto();
272         RSEQ_INJECT_FAILED
273         return -1;
274 cmpfail:
275         rseq_after_asm_goto();
276         return 1;
277 #ifdef RSEQ_COMPARE_TWICE
278 error1:
279         rseq_after_asm_goto();
280         rseq_bug("cpu_id comparison failed");
281 error2:
282         rseq_after_asm_goto();
283         rseq_bug("1st expected value comparison failed");
284 error3:
285         rseq_after_asm_goto();
286         rseq_bug("2nd expected value comparison failed");
287 #endif
288 }
289
290 #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
291         (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
292
293 #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
294         (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
295
296 static inline __attribute__((always_inline))
297 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect,
298                                  intptr_t *v2, intptr_t newv2,
299                                  intptr_t newv, int cpu)
300 {
301         RSEQ_INJECT_C(9)
302
303         __asm__ __volatile__ goto (
304                 RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
305                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
306 #ifdef RSEQ_COMPARE_TWICE
307                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
308                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
309 #endif
310                 /* Start rseq by storing table entry pointer into rseq_cs. */
311                 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
312                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
313                 RSEQ_INJECT_ASM(3)
314                 "ldr r0, %[v]\n\t"
315                 "cmp %[expect], r0\n\t"
316                 "bne %l[cmpfail]\n\t"
317                 RSEQ_INJECT_ASM(4)
318 #ifdef RSEQ_COMPARE_TWICE
319                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
320                 "ldr r0, %[v]\n\t"
321                 "cmp %[expect], r0\n\t"
322                 "bne %l[error2]\n\t"
323 #endif
324                 /* try store */
325                 "str %[newv2], %[v2]\n\t"
326                 RSEQ_INJECT_ASM(5)
327 #ifdef RSEQ_TEMPLATE_MO_RELEASE
328                 "dmb\n\t"       /* full mb provides store-release */
329 #endif
330                 /* final store */
331                 "str %[newv], %[v]\n\t"
332                 "2:\n\t"
333                 RSEQ_INJECT_ASM(6)
334                 "b 5f\n\t"
335                 RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
336                 "5:\n\t"
337                 : /* gcc asm goto does not allow outputs */
338                 : [cpu_id]              "r" (cpu),
339                   [current_cpu_id]      "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
340                   [rseq_cs]             "m" (rseq_get_abi()->rseq_cs.arch.ptr),
341                   /* try store input */
342                   [v2]                  "m" (*v2),
343                   [newv2]               "r" (newv2),
344                   /* final store input */
345                   [v]                   "m" (*v),
346                   [expect]              "r" (expect),
347                   [newv]                "r" (newv)
348                   RSEQ_INJECT_INPUT
349                 : "r0", "memory", "cc"
350                   RSEQ_INJECT_CLOBBER
351                 : abort, cmpfail
352 #ifdef RSEQ_COMPARE_TWICE
353                   , error1, error2
354 #endif
355         );
356         rseq_after_asm_goto();
357         return 0;
358 abort:
359         rseq_after_asm_goto();
360         RSEQ_INJECT_FAILED
361         return -1;
362 cmpfail:
363         rseq_after_asm_goto();
364         return 1;
365 #ifdef RSEQ_COMPARE_TWICE
366 error1:
367         rseq_after_asm_goto();
368         rseq_bug("cpu_id comparison failed");
369 error2:
370         rseq_after_asm_goto();
371         rseq_bug("expected value comparison failed");
372 #endif
373 }
374
375
376 static inline __attribute__((always_inline))
377 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect,
378                                  void *dst, void *src, size_t len,
379                                  intptr_t newv, int cpu)
380 {
381         uint32_t rseq_scratch[3];
382
383         RSEQ_INJECT_C(9)
384
385         __asm__ __volatile__ goto (
386                 RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
387                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
388 #ifdef RSEQ_COMPARE_TWICE
389                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
390                 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
391 #endif
392                 "str %[src], %[rseq_scratch0]\n\t"
393                 "str %[dst], %[rseq_scratch1]\n\t"
394                 "str %[len], %[rseq_scratch2]\n\t"
395                 /* Start rseq by storing table entry pointer into rseq_cs. */
396                 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
397                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
398                 RSEQ_INJECT_ASM(3)
399                 "ldr r0, %[v]\n\t"
400                 "cmp %[expect], r0\n\t"
401                 "bne 5f\n\t"
402                 RSEQ_INJECT_ASM(4)
403 #ifdef RSEQ_COMPARE_TWICE
404                 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
405                 "ldr r0, %[v]\n\t"
406                 "cmp %[expect], r0\n\t"
407                 "bne 7f\n\t"
408 #endif
409                 /* try memcpy */
410                 "cmp %[len], #0\n\t" \
411                 "beq 333f\n\t" \
412                 "222:\n\t" \
413                 "ldrb %%r0, [%[src]]\n\t" \
414                 "strb %%r0, [%[dst]]\n\t" \
415                 "adds %[src], #1\n\t" \
416                 "adds %[dst], #1\n\t" \
417                 "subs %[len], #1\n\t" \
418                 "bne 222b\n\t" \
419                 "333:\n\t" \
420                 RSEQ_INJECT_ASM(5)
421 #ifdef RSEQ_TEMPLATE_MO_RELEASE
422                 "dmb\n\t"       /* full mb provides store-release */
423 #endif
424                 /* final store */
425                 "str %[newv], %[v]\n\t"
426                 "2:\n\t"
427                 RSEQ_INJECT_ASM(6)
428                 /* teardown */
429                 "ldr %[len], %[rseq_scratch2]\n\t"
430                 "ldr %[dst], %[rseq_scratch1]\n\t"
431                 "ldr %[src], %[rseq_scratch0]\n\t"
432                 "b 8f\n\t"
433                 RSEQ_ASM_DEFINE_ABORT(3, 4,
434                                       /* teardown */
435                                       "ldr %[len], %[rseq_scratch2]\n\t"
436                                       "ldr %[dst], %[rseq_scratch1]\n\t"
437                                       "ldr %[src], %[rseq_scratch0]\n\t",
438                                       abort, 1b, 2b, 4f)
439                 RSEQ_ASM_DEFINE_CMPFAIL(5,
440                                         /* teardown */
441                                         "ldr %[len], %[rseq_scratch2]\n\t"
442                                         "ldr %[dst], %[rseq_scratch1]\n\t"
443                                         "ldr %[src], %[rseq_scratch0]\n\t",
444                                         cmpfail)
445 #ifdef RSEQ_COMPARE_TWICE
446                 RSEQ_ASM_DEFINE_CMPFAIL(6,
447                                         /* teardown */
448                                         "ldr %[len], %[rseq_scratch2]\n\t"
449                                         "ldr %[dst], %[rseq_scratch1]\n\t"
450                                         "ldr %[src], %[rseq_scratch0]\n\t",
451                                         error1)
452                 RSEQ_ASM_DEFINE_CMPFAIL(7,
453                                         /* teardown */
454                                         "ldr %[len], %[rseq_scratch2]\n\t"
455                                         "ldr %[dst], %[rseq_scratch1]\n\t"
456                                         "ldr %[src], %[rseq_scratch0]\n\t",
457                                         error2)
458 #endif
459                 "8:\n\t"
460                 : /* gcc asm goto does not allow outputs */
461                 : [cpu_id]              "r" (cpu),
462                   [current_cpu_id]      "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
463                   [rseq_cs]             "m" (rseq_get_abi()->rseq_cs.arch.ptr),
464                   /* final store input */
465                   [v]                   "m" (*v),
466                   [expect]              "r" (expect),
467                   [newv]                "r" (newv),
468                   /* try memcpy input */
469                   [dst]                 "r" (dst),
470                   [src]                 "r" (src),
471                   [len]                 "r" (len),
472                   [rseq_scratch0]       "m" (rseq_scratch[0]),
473                   [rseq_scratch1]       "m" (rseq_scratch[1]),
474                   [rseq_scratch2]       "m" (rseq_scratch[2])
475                   RSEQ_INJECT_INPUT
476                 : "r0", "memory", "cc"
477                   RSEQ_INJECT_CLOBBER
478                 : abort, cmpfail
479 #ifdef RSEQ_COMPARE_TWICE
480                   , error1, error2
481 #endif
482         );
483         rseq_after_asm_goto();
484         return 0;
485 abort:
486         rseq_after_asm_goto();
487         RSEQ_INJECT_FAILED
488         return -1;
489 cmpfail:
490         rseq_after_asm_goto();
491         return 1;
492 #ifdef RSEQ_COMPARE_TWICE
493 error1:
494         rseq_after_asm_goto();
495         rseq_bug("cpu_id comparison failed");
496 error2:
497         rseq_after_asm_goto();
498         rseq_bug("expected value comparison failed");
499 #endif
500 }
501
502 #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
503         (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
504
505 #include "rseq-bits-reset.h"
This page took 0.061217 seconds and 4 git commands to generate.