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

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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,8 @@ 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_id() == node);
			CPU_CLR(i, &test_affinity);
		}
	}
+8 −0
Original line number Diff line number Diff line
@@ -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.
	 */
+18 −0
Original line number Diff line number Diff line
@@ -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 *cpu, unsigned *node)
{
	return syscall(__NR_getcpu, cpu, node, NULL);
}

int rseq_available(void)
{
	int rc;
@@ -201,3 +206,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;
}
+28 −0
Original line number Diff line number Diff line
@@ -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
@@ -128,6 +137,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).
@@ -163,6 +177,20 @@ static inline uint32_t rseq_current_cpu(void)
	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)
{
	RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0);