Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9aa134cb authored by Mathieu Desnoyers's avatar Mathieu Desnoyers Committed by Greg Kroah-Hartman
Browse files

selftests/rseq: introduce own copy of rseq uapi header



commit 5c105d55a9dc9e01535116ccfc26e703168a574f upstream.

The Linux kernel rseq uapi header has a broken layout for the
rseq_cs.ptr field on 32-bit little endian architectures. The entire
rseq_cs.ptr field is planned for removal, leaving only the 64-bit
rseq_cs.ptr64 field available.

Both glibc and librseq use their own copy of the Linux kernel uapi
header, where they introduce proper union fields to access to the 32-bit
low order bits of the rseq_cs pointer on 32-bit architectures.

Introduce a copy of the Linux kernel uapi headers in the Linux kernel
selftests.

Signed-off-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20220124171253.22072-2-mathieu.desnoyers@efficios.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8417f447
Loading
Loading
Loading
Loading
+151 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
#ifndef _RSEQ_ABI_H
#define _RSEQ_ABI_H

/*
 * rseq-abi.h
 *
 * Restartable sequences system call API
 *
 * Copyright (c) 2015-2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
 */

#include <linux/types.h>
#include <asm/byteorder.h>

enum rseq_abi_cpu_id_state {
	RSEQ_ABI_CPU_ID_UNINITIALIZED			= -1,
	RSEQ_ABI_CPU_ID_REGISTRATION_FAILED		= -2,
};

enum rseq_abi_flags {
	RSEQ_ABI_FLAG_UNREGISTER = (1 << 0),
};

enum rseq_abi_cs_flags_bit {
	RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT	= 0,
	RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT	= 1,
	RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT	= 2,
};

