mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-27 13:10:29 +00:00
6c33b01843
This matches the data size initial-exec relocations use on most targets. Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
186 lines
6.6 KiB
C
186 lines
6.6 KiB
C
/* Restartable Sequences exported symbols. Linux header.
|
|
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef _SYS_RSEQ_H
|
|
#define _SYS_RSEQ_H 1
|
|
|
|
/* Architecture-specific rseq signature. */
|
|
#include <bits/rseq.h>
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <sys/cdefs.h>
|
|
#include <bits/endian.h>
|
|
|
|
#ifdef __has_include
|
|
# if __has_include ("linux/rseq.h")
|
|
# define __GLIBC_HAVE_KERNEL_RSEQ
|
|
# endif
|
|
#else
|
|
# include <linux/version.h>
|
|
# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0)
|
|
# define __GLIBC_HAVE_KERNEL_RSEQ
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef __GLIBC_HAVE_KERNEL_RSEQ
|
|
/* We use the structures declarations from the kernel headers. */
|
|
# include <linux/rseq.h>
|
|
#else /* __GLIBC_HAVE_KERNEL_RSEQ */
|
|
/* We use a copy of the include/uapi/linux/rseq.h kernel header. */
|
|
|
|
enum rseq_cpu_id_state
|
|
{
|
|
RSEQ_CPU_ID_UNINITIALIZED = -1,
|
|
RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
|
|
};
|
|
|
|
enum rseq_flags
|
|
{
|
|
RSEQ_FLAG_UNREGISTER = (1 << 0),
|
|
};
|
|
|
|
enum rseq_cs_flags_bit
|
|
{
|
|
RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
|
|
RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
|
|
RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
|
|
};
|
|
|
|
enum rseq_cs_flags
|
|
{
|
|
RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT =
|
|
(1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
|
|
RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL =
|
|
(1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
|
|
RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE =
|
|
(1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
|
|
};
|
|
|
|
/* struct rseq_cs is aligned on 32 bytes to ensure it is always
|
|
contained within a single cache-line. It is usually declared as
|
|
link-time constant data. */
|
|
struct rseq_cs
|
|
{
|
|
/* Version of this structure. */
|
|
uint32_t version;
|
|
/* enum rseq_cs_flags. */
|
|
uint32_t flags;
|
|
uint64_t start_ip;
|
|
/* Offset from start_ip. */
|
|
uint64_t post_commit_offset;
|
|
uint64_t abort_ip;
|
|
} __attribute__ ((__aligned__ (32)));
|
|
|
|
/* struct rseq is aligned on 32 bytes to ensure it is always
|
|
contained within a single cache-line.
|
|
|
|
A single struct rseq per thread is allowed. */
|
|
struct rseq
|
|
{
|
|
/* 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. */
|
|
uint32_t 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. */
|
|
uint32_t 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
|
|
{
|
|
uint64_t ptr64;
|
|
# ifdef __LP64__
|
|
uint64_t ptr;
|
|
# else /* __LP64__ */
|
|
struct
|
|
{
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
uint32_t padding; /* Initialized to zero. */
|
|
uint32_t ptr32;
|
|
# else /* LITTLE */
|
|
uint32_t ptr32;
|
|
uint32_t padding; /* Initialized to zero. */
|
|
# endif /* ENDIAN */
|
|
} ptr;
|
|
# endif /* __LP64__ */
|
|
} 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_CS_FLAG_NO_RESTART_ON_PREEMPT
|
|
Inhibit instruction sequence block restart on preemption
|
|
for this thread.
|
|
- RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
|
|
Inhibit instruction sequence block restart on signal
|
|
delivery for this thread.
|
|
- RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
|
|
Inhibit instruction sequence block restart on migration for
|
|
this thread. */
|
|
uint32_t flags;
|
|
} __attribute__ ((__aligned__ (32)));
|
|
|
|
#endif /* __GLIBC_HAVE_KERNEL_RSEQ */
|
|
|
|
/* Offset from the thread pointer to the rseq area. */
|
|
extern const ptrdiff_t __rseq_offset;
|
|
|
|
/* Size of the registered rseq area. 0 if the registration was
|
|
unsuccessful. */
|
|
extern const unsigned int __rseq_size;
|
|
|
|
/* Flags used during rseq registration. */
|
|
extern const unsigned int __rseq_flags;
|
|
|
|
#endif /* sys/rseq.h */
|