summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/rseq
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/rseq')
-rw-r--r--tools/testing/selftests/rseq/Makefile6
-rw-r--r--tools/testing/selftests/rseq/compiler.h26
-rw-r--r--tools/testing/selftests/rseq/rseq-arm.h4
-rw-r--r--tools/testing/selftests/rseq/rseq-arm64.h58
-rw-r--r--tools/testing/selftests/rseq/rseq-mips.h4
-rw-r--r--tools/testing/selftests/rseq/rseq-ppc.h4
-rw-r--r--tools/testing/selftests/rseq/rseq-riscv.h6
-rw-r--r--tools/testing/selftests/rseq/rseq-s390.h4
-rw-r--r--tools/testing/selftests/rseq/rseq-x86.h4
-rw-r--r--tools/testing/selftests/rseq/rseq.c30
10 files changed, 97 insertions, 49 deletions
diff --git a/tools/testing/selftests/rseq/Makefile b/tools/testing/selftests/rseq/Makefile
index b357ba24af06..5a3432fceb58 100644
--- a/tools/testing/selftests/rseq/Makefile
+++ b/tools/testing/selftests/rseq/Makefile
@@ -4,8 +4,10 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
CLANG_FLAGS += -no-integrated-as
endif
+top_srcdir = ../../../..
+
CFLAGS += -O2 -Wall -g -I./ $(KHDR_INCLUDES) -L$(OUTPUT) -Wl,-rpath=./ \
- $(CLANG_FLAGS)
+ $(CLANG_FLAGS) -I$(top_srcdir)/tools/include
LDLIBS += -lpthread -ldl
# Own dependencies because we only want to build against 1st prerequisite, but
@@ -31,7 +33,7 @@ $(OUTPUT)/%: %.c $(TEST_GEN_PROGS_EXTENDED) rseq.h rseq-*.h
$(CC) $(CFLAGS) $< $(LDLIBS) -lrseq -o $@
$(OUTPUT)/basic_percpu_ops_mm_cid_test: basic_percpu_ops_test.c $(TEST_GEN_PROGS_EXTENDED) rseq.h rseq-*.h
- $(CC) $(CFLAGS) -DBUILDOPT_RSEQ_PERCPU_MM_CID_ID $< $(LDLIBS) -lrseq -o $@
+ $(CC) $(CFLAGS) -DBUILDOPT_RSEQ_PERCPU_MM_CID $< $(LDLIBS) -lrseq -o $@
$(OUTPUT)/param_test_benchmark: param_test.c $(TEST_GEN_PROGS_EXTENDED) \
rseq.h rseq-*.h
diff --git a/tools/testing/selftests/rseq/compiler.h b/tools/testing/selftests/rseq/compiler.h
index f47092bddeba..49d62fbd6dda 100644
--- a/tools/testing/selftests/rseq/compiler.h
+++ b/tools/testing/selftests/rseq/compiler.h
@@ -33,4 +33,30 @@
#define RSEQ_COMBINE_TOKENS(_tokena, _tokenb) \
RSEQ__COMBINE_TOKENS(_tokena, _tokenb)
+#ifdef __cplusplus
+#define rseq_unqual_scalar_typeof(x) \
+ std::remove_cv<std::remove_reference<decltype(x)>::type>::type
+#else
+#define rseq_scalar_type_to_expr(type) \
+ unsigned type: (unsigned type)0, \
+ signed type: (signed type)0
+
+/*
+ * Use C11 _Generic to express unqualified type from expression. This removes
+ * volatile qualifier from expression type.
+ */
+#define rseq_unqual_scalar_typeof(x) \
+ __typeof__( \
+ _Generic((x), \
+ char: (char)0, \
+ rseq_scalar_type_to_expr(char), \
+ rseq_scalar_type_to_expr(short), \
+ rseq_scalar_type_to_expr(int), \
+ rseq_scalar_type_to_expr(long), \
+ rseq_scalar_type_to_expr(long long), \
+ default: (x) \
+ ) \
+ )
+#endif
+
#endif /* RSEQ_COMPILER_H_ */
diff --git a/tools/testing/selftests/rseq/rseq-arm.h b/tools/testing/selftests/rseq/rseq-arm.h
index 8414fc3eac15..d887b3bbe257 100644
--- a/tools/testing/selftests/rseq/rseq-arm.h
+++ b/tools/testing/selftests/rseq/rseq-arm.h
@@ -66,7 +66,7 @@
#define rseq_smp_load_acquire(p) \
__extension__ ({ \
- __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
+ rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
rseq_smp_mb(); \
____p1; \
})
@@ -76,7 +76,7 @@ __extension__ ({ \
#define rseq_smp_store_release(p, v) \
do { \
rseq_smp_mb(); \
- RSEQ_WRITE_ONCE(*p, v); \
+ RSEQ_WRITE_ONCE(*(p), v); \
} while (0)
#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \
diff --git a/tools/testing/selftests/rseq/rseq-arm64.h b/tools/testing/selftests/rseq/rseq-arm64.h
index 85b90977e7e6..21e1626a7235 100644
--- a/tools/testing/selftests/rseq/rseq-arm64.h
+++ b/tools/testing/selftests/rseq/rseq-arm64.h
@@ -27,59 +27,61 @@
#define rseq_smp_load_acquire(p) \
__extension__ ({ \
- __typeof(*p) ____p1; \
- switch (sizeof(*p)) { \
+ union { rseq_unqual_scalar_typeof(*(p)) __val; char __c[sizeof(*(p))]; } __u; \
+ switch (sizeof(*(p))) { \
case 1: \
- asm volatile ("ldarb %w0, %1" \
- : "=r" (*(__u8 *)p) \
- : "Q" (*p) : "memory"); \
+ __asm__ __volatile__ ("ldarb %w0, %1" \
+ : "=r" (*(__u8 *)__u.__c) \
+ : "Q" (*(p)) : "memory"); \
break; \
case 2: \
- asm volatile ("ldarh %w0, %1" \
- : "=r" (*(__u16 *)p) \
- : "Q" (*p) : "memory"); \
+ __asm__ __volatile__ ("ldarh %w0, %1" \
+ : "=r" (*(__u16 *)__u.__c) \
+ : "Q" (*(p)) : "memory"); \
break; \
case 4: \
- asm volatile ("ldar %w0, %1" \
- : "=r" (*(__u32 *)p) \
- : "Q" (*p) : "memory"); \
+ __asm__ __volatile__ ("ldar %w0, %1" \
+ : "=r" (*(__u32 *)__u.__c) \
+ : "Q" (*(p)) : "memory"); \
break; \
case 8: \
- asm volatile ("ldar %0, %1" \
- : "=r" (*(__u64 *)p) \
- : "Q" (*p) : "memory"); \
+ __asm__ __volatile__ ("ldar %0, %1" \
+ : "=r" (*(__u64 *)__u.__c) \
+ : "Q" (*(p)) : "memory"); \
break; \
} \
- ____p1; \
+ (rseq_unqual_scalar_typeof(*(p)))__u.__val; \
})
#define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
#define rseq_smp_store_release(p, v) \
do { \
- switch (sizeof(*p)) { \
+ union { rseq_unqual_scalar_typeof(*(p)) __val; char __c[sizeof(*(p))]; } __u = \
+ { .__val = (rseq_unqual_scalar_typeof(*(p))) (v) }; \
+ switch (sizeof(*(p))) { \
case 1: \
- asm volatile ("stlrb %w1, %0" \
- : "=Q" (*p) \
- : "r" ((__u8)v) \
+ __asm__ __volatile__ ("stlrb %w1, %0" \
+ : "=Q" (*(p)) \
+ : "r" (*(__u8 *)__u.__c) \
: "memory"); \
break; \
case 2: \
- asm volatile ("stlrh %w1, %0" \
- : "=Q" (*p) \
- : "r" ((__u16)v) \
+ __asm__ __volatile__ ("stlrh %w1, %0" \
+ : "=Q" (*(p)) \
+ : "r" (*(__u16 *)__u.__c) \
: "memory"); \
break; \
case 4: \
- asm volatile ("stlr %w1, %0" \
- : "=Q" (*p) \
- : "r" ((__u32)v) \
+ __asm__ __volatile__ ("stlr %w1, %0" \
+ : "=Q" (*(p)) \
+ : "r" (*(__u32 *)__u.__c) \
: "memory"); \
break; \
case 8: \
- asm volatile ("stlr %1, %0" \
- : "=Q" (*p) \
- : "r" ((__u64)v) \
+ __asm__ __volatile__ ("stlr %1, %0" \
+ : "=Q" (*(p)) \
+ : "r" (*(__u64 *)__u.__c) \
: "memory"); \
break; \
} \
diff --git a/tools/testing/selftests/rseq/rseq-mips.h b/tools/testing/selftests/rseq/rseq-mips.h
index 50b950cf9585..42ef8e946693 100644
--- a/tools/testing/selftests/rseq/rseq-mips.h
+++ b/tools/testing/selftests/rseq/rseq-mips.h
@@ -45,7 +45,7 @@
#define rseq_smp_load_acquire(p) \
__extension__ ({ \
- __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
+ rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
rseq_smp_mb(); \
____p1; \
})
@@ -55,7 +55,7 @@ __extension__ ({ \
#define rseq_smp_store_release(p, v) \
do { \
rseq_smp_mb(); \
- RSEQ_WRITE_ONCE(*p, v); \
+ RSEQ_WRITE_ONCE(*(p), v); \
} while (0)
#if _MIPS_SZLONG == 64
diff --git a/tools/testing/selftests/rseq/rseq-ppc.h b/tools/testing/selftests/rseq/rseq-ppc.h
index dc9190facee9..57b160597189 100644
--- a/tools/testing/selftests/rseq/rseq-ppc.h
+++ b/tools/testing/selftests/rseq/rseq-ppc.h
@@ -23,7 +23,7 @@
#define rseq_smp_load_acquire(p) \
__extension__ ({ \
- __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
+ rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
rseq_smp_lwsync(); \
____p1; \
})
@@ -33,7 +33,7 @@ __extension__ ({ \
#define rseq_smp_store_release(p, v) \
do { \
rseq_smp_lwsync(); \
- RSEQ_WRITE_ONCE(*p, v); \
+ RSEQ_WRITE_ONCE(*(p), v); \
} while (0)
/*
diff --git a/tools/testing/selftests/rseq/rseq-riscv.h b/tools/testing/selftests/rseq/rseq-riscv.h
index 17932a79e066..37e598d0a365 100644
--- a/tools/testing/selftests/rseq/rseq-riscv.h
+++ b/tools/testing/selftests/rseq/rseq-riscv.h
@@ -36,8 +36,8 @@
#define rseq_smp_load_acquire(p) \
__extension__ ({ \
- __typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
- RISCV_FENCE(r, rw) \
+ rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
+ RISCV_FENCE(r, rw); \
____p1; \
})
@@ -46,7 +46,7 @@ __extension__ ({ \
#define rseq_smp_store_release(p, v) \
do { \
RISCV_FENCE(rw, w); \
- RSEQ_WRITE_ONCE(*(p), v); \
+ RSEQ_WRITE_ONCE(*(p), v); \
} while (0)
#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \
diff --git a/tools/testing/selftests/rseq/rseq-s390.h b/tools/testing/selftests/rseq/rseq-s390.h
index 46c92598acc7..33baaa9f9997 100644
--- a/tools/testing/selftests/rseq/rseq-s390.h
+++ b/tools/testing/selftests/rseq/rseq-s390.h
@@ -15,7 +15,7 @@
#define rseq_smp_load_acquire(p) \
__extension__ ({ \
- __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
+ rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
rseq_barrier(); \
____p1; \
})
@@ -25,7 +25,7 @@ __extension__ ({ \
#define rseq_smp_store_release(p, v) \
do { \
rseq_barrier(); \
- RSEQ_WRITE_ONCE(*p, v); \
+ RSEQ_WRITE_ONCE(*(p), v); \
} while (0)
#ifdef __s390x__
diff --git a/tools/testing/selftests/rseq/rseq-x86.h b/tools/testing/selftests/rseq/rseq-x86.h
index fb65ef54b0fb..a2aa428ba151 100644
--- a/tools/testing/selftests/rseq/rseq-x86.h
+++ b/tools/testing/selftests/rseq/rseq-x86.h
@@ -42,7 +42,7 @@
#define rseq_smp_load_acquire(p) \
__extension__ ({ \
- __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
+ rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
rseq_barrier(); \
____p1; \
})
@@ -52,7 +52,7 @@ __extension__ ({ \
#define rseq_smp_store_release(p, v) \
do { \
rseq_barrier(); \
- RSEQ_WRITE_ONCE(*p, v); \
+ RSEQ_WRITE_ONCE(*(p), v); \
} while (0)
#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c
index 4e4aa006004c..96e812bdf8a4 100644
--- a/tools/testing/selftests/rseq/rseq.c
+++ b/tools/testing/selftests/rseq/rseq.c
@@ -31,12 +31,22 @@
#include <sys/auxv.h>
#include <linux/auxvec.h>
+#include <linux/compiler.h>
+
#include "../kselftest.h"
#include "rseq.h"
-static const ptrdiff_t *libc_rseq_offset_p;
-static const unsigned int *libc_rseq_size_p;
-static const unsigned int *libc_rseq_flags_p;
+/*
+ * Define weak versions to play nice with binaries that are statically linked
+ * against a libc that doesn't support registering its own rseq.
+ */
+__weak ptrdiff_t __rseq_offset;
+__weak unsigned int __rseq_size;
+__weak unsigned int __rseq_flags;
+
+static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset;
+static const unsigned int *libc_rseq_size_p = &__rseq_size;
+static const unsigned int *libc_rseq_flags_p = &__rseq_flags;
/* Offset from the thread pointer to the rseq area. */
ptrdiff_t rseq_offset;
@@ -155,9 +165,17 @@ unsigned int get_rseq_feature_size(void)
static __attribute__((constructor))
void rseq_init(void)
{
- libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
- libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
- libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+ /*
+ * If the libc's registered rseq size isn't already valid, it may be
+ * because the binary is dynamically linked and not necessarily due to
+ * libc not having registered a restartable sequence. Try to find the
+ * symbols if that's the case.
+ */
+ if (!*libc_rseq_size_p) {
+ libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
+ libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
+ libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+ }
if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
*libc_rseq_size_p != 0) {
/* rseq registration owned by glibc */