enum rseq_abi_cs_flags {
	RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT	=
		(1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
	RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL	=
		(1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
	RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE	=
		(1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
};

/*
 * struct rseq_abi_cs is aligned on 4 * 8 bytes to ensure it is always
 * contained within a single cache-line. It is usually declared as
 * link-time constant data.
 */
struct rseq_abi_cs {
	/* Version of this structure. */
	__u32 version;
	/* enum rseq_abi_cs_flags */
	__u32 flags;
	__u64 start_ip;
	/* Offset from start_ip. */
	__u64 post_commit_offset;
	__u64 abort_ip;
} __attribute__((aligned(4 * sizeof(__u64))));

/*
 * struct rseq_abi is aligned on 4 * 8 bytes to ensure it is always
 * contained within a single cache-line.
 *
 * A single struct rseq_abi per thread is allowed.
 */
struct rseq_abi {
	/*
	 * Restartable sequences cpu_id_start 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. Always
	 * contains a value in the range of possible CPUs, although the
	 * value may not be the actual current CPU (e.g. if rseq is not
	 * initialized). This CPU number value should always be compared
	 * against the value of the cpu_id field before performing a rseq
	 * commit or returning a value read from a data structure indexed
	 * using the cpu_id_start value.
	 */
	__u32 cpu_id_start;
	/*
	 * Restartable sequences cpu_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. Values
	 * RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
	 * have a special semantic: the former means "rseq uninitialized",
	 * and latter means "rseq initialization failed". This value is
	 * meant to be read within rseq critical sections and compared
	 * with the cpu_id_start value previously read, before performing
	 * the commit instruction, or read and compared with the
	 * cpu_id_start value before returning a value loaded from a data
	 * structure indexed using the cpu_id_start value.
	 */
	__u32 cpu_id;
	/*
	 * Restartable sequences rseq_cs field.
	 *
	 * Contains NULL when no critical section is active for the current
	 * thread, or holds a pointer to the currently active struct rseq_cs.
	 *
	 * Updated by user-space, which sets the address of the currently
	 * active rseq_cs at the beginning of assembly instruction sequence
	 * block, and set to NULL by the kernel when it restarts an assembly
	 * instruction sequence block, as well as when the kernel detects that
	 * it is preempting or delivering a signal outside of the range
	 * targeted by the rseq_cs. Also needs to be set to NULL by user-space
	 * before reclaiming memory that contains the targeted struct rseq_cs.
	 *
	 * Read and set by the kernel. Set by user-space with single-copy
	 * atomicity semantics. This field should only be updated by the
	 * thread which registered this data structure. Aligned on 64-bit.
	 */
	union {
		__u64 ptr64;

		/*
		 * The "arch" field provides architecture accessor for
		 * the ptr field based on architecture pointer size and
		 * endianness.
		 */
		struct {
#ifdef __LP64__
			__u64 ptr;
#elif defined(__BYTE_ORDER) ? (__BYTE_ORDER == __BIG_ENDIAN) : defined(__BIG_ENDIAN)
			__u32 padding;		/* Initialized to zero. */
			__u32 ptr;
#else
			__u32 ptr;
			__u32 padding;		/* Initialized to zero. */
#endif
		} arch;
	} rseq_cs;

	/*
	 * Restartable sequences flags field.
	 *
	 * This field should only be updated by the thread which
	 * registered this data structure. Read by the kernel.
	 * Mainly used for single-stepping through rseq critical sections
	 * with debuggers.
	 *
	 * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT
	 *     Inhibit instruction sequence block restart on preemption
	 *     for this thread.
	 * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL
	 *     Inhibit instruction sequence block restart on signal
	 *     delivery for this thread.
	 * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE
	 *     Inhibit instruction sequence block restart on migration for
	 *     this thread.
	 */
	__u32 flags;
} __attribute__((aligned(4 * sizeof(__u64))));

#endif /* _RSEQ_ABI_H */
+7 −7
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@
#include "../kselftest.h"
#include "rseq.h"

__thread volatile struct rseq __rseq_abi = {
	.cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
__thread volatile struct rseq_abi __rseq_abi = {
	.cpu_id = RSEQ_ABI_CPU_ID_UNINITIALIZED,
};

/*
@@ -66,7 +66,7 @@ static void signal_restore(sigset_t oldset)
		abort();
}

static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len,
static int sys_rseq(volatile struct rseq_abi *rseq_abi, uint32_t rseq_len,
		    int flags, uint32_t sig)
{
	return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
@@ -86,13 +86,13 @@ int rseq_register_current_thread(void)
	}
	if (__rseq_refcount++)
		goto end;
	rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
	rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi), 0, RSEQ_SIG);
	if (!rc) {
		assert(rseq_current_cpu_raw() >= 0);
		goto end;
	}
	if (errno != EBUSY)
		__rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
		__rseq_abi.cpu_id = RSEQ_ABI_CPU_ID_REGISTRATION_FAILED;
	ret = -1;
	__rseq_refcount--;
end:
@@ -114,8 +114,8 @@ int rseq_unregister_current_thread(void)
	}
	if (--__rseq_refcount)
		goto end;
	rc = sys_rseq(&__rseq_abi, sizeof(struct rseq),
		      RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
	rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi),
		      RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
	if (!rc)
		goto end;
	__rseq_refcount = 1;
+3 −7
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/rseq.h>
#include "rseq-abi.h"

/*
 * Empty code injection macros, override when testing.
@@ -43,7 +43,7 @@
#define RSEQ_INJECT_FAILED
#endif

extern __thread volatile struct rseq __rseq_abi;
extern __thread volatile struct rseq_abi __rseq_abi;
extern int __rseq_handled;

#define rseq_likely(x)		__builtin_expect(!!(x), 1)
@@ -139,11 +139,7 @@ static inline uint32_t rseq_current_cpu(void)

static inline void rseq_clear_rseq_cs(void)
{
#ifdef __LP64__
	__rseq_abi.rseq_cs.ptr = 0;
#else
	__rseq_abi.rseq_cs.ptr.ptr32 = 0;
#endif
	__rseq_abi.rseq_cs.arch.ptr = 0;
}

/*