Commit 99babd04 authored by Mathieu Desnoyers's avatar Mathieu Desnoyers Committed by Peter Zijlstra

selftests/rseq: Implement rseq numa node id field selftest

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: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20221122203932.231377-7-mathieu.desnoyers@efficios.com
parent 03f5c027
...@@ -22,6 +22,8 @@ void test_cpu_pointer(void) ...@@ -22,6 +22,8 @@ void test_cpu_pointer(void)
CPU_ZERO(&test_affinity); CPU_ZERO(&test_affinity);
for (i = 0; i < CPU_SETSIZE; i++) { for (i = 0; i < CPU_SETSIZE; i++) {
if (CPU_ISSET(i, &affinity)) { if (CPU_ISSET(i, &affinity)) {
int node;
CPU_SET(i, &test_affinity); CPU_SET(i, &test_affinity);
sched_setaffinity(0, sizeof(test_affinity), sched_setaffinity(0, sizeof(test_affinity),
&test_affinity); &test_affinity);
...@@ -29,6 +31,8 @@ void test_cpu_pointer(void) ...@@ -29,6 +31,8 @@ void test_cpu_pointer(void)
assert(rseq_current_cpu() == i); assert(rseq_current_cpu() == i);
assert(rseq_current_cpu_raw() == i); assert(rseq_current_cpu_raw() == i);
assert(rseq_cpu_start() == i); assert(rseq_cpu_start() == i);
node = rseq_fallback_current_node();
assert(rseq_current_node_id() == node);
CPU_CLR(i, &test_affinity); CPU_CLR(i, &test_affinity);
} }
} }
......
...@@ -147,6 +147,14 @@ struct rseq_abi { ...@@ -147,6 +147,14 @@ struct rseq_abi {
*/ */
__u32 flags; __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. * Flexible array member at end of structure, after last feature field.
*/ */
......
...@@ -79,6 +79,11 @@ static int sys_rseq(struct rseq_abi *rseq_abi, uint32_t rseq_len, ...@@ -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); return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
} }
static int sys_getcpu(unsigned *cpu, unsigned *node)
{
return syscall(__NR_getcpu, cpu, node, NULL);
}
int rseq_available(void) int rseq_available(void)
{ {
int rc; int rc;
...@@ -201,3 +206,16 @@ int32_t rseq_fallback_current_cpu(void) ...@@ -201,3 +206,16 @@ int32_t rseq_fallback_current_cpu(void)
} }
return cpu; 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;
}
...@@ -20,6 +20,15 @@ ...@@ -20,6 +20,15 @@
#include "rseq-abi.h" #include "rseq-abi.h"
#include "compiler.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. * Empty code injection macros, override when testing.
* It is important to consider that the ASM injection macros need to be * It is important to consider that the ASM injection macros need to be
...@@ -128,6 +137,11 @@ int rseq_unregister_current_thread(void); ...@@ -128,6 +137,11 @@ int rseq_unregister_current_thread(void);
*/ */
int32_t rseq_fallback_current_cpu(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 * Values returned can be either the current CPU number, -1 (rseq is
* uninitialized), or -2 (rseq initialization has failed). * uninitialized), or -2 (rseq initialization has failed).
...@@ -163,6 +177,20 @@ static inline uint32_t rseq_current_cpu(void) ...@@ -163,6 +177,20 @@ static inline uint32_t rseq_current_cpu(void)
return cpu; return cpu;
} }
static inline bool rseq_node_id_available(void)
{
return (int) rseq_feature_size >= rseq_offsetofend(struct rseq_abi, node_id);
}
/*
* Current NUMA node number.
*/
static inline uint32_t rseq_current_node_id(void)
{
assert(rseq_node_id_available());
return RSEQ_ACCESS_ONCE(rseq_get_abi()->node_id);
}
static inline void rseq_clear_rseq_cs(void) static inline void rseq_clear_rseq_cs(void)
{ {
RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0); RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment