All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: Stafford Horne <shorne@gmail.com>, LKML <linux-kernel@vger.kernel.org>
Cc: Linux OpenRISC <linux-openrisc@vger.kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	"Paul E. McKenney" <paulmck@kernel.org>,
	Boqun Feng <boqun.feng@gmail.com>, Shuah Khan <shuah@kernel.org>,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH 3/3] rseq/selftests: Add support for OpenRISC
Date: Fri, 10 Jan 2025 11:16:53 -0500	[thread overview]
Message-ID: <cf78a480-e38f-496c-931c-cd889fb29d59@efficios.com> (raw)
In-Reply-To: <20250110102248.3295944-4-shorne@gmail.com>

On 2025-01-10 05:22, Stafford Horne wrote:
> Add support for OpenRISC in the rseq selftests.  OpenRISC is 32-bit
> only.
> 
> Tested this with:
> 
>      Compiler:  gcc version 14.2.0 (GCC)
>      Binutils:  GNU assembler version 2.43.1 (or1k-smh-linux-gnu) using BFD version (GNU Binutils) 2.43.1.20241207
>      Linux:     Linux buildroot 6.13.0-rc2-00005-g1fa73dd6c2d3-dirty #213 SMP Sat Dec 28 22:18:39 GMT 2024 openrisc GNU/Linux
>      Glibc:     2024-12-13 e4e49583d9 Stafford Horne   or1k: Update libm-test-ulps
> 
> Signed-off-by: Stafford Horne <shorne@gmail.com>

Thanks!

Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>

