Skip to content

Commit ea366dd

Browse files
posk-ioPeter Zijlstra
authored andcommitted
rseq/selftests,x86_64: Add rseq_offset_deref_addv()
This patch adds rseq_offset_deref_addv() function to tools/testing/selftests/rseq/rseq-x86.h, to be used in a selftest in the next patch in the patchset. Once an architecture adds support for this function they should define "RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV". Signed-off-by: Peter Oskolkov <posk@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://lkml.kernel.org/r/20200923233618.2572849-2-posk@google.com
1 parent 2a36ab7 commit ea366dd

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

tools/testing/selftests/rseq/rseq-x86.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,63 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
279279
#endif
280280
}
281281

282+
#define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
283+
284+
/*
285+
* pval = *(ptr+off)
286+
* *pval += inc;
287+
*/
288+
static inline __attribute__((always_inline))
289+
int rseq_offset_deref_addv(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
290+
{
291+
RSEQ_INJECT_C(9)
292+
293+
__asm__ __volatile__ goto (
294+
RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
295+
#ifdef RSEQ_COMPARE_TWICE
296+
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
297+
#endif
298+
/* Start rseq by storing table entry pointer into rseq_cs. */
299+
RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
300+
RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
301+
RSEQ_INJECT_ASM(3)
302+
#ifdef RSEQ_COMPARE_TWICE
303+
RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
304+
#endif
305+
/* get p+v */
306+
"movq %[ptr], %%rbx\n\t"
307+
"addq %[off], %%rbx\n\t"
308+
/* get pv */
309+
"movq (%%rbx), %%rcx\n\t"
310+
/* *pv += inc */
311+
"addq %[inc], (%%rcx)\n\t"
312+
"2:\n\t"
313+
RSEQ_INJECT_ASM(4)
314+
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
315+
: /* gcc asm goto does not allow outputs */
316+
: [cpu_id] "r" (cpu),
317+
[rseq_abi] "r" (&__rseq_abi),
318+
/* final store input */
319+
[ptr] "m" (*ptr),
320+
[off] "er" (off),
321+
[inc] "er" (inc)
322+
: "memory", "cc", "rax", "rbx", "rcx"
323+
RSEQ_INJECT_CLOBBER
324+
: abort
325+
#ifdef RSEQ_COMPARE_TWICE
326+
, error1
327+
#endif
328+
);
329+
return 0;
330+
abort:
331+
RSEQ_INJECT_FAILED
332+
return -1;
333+
#ifdef RSEQ_COMPARE_TWICE
334+
error1:
335+
rseq_bug("cpu_id comparison failed");
336+
#endif
337+
}
338+
282339
static inline __attribute__((always_inline))
283340
int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
284341
intptr_t *v2, intptr_t newv2,

0 commit comments

Comments
 (0)