[RFC PATCH v2 05/11] selftests/rseq: Implement rseq numa node id field selftest
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Date: 2022-02-18 21:16:31
Also in:
lkml
Subsystem:
kernel selftest framework, restartable sequences support, the rest · Maintainers:
Shuah Khan, Shuah Khan, Mathieu Desnoyers, Peter Zijlstra, "Paul E. McKenney", Boqun Feng, Linus Torvalds
Test the NUMA node id extension rseq field. Compare it against the value returned by the getcpu(2) system call while pinned on a specific core. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> --- tools/testing/selftests/rseq/basic_test.c | 5 ++++ tools/testing/selftests/rseq/rseq-abi.h | 8 ++++++ tools/testing/selftests/rseq/rseq.c | 18 +++++++++++++ tools/testing/selftests/rseq/rseq.h | 31 +++++++++++++++++++++++ 4 files changed, 62 insertions(+)
diff --git a/tools/testing/selftests/rseq/basic_test.c b/tools/testing/selftests/rseq/basic_test.c
index d8efbfb89193..a49b88cb20a3 100644
--- a/tools/testing/selftests/rseq/basic_test.c
+++ b/tools/testing/selftests/rseq/basic_test.c@@ -22,6 +22,8 @@ void test_cpu_pointer(void) CPU_ZERO(&test_affinity); for (i = 0; i < CPU_SETSIZE; i++) { if (CPU_ISSET(i, &affinity)) { + int node; + CPU_SET(i, &test_affinity); sched_setaffinity(0, sizeof(test_affinity), &test_affinity);
@@ -29,6 +31,9 @@ void test_cpu_pointer(void) assert(rseq_current_cpu() == i); assert(rseq_current_cpu_raw() == i); assert(rseq_cpu_start() == i); + node = rseq_fallback_current_node(); + assert(rseq_current_node() == node); + assert(rseq_current_node_raw() == node); CPU_CLR(i, &test_affinity); } }
diff --git a/tools/testing/selftests/rseq/rseq-abi.h b/tools/testing/selftests/rseq/rseq-abi.h
index 00ac846d85b0..a1faa9162d52 100644
--- a/tools/testing/selftests/rseq/rseq-abi.h
+++ b/tools/testing/selftests/rseq/rseq-abi.h@@ -147,6 +147,14 @@ struct rseq_abi { */ __u32 flags; + /* + * Restartable sequences node_id field. Updated by the kernel. Read by + * user-space with single-copy atomicity semantics. This field should + * only be read by the thread which registered this data structure. + * Aligned on 32-bit. Contains the current NUMA node ID. + */ + __u32 node_id; + /* * Flexible array member at end of structure, after last feature field. */
diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c
index 506f2b17aea6..470fc0f73e22 100644
--- a/tools/testing/selftests/rseq/rseq.c
+++ b/tools/testing/selftests/rseq/rseq.c@@ -79,6 +79,11 @@ static int sys_rseq(struct rseq_abi *rseq_abi, uint32_t rseq_len, return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig); } +static int sys_getcpu(unsigned int *cpu, unsigned int *node) +{ + return syscall(__NR_getcpu, cpu, node, NULL); +} + int rseq_available(void) { int rc;
@@ -199,3 +204,16 @@ int32_t rseq_fallback_current_cpu(void) } return cpu; } + +int32_t rseq_fallback_current_node(void) +{ + uint32_t cpu_id, node_id; + int ret; + + ret = sys_getcpu(&cpu_id, &node_id); + if (ret) { + perror("sys_getcpu()"); + return ret; + } + return (int32_t) node_id; +}
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
index e73db2e82a11..4f1954cd12ff 100644
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h@@ -20,6 +20,15 @@ #include "rseq-abi.h" #include "compiler.h" +#ifndef rseq_sizeof_field +#define rseq_sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) +#endif + +#ifndef rseq_offsetofend +#define rseq_offsetofend(TYPE, MEMBER) \ + (offsetof(TYPE, MEMBER) + rseq_sizeof_field(TYPE, MEMBER)) +#endif + /* * Empty code injection macros, override when testing. * It is important to consider that the ASM injection macros need to be
@@ -123,6 +132,11 @@ int rseq_unregister_current_thread(void); */ int32_t rseq_fallback_current_cpu(void); +/* + * Restartable sequence fallback for reading the current node number. + */ +int32_t rseq_fallback_current_node(void); + /* * Values returned can be either the current CPU number, -1 (rseq is * uninitialized), or -2 (rseq initialization has failed).
@@ -132,6 +146,15 @@ static inline int32_t rseq_current_cpu_raw(void) return RSEQ_ACCESS_ONCE(rseq_get_abi()->cpu_id); } +/* + * Current NUMA node number. + */ +static inline uint32_t rseq_current_node_raw(void) +{ + assert((int) rseq_feature_size >= rseq_offsetofend(struct rseq_abi, node_id)); + return RSEQ_ACCESS_ONCE(rseq_get_abi()->node_id); +} + /* * Returns a possible CPU number, which is typically the current CPU. * The returned CPU number can be used to prepare for an rseq critical
@@ -158,6 +181,14 @@ static inline uint32_t rseq_current_cpu(void) return cpu; } +static inline uint32_t rseq_current_node(void) +{ + if (rseq_likely((int) rseq_feature_size >= rseq_offsetofend(struct rseq_abi, node_id))) + return rseq_current_node_raw(); + else + return rseq_fallback_current_node(); +} + static inline void rseq_clear_rseq_cs(void) { RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0);
--
2.17.1