> ---
>   tools/testing/selftests/rseq/param_test.c     |  24 +
>   tools/testing/selftests/rseq/rseq-or1k-bits.h | 412 ++++++++++++++++++
>   .../selftests/rseq/rseq-or1k-thread-pointer.h |  13 +
>   tools/testing/selftests/rseq/rseq-or1k.h      | 181 ++++++++
>   .../selftests/rseq/rseq-thread-pointer.h      |   2 +
>   tools/testing/selftests/rseq/rseq.h           |   2 +
>   6 files changed, 634 insertions(+)
>   create mode 100644 tools/testing/selftests/rseq/rseq-or1k-bits.h
>   create mode 100644 tools/testing/selftests/rseq/rseq-or1k-thread-pointer.h
>   create mode 100644 tools/testing/selftests/rseq/rseq-or1k.h
> 
> diff --git a/tools/testing/selftests/rseq/param_test.c b/tools/testing/selftests/rseq/param_test.c
> index 2f37961240ca..05d03e679e06 100644
> --- a/tools/testing/selftests/rseq/param_test.c
> +++ b/tools/testing/selftests/rseq/param_test.c
> @@ -226,8 +226,32 @@ unsigned int yield_mod_cnt, nr_abort;
>   	"addi  " INJECT_ASM_REG "," INJECT_ASM_REG ", -1\n\t"	\
>   	"bnez " INJECT_ASM_REG ", 222b\n\t"			\
>   	"333:\n\t"
> +#elif defined(__or1k__)
>   
> +#define RSEQ_INJECT_INPUT \
> +	, [loop_cnt_1]"m"(loop_cnt[1]) \
> +	, [loop_cnt_2]"m"(loop_cnt[2]) \
> +	, [loop_cnt_3]"m"(loop_cnt[3]) \
> +	, [loop_cnt_4]"m"(loop_cnt[4]) \
> +	, [loop_cnt_5]"m"(loop_cnt[5]) \
> +	, [loop_cnt_6]"m"(loop_cnt[6])
>   
> +#define INJECT_ASM_REG	"r31"
> +
> +#define RSEQ_INJECT_CLOBBER \
> +	, INJECT_ASM_REG
> +
> +#define RSEQ_INJECT_ASM(n)					\
> +	"l.lwz   " INJECT_ASM_REG ", %[loop_cnt_" #n "]\n\t"	\
> +	"l.sfeqi " INJECT_ASM_REG ", 0\n\t"			\
> +	"l.bf 333f\n\t"						\
> +	" l.nop\n\t"						\
> +	"222:\n\t"						\
> +	"l.addi  " INJECT_ASM_REG "," INJECT_ASM_REG ", -1\n\t"	\
> +	"l.sfeqi " INJECT_ASM_REG ", 0\n\t"			\
> +	"l.bf 222f\n\t"						\
> +	" l.nop\n\t"						\
> +	"333:\n\t"
>   #else
>   #error unsupported target
>   #endif
> diff --git a/tools/testing/selftests/rseq/rseq-or1k-bits.h b/tools/testing/selftests/rseq/rseq-or1k-bits.h
> new file mode 100644
> index 000000000000..15d0e8200cd1
> --- /dev/null
> +++ b/tools/testing/selftests/rseq/rseq-or1k-bits.h
> @@ -0,0 +1,412 @@
> +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
> +
> +#include "rseq-bits-template.h"
> +
> +#if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
> +	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
> +
> +static inline __always_inline
> +int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv,
> +				int cpu)
> +{
> +	RSEQ_INJECT_C(9)
> +
> +	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
> +				  RSEQ_INJECT_ASM(3)
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
> +				  RSEQ_INJECT_ASM(4)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
> +				  RSEQ_INJECT_ASM(5)
> +				  RSEQ_ASM_DEFINE_ABORT(4, abort)
> +				  : /* gcc asm goto does not allow outputs */
> +				  : [cpu_id]		"r" (cpu),
> +				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
> +				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
> +				    [v]			"m" (*v),
> +				    [expect]		"r" (expect),
> +				    [newv]		"r" (newv)
> +				    RSEQ_INJECT_INPUT
> +				  : "memory", RSEQ_ASM_TMP_REG_1
> +				    RSEQ_INJECT_CLOBBER
> +				  : abort, cmpfail
> +#ifdef RSEQ_COMPARE_TWICE
> +				    , error1, error2
> +#endif
> +	);
> +
> +	return 0;
> +abort:
> +	RSEQ_INJECT_FAILED
> +	return -1;
> +cmpfail:
> +	return 1;
> +#ifdef RSEQ_COMPARE_TWICE
> +error1:
> +	rseq_bug("cpu_id comparison failed");
> +error2:
> +	rseq_bug("expected value comparison failed");
> +#endif
> +}
> +
> +static inline __always_inline
> +int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot,
> +			       off_t voffp, intptr_t *load, int cpu)
> +{
> +	RSEQ_INJECT_C(9)
> +
> +	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
> +				  RSEQ_INJECT_ASM(3)
> +				  RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[cmpfail]")
> +				  RSEQ_INJECT_ASM(4)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
> +				  RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_OP_R_LOAD(v)
> +				  RSEQ_ASM_OP_R_STORE(load)
> +				  RSEQ_ASM_OP_R_LOAD_OFF(voffp)
> +				  RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
> +				  RSEQ_INJECT_ASM(5)
> +				  RSEQ_ASM_DEFINE_ABORT(4, abort)
> +				  : /* gcc asm goto does not allow outputs */
> +				  : [cpu_id]		"r" (cpu),
> +				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
> +				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
> +				    [v]			"m" (*v),
> +				    [expectnot]		"r" (expectnot),
> +				    [load]		"m" (*load),
> +				    [voffp]		"Ir" (voffp)
> +				    RSEQ_INJECT_INPUT
> +				  : "memory", RSEQ_ASM_TMP_REG_1
> +				    RSEQ_INJECT_CLOBBER
> +				  : abort, cmpfail
> +#ifdef RSEQ_COMPARE_TWICE
> +				    , error1, error2
> +#endif
> +	);
> +	return 0;
> +abort:
> +	RSEQ_INJECT_FAILED
> +	return -1;
> +cmpfail:
> +	return 1;
> +#ifdef RSEQ_COMPARE_TWICE
> +error1:
> +	rseq_bug("cpu_id comparison failed");
> +error2:
> +	rseq_bug("expected value comparison failed");
> +#endif
> +}
> +
> +static inline __always_inline
> +int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu)
> +{
> +	RSEQ_INJECT_C(9)
> +
> +	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
> +#endif
> +				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
> +				  RSEQ_INJECT_ASM(3)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
> +#endif
> +				  RSEQ_ASM_OP_R_LOAD(v)
> +				  RSEQ_ASM_OP_R_ADD(count)
> +				  RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
> +				  RSEQ_INJECT_ASM(4)
> +				  RSEQ_ASM_DEFINE_ABORT(4, abort)
> +				  : /* gcc asm goto does not allow outputs */
> +				  : [cpu_id]		"r" (cpu),
> +				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
> +				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
> +				    [v]			"m" (*v),
> +				    [count]		"r" (count)
> +				    RSEQ_INJECT_INPUT
> +				  : "memory", RSEQ_ASM_TMP_REG_1
> +				    RSEQ_INJECT_CLOBBER
> +				  : abort
> +#ifdef RSEQ_COMPARE_TWICE
> +				    , error1
> +#endif
> +	);
> +	return 0;
> +abort:
> +	RSEQ_INJECT_FAILED
> +	return -1;
> +#ifdef RSEQ_COMPARE_TWICE
> +error1:
> +	rseq_bug("cpu_id comparison failed");
> +#endif
> +}
> +
> +static inline __always_inline
> +int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect,
> +			      intptr_t *v2, intptr_t expect2,
> +			      intptr_t newv, int cpu)
> +{
> +	RSEQ_INJECT_C(9)
> +
> +	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error3]")
> +#endif
> +				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
> +				  RSEQ_INJECT_ASM(3)
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
> +				  RSEQ_INJECT_ASM(4)
> +				  RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[cmpfail]")
> +				  RSEQ_INJECT_ASM(5)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
> +				  RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[error3]")
> +#endif
> +				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
> +				  RSEQ_INJECT_ASM(6)
> +				  RSEQ_ASM_DEFINE_ABORT(4, abort)
> +				  : /* gcc asm goto does not allow outputs */
> +				  : [cpu_id]		"r" (cpu),
> +				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
> +				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
> +				    [v]			"m" (*v),
> +				    [expect]		"r" (expect),
> +				    [v2]		"m" (*v2),
> +				    [expect2]		"r" (expect2),
> +				    [newv]		"r" (newv)
> +				    RSEQ_INJECT_INPUT
> +				  : "memory", RSEQ_ASM_TMP_REG_1
> +				    RSEQ_INJECT_CLOBBER
> +				  : abort, cmpfail
> +#ifdef RSEQ_COMPARE_TWICE
> +				    , error1, error2, error3
> +#endif
> +	);
> +
> +	return 0;
> +abort:
> +	RSEQ_INJECT_FAILED
> +	return -1;
> +cmpfail:
> +	return 1;
> +#ifdef RSEQ_COMPARE_TWICE
> +error1:
> +	rseq_bug("cpu_id comparison failed");
> +error2:
> +	rseq_bug("expected value comparison failed");
> +error3:
> +	rseq_bug("2nd expected value comparison failed");
> +#endif
> +}
> +
> +#define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
> +
> +/*
> + *   pval = *(ptr+off)
> + *  *pval += inc;
> + */
> +static inline __always_inline
> +int RSEQ_TEMPLATE_IDENTIFIER(rseq_offset_deref_addv)(intptr_t *ptr, off_t off, intptr_t inc,
> +				int cpu)
> +{
> +	RSEQ_INJECT_C(9)
> +
> +	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
> +#endif
> +				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
> +				  RSEQ_INJECT_ASM(3)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
> +#endif
> +				  RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, inc, 3)
> +				  RSEQ_INJECT_ASM(4)
> +				  RSEQ_ASM_DEFINE_ABORT(4, abort)
> +				  : /* gcc asm goto does not allow outputs */
> +				  : [cpu_id]		"r" (cpu),
> +				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
> +				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
> +				    [ptr]		"r" (ptr),
> +				    [off]		"r" (off),
> +				    [inc]		"r" (inc)
> +				    RSEQ_INJECT_INPUT
> +				  : "memory", RSEQ_ASM_TMP_REG_1
> +				    RSEQ_INJECT_CLOBBER
> +				  : abort
> +#ifdef RSEQ_COMPARE_TWICE
> +				    , error1
> +#endif
> +	);
> +	return 0;
> +abort:
> +	RSEQ_INJECT_FAILED
> +	return -1;
> +#ifdef RSEQ_COMPARE_TWICE
> +error1:
> +	rseq_bug("cpu_id comparison failed");
> +#endif
> +}
> +
> +#endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
> +	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
> +
> +#if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
> +	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
> +
> +static inline __always_inline
> +int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect,
> +				 intptr_t *v2, intptr_t newv2,
> +				 intptr_t newv, int cpu)
> +{
> +	RSEQ_INJECT_C(9)
> +
> +	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
> +				  RSEQ_INJECT_ASM(3)
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
> +				  RSEQ_INJECT_ASM(4)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_OP_STORE(v2, newv2)
> +				  RSEQ_INJECT_ASM(5)
> +#ifdef RSEQ_TEMPLATE_MO_RELEASE
> +				  RSEQ_ASM_OP_FINAL_STORE_RELEASE(v, newv, 3)
> +#else
> +				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
> +#endif
> +				  RSEQ_INJECT_ASM(6)
> +				  RSEQ_ASM_DEFINE_ABORT(4, abort)
> +				  : /* gcc asm goto does not allow outputs */
> +				  : [cpu_id]		"r" (cpu),
> +				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
> +				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
> +				    [expect]		"r" (expect),
> +				    [v]			"m" (*v),
> +				    [newv]		"r" (newv),
> +				    [v2]		"m" (*v2),
> +				    [newv2]		"r" (newv2)
> +				    RSEQ_INJECT_INPUT
> +				  : "memory", RSEQ_ASM_TMP_REG_1
> +				    RSEQ_INJECT_CLOBBER
> +				  : abort, cmpfail
> +#ifdef RSEQ_COMPARE_TWICE
> +				    , error1, error2
> +#endif
> +	);
> +
> +	return 0;
> +abort:
> +	RSEQ_INJECT_FAILED
> +	return -1;
> +cmpfail:
> +	return 1;
> +#ifdef RSEQ_COMPARE_TWICE
> +error1:
> +	rseq_bug("cpu_id comparison failed");
> +error2:
> +	rseq_bug("expected value comparison failed");
> +#endif
> +}
> +
> +static inline __always_inline
> +int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect,
> +				 void *dst, void *src, size_t len,
> +				 intptr_t newv, int cpu)
> +{
> +	RSEQ_INJECT_C(9)
> +	__asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
> +				  RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
> +				  RSEQ_INJECT_ASM(3)
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
> +				  RSEQ_INJECT_ASM(4)
> +#ifdef RSEQ_COMPARE_TWICE
> +				  RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
> +				  RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
> +#endif
> +				  RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
> +				  RSEQ_INJECT_ASM(5)
> +#ifdef RSEQ_TEMPLATE_MO_RELEASE
> +				  RSEQ_ASM_OP_FINAL_STORE_RELEASE(v, newv, 3)
> +#else
> +				  RSEQ_ASM_OP_FINAL_STORE(v, newv, 3)
> +#endif
> +				  RSEQ_INJECT_ASM(6)
> +				  RSEQ_ASM_DEFINE_ABORT(4, abort)
> +				  : /* gcc asm goto does not allow outputs */
> +				  : [cpu_id]		"r" (cpu),
> +				    [current_cpu_id]	"m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
> +				    [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
> +				    [expect]		"r" (expect),
> +				    [v]			"m" (*v),
> +				    [newv]		"r" (newv),
> +				    [dst]		"r" (dst),
> +				    [src]		"r" (src),
> +				    [len]		"r" (len)
> +				    RSEQ_INJECT_INPUT
> +				  : "memory", RSEQ_ASM_TMP_REG_1, RSEQ_ASM_TMP_REG_2,
> +				    RSEQ_ASM_TMP_REG_3, RSEQ_ASM_TMP_REG_4
> +				    RSEQ_INJECT_CLOBBER
> +				  : abort, cmpfail
> +#ifdef RSEQ_COMPARE_TWICE
> +				    , error1, error2
> +#endif
> +	);
> +
> +	return 0;
> +abort:
> +	RSEQ_INJECT_FAILED
> +	return -1;
> +cmpfail:
> +	return 1;
> +#ifdef RSEQ_COMPARE_TWICE
> +error1:
> +	rseq_bug("cpu_id comparison failed");
> +error2:
> +	rseq_bug("expected value comparison failed");
> +#endif
> +}
> +
> +#endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
> +	(defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
> +
> +#include "rseq-bits-reset.h"
> diff --git a/tools/testing/selftests/rseq/rseq-or1k-thread-pointer.h b/tools/testing/selftests/rseq/rseq-or1k-thread-pointer.h
> new file mode 100644
> index 000000000000..cda740f7aff3
> --- /dev/null
> +++ b/tools/testing/selftests/rseq/rseq-or1k-thread-pointer.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
> +#ifndef _RSEQ_OR1K_THREAD_POINTER
> +#define _RSEQ_OR1K_THREAD_POINTER
> +
> +static inline void *rseq_thread_pointer(void)
> +{
> +	void *__thread_register;
> +
> +	__asm__ ("l.or %0, r10, r0" : "=r" (__thread_register));
> +	return __thread_register;
> +}
> +
> +#endif
> diff --git a/tools/testing/selftests/rseq/rseq-or1k.h b/tools/testing/selftests/rseq/rseq-or1k.h
> new file mode 100644
> index 000000000000..9e78eebdf79a
> --- /dev/null
> +++ b/tools/testing/selftests/rseq/rseq-or1k.h
> @@ -0,0 +1,181 @@
> +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
> +
> +/*
> + * Select the instruction "l.nop 0x35" as the RSEQ_SIG.
> + */
> +#define RSEQ_SIG   0x15000035
> +
> +#define rseq_smp_mb()	__asm__ __volatile__ ("l.msync" ::: "memory")
> +#define rseq_smp_rmb()	rseq_smp_mb()
> +#define rseq_smp_wmb()	rseq_smp_mb()
> +#define RSEQ_ASM_TMP_REG_1	"r31"
> +#define RSEQ_ASM_TMP_REG_2	"r29"
> +#define RSEQ_ASM_TMP_REG_3	"r27"
> +#define RSEQ_ASM_TMP_REG_4	"r25"
> +
> +#define rseq_smp_load_acquire(p)					\
> +__extension__ ({							\
> +	rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p));	\
> +	rseq_smp_mb();							\
> +	____p1;								\
> +})
> +
> +#define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_rmb()
> +
> +#define rseq_smp_store_release(p, v)					\
> +do {									\
> +	rseq_smp_mb();							\
> +	RSEQ_WRITE_ONCE(*(p), v);					\
> +} while (0)
> +
> +#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip,	\
> +				post_commit_offset, abort_ip)		\
> +	".pushsection	__rseq_cs, \"aw\"\n"				\
> +	".balign	32\n"						\
> +	__rseq_str(label) ":\n"						\
> +	".long " __rseq_str(version) ", " __rseq_str(flags) "\n"	\
> +	".long 0x0, " __rseq_str(start_ip) ", "				\
> +		"0x0, " __rseq_str(post_commit_offset) ", "		\
> +		"0x0, " __rseq_str(abort_ip) "\n"			\
> +	".popsection\n\t"						\
> +	".pushsection __rseq_cs_ptr_array, \"aw\"\n"			\
> +	".long 0x0, " __rseq_str(label) "b\n"				\
> +	".popsection\n"
> +
> +#define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
> +	__RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,		 \
> +				((post_commit_ip) - (start_ip)), abort_ip)
> +
> +/*
> + * Exit points of a rseq critical section consist of all instructions outside
> + * of the critical section where a critical section can either branch to or
> + * reach through the normal course of its execution. The abort IP and the
> + * post-commit IP are already part of the __rseq_cs section and should not be
> + * explicitly defined as additional exit points. Knowing all exit points is
> + * useful to assist debuggers stepping over the critical section.
> + */
> +#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)			\
> +	".pushsection __rseq_exit_point_array, \"aw\"\n"		\
> +	".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n"	\
> +	".popsection\n"
> +
> +#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)		\
> +	RSEQ_INJECT_ASM(1)						\
> +	"l.movhi " RSEQ_ASM_TMP_REG_1 ", hi(" __rseq_str(cs_label) ")\n"\
> +	"l.ori   " RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1		\
> +		", lo(" __rseq_str(cs_label) ")\n"\
> +	"l.sw  %[" __rseq_str(rseq_cs) "], " RSEQ_ASM_TMP_REG_1 "\n"	\
> +	__rseq_str(label) ":\n"
> +
> +#define RSEQ_ASM_DEFINE_ABORT(label, abort_label)			\
> +	"l.j 222f\n"							\
> +	" l.nop\n"							\
> +	".balign	4\n"						\
> +	".long "	__rseq_str(RSEQ_SIG) "\n"			\
> +	__rseq_str(label) ":\n"						\
> +	"l.j %l[" __rseq_str(abort_label) "]\n"				\
> +	" l.nop\n"							\
> +	"222:\n"
> +
> +#define RSEQ_ASM_OP_STORE(var, value)					\
> +	"l.sw %[" __rseq_str(var) "], %[" __rseq_str(value) "]\n"
> +
> +#define RSEQ_ASM_OP_CMPEQ(var, expect, label)				\
> +	"l.lwz  " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"	\
> +	"l.sfne " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "]\n"	\
> +	"l.bf   " __rseq_str(label) "\n"				\
> +	" l.nop\n"
> +
> +#define RSEQ_ASM_OP_CMPNE(var, expect, label)				\
> +	"l.lwz  " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"	\
> +	"l.sfeq " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "]\n"	\
> +	"l.bf   " __rseq_str(label) "\n"				\
> +	" l.nop\n"
> +
> +#define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)		\
> +	RSEQ_INJECT_ASM(2)						\
> +	RSEQ_ASM_OP_CMPEQ(current_cpu_id, cpu_id, label)
> +
> +#define RSEQ_ASM_OP_R_LOAD(var)						\
> +	"l.lwz " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"
> +
> +#define RSEQ_ASM_OP_R_STORE(var)					\
> +	"l.sw %[" __rseq_str(var) "], " RSEQ_ASM_TMP_REG_1 "\n"
> +
> +#define RSEQ_ASM_OP_R_LOAD_OFF(offset)					\
> +	"l.lwz " RSEQ_ASM_TMP_REG_1 ", "				\
> +		"%[" __rseq_str(offset) "](" RSEQ_ASM_TMP_REG_1 ")\n"
> +
> +#define RSEQ_ASM_OP_R_ADD(count)					\
> +	"l.add " RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1		\
> +		", %[" __rseq_str(count) "]\n"
> +
> +#define RSEQ_ASM_OP_FINAL_STORE(var, value, post_commit_label)		\
> +	RSEQ_ASM_OP_STORE(var, value)					\
> +	__rseq_str(post_commit_label) ":\n"
> +
> +#define RSEQ_ASM_OP_FINAL_STORE_RELEASE(var, value, post_commit_label)	\
> +	"l.msync\n"							\
> +	RSEQ_ASM_OP_STORE(var, value)					\
> +	__rseq_str(post_commit_label) ":\n"
> +
> +#define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label)		\
> +	"l.sw %[" __rseq_str(var) "], " RSEQ_ASM_TMP_REG_1 "\n"		\
> +	__rseq_str(post_commit_label) ":\n"
> +
> +#define RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)				\
> +	"l.sfeq	%[" __rseq_str(len) "], r0\n"				\
> +	"l.bf 333f\n"							\
> +	" l.nop\n"							\
> +	"l.ori  " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(len) "], 0\n"	\
> +	"l.ori  " RSEQ_ASM_TMP_REG_2 ", %[" __rseq_str(src) "], 0\n"	\
> +	"l.ori  " RSEQ_ASM_TMP_REG_3 ", %[" __rseq_str(dst) "], 0\n"	\
> +	"222:\n"							\
> +	"l.lbz  " RSEQ_ASM_TMP_REG_4 ", 0(" RSEQ_ASM_TMP_REG_2 ")\n"	\
> +	"l.sb   0(" RSEQ_ASM_TMP_REG_3 "), " RSEQ_ASM_TMP_REG_4 "\n"	\
> +	"l.addi " RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1 ", -1\n"	\
> +	"l.addi " RSEQ_ASM_TMP_REG_2 ", " RSEQ_ASM_TMP_REG_2 ", 1\n"	\
> +	"l.addi " RSEQ_ASM_TMP_REG_3 ", " RSEQ_ASM_TMP_REG_3 ", 1\n"	\
> +	"l.sfne " RSEQ_ASM_TMP_REG_1 ", r0\n"				\
> +	"l.bf 222b\n"							\
> +	" l.nop\n"							\
> +	"333:\n"
> +
> +#define RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, inc, post_commit_label)	\
> +	"l.ori  " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(ptr) "], 0\n"	\
> +	RSEQ_ASM_OP_R_ADD(off)						\
> +	"l.lwz  " RSEQ_ASM_TMP_REG_1 ", 0(" RSEQ_ASM_TMP_REG_1 ")\n"	\
> +	RSEQ_ASM_OP_R_ADD(inc)						\
> +	__rseq_str(post_commit_label) ":\n"
> +
> +/* Per-cpu-id indexing. */
> +
> +#define RSEQ_TEMPLATE_CPU_ID
> +#define RSEQ_TEMPLATE_MO_RELAXED
> +#include "rseq-or1k-bits.h"
> +#undef RSEQ_TEMPLATE_MO_RELAXED
> +
> +#define RSEQ_TEMPLATE_MO_RELEASE
> +#include "rseq-or1k-bits.h"
> +#undef RSEQ_TEMPLATE_MO_RELEASE
> +#undef RSEQ_TEMPLATE_CPU_ID
> +
> +/* Per-mm-cid indexing. */
> +
> +#define RSEQ_TEMPLATE_MM_CID
> +#define RSEQ_TEMPLATE_MO_RELAXED
> +#include "rseq-or1k-bits.h"
> +#undef RSEQ_TEMPLATE_MO_RELAXED
> +
> +#define RSEQ_TEMPLATE_MO_RELEASE
> +#include "rseq-or1k-bits.h"
> +#undef RSEQ_TEMPLATE_MO_RELEASE
> +#undef RSEQ_TEMPLATE_MM_CID
> +
> +/* APIs which are not based on cpu ids. */
> +
> +#define RSEQ_TEMPLATE_CPU_ID_NONE
> +#define RSEQ_TEMPLATE_MO_RELAXED
> +#include "rseq-or1k-bits.h"
> +#undef RSEQ_TEMPLATE_MO_RELAXED
> +#undef RSEQ_TEMPLATE_CPU_ID_NONE
> diff --git a/tools/testing/selftests/rseq/rseq-thread-pointer.h b/tools/testing/selftests/rseq/rseq-thread-pointer.h
> index 977c25d758b2..3d5019307a1b 100644
> --- a/tools/testing/selftests/rseq/rseq-thread-pointer.h
> +++ b/tools/testing/selftests/rseq/rseq-thread-pointer.h
> @@ -12,6 +12,8 @@
>   #include "rseq-x86-thread-pointer.h"
>   #elif defined(__PPC__)
>   #include "rseq-ppc-thread-pointer.h"
> +#elif defined(__or1k__)
> +#include "rseq-or1k-thread-pointer.h"
>   #else
>   #include "rseq-generic-thread-pointer.h"
>   #endif
> diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
> index 4e217b620e0c..cbf114d5bb8a 100644
> --- a/tools/testing/selftests/rseq/rseq.h
> +++ b/tools/testing/selftests/rseq/rseq.h
> @@ -122,6 +122,8 @@ static inline struct rseq_abi *rseq_get_abi(void)
>   #include <rseq-s390.h>
>   #elif defined(__riscv)
>   #include <rseq-riscv.h>
> +#elif defined(__or1k__)
> +#include <rseq-or1k.h>
>   #else
>   #error unsupported target
>   #endif

-- 
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com


  reply	other threads:[~2025-01-10 16:16 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-10 10:22 [PATCH 0/3] Add OpenRISC restartable sequences support Stafford Horne
2025-01-10 10:22 ` Stafford Horne
2025-01-10 10:22 ` [PATCH 1/3] openrisc: Add HAVE_REGS_AND_STACK_ACCESS_API support Stafford Horne
2025-01-10 10:22   ` Stafford Horne
2025-01-10 10:22 ` [PATCH 2/3] openrisc: Add support for restartable sequences Stafford Horne
2025-01-10 10:22 ` [PATCH 3/3] rseq/selftests: Add support for OpenRISC Stafford Horne
2025-01-10 16:16   ` Mathieu Desnoyers [this message]
2025-01-13 22:58     ` Shuah Khan
2025-01-14 17:18       ` Stafford Horne

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cf78a480-e38f-496c-931c-cd889fb29d59@efficios.com \
    --to=mathieu.desnoyers@efficios.com \
    --cc=boqun.feng@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-openrisc@vger.kernel.org \
    --cc=paulmck@kernel.org \
    --cc=peterz@infradead.org \
    --cc=shorne@gmail.com \
    --cc=shuah@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.