1/* Restartable Sequences exported symbols. Linux header.
2 Copyright (C) 2021-2022 Free Software Foundation, Inc.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#ifndef _SYS_RSEQ_H
19#define _SYS_RSEQ_H 1
20
21/* Architecture-specific rseq signature. */
22#include <bits/rseq.h>
23
24#include <stddef.h>
25#include <stdint.h>
26#include <sys/cdefs.h>
27#include <bits/endian.h>
28
29#ifdef __has_include
30# if __has_include ("linux/rseq.h")
31# define __GLIBC_HAVE_KERNEL_RSEQ
32# endif
33#else
34# include <linux/version.h>
35# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0)
36# define __GLIBC_HAVE_KERNEL_RSEQ
37# endif
38#endif
39
40#ifdef __GLIBC_HAVE_KERNEL_RSEQ
41/* We use the structures declarations from the kernel headers. */
42# include <linux/rseq.h>
43#else /* __GLIBC_HAVE_KERNEL_RSEQ */
44/* We use a copy of the include/uapi/linux/rseq.h kernel header. */
45
46enum rseq_cpu_id_state
47 {
48 RSEQ_CPU_ID_UNINITIALIZED = -1,
49 RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
50 };
51
52enum rseq_flags
53 {
54 RSEQ_FLAG_UNREGISTER = (1 << 0),
55 };
56
57enum rseq_cs_flags_bit
58 {
59 RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
60 RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
61 RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
62 };
63
64enum rseq_cs_flags
65 {
66 RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT =
67 (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
68 RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL =
69 (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
70 RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE =
71 (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
72 };
73
74/* struct rseq_cs is aligned on 32 bytes to ensure it is always
75 contained within a single cache-line. It is usually declared as
76 link-time constant data. */
77struct rseq_cs
78 {
79 /* Version of this structure. */
80 uint32_t version;
81 /* enum rseq_cs_flags. */
82 uint32_t flags;
83 uint64_t start_ip;
84 /* Offset from start_ip. */
85 uint64_t post_commit_offset;
86 uint64_t abort_ip;
87 } __attribute__ ((__aligned__ (32)));
88
89/* struct rseq is aligned on 32 bytes to ensure it is always
90 contained within a single cache-line.
91
92 A single struct rseq per thread is allowed. */
93struct rseq
94 {
95 /* Restartable sequences cpu_id_start field. Updated by the
96 kernel. Read by user-space with single-copy atomicity
97 semantics. This field should only be read by the thread which
98 registered this data structure. Aligned on 32-bit. Always
99 contains a value in the range of possible CPUs, although the
100 value may not be the actual current CPU (e.g. if rseq is not
101 initialized). This CPU number value should always be compared
102 against the value of the cpu_id field before performing a rseq
103 commit or returning a value read from a data structure indexed
104 using the cpu_id_start value. */
105 uint32_t cpu_id_start;
106 /* Restartable sequences cpu_id field. Updated by the kernel.
107 Read by user-space with single-copy atomicity semantics. This
108 field should only be read by the thread which registered this
109 data structure. Aligned on 32-bit. Values
110 RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
111 have a special semantic: the former means "rseq uninitialized",
112 and latter means "rseq initialization failed". This value is
113 meant to be read within rseq critical sections and compared
114 with the cpu_id_start value previously read, before performing
115 the commit instruction, or read and compared with the
116 cpu_id_start value before returning a value loaded from a data
117 structure indexed using the cpu_id_start value. */
118 uint32_t cpu_id;
119 /* Restartable sequences rseq_cs field.
120
121 Contains NULL when no critical section is active for the current
122 thread, or holds a pointer to the currently active struct rseq_cs.
123
124 Updated by user-space, which sets the address of the currently
125 active rseq_cs at the beginning of assembly instruction sequence
126 block, and set to NULL by the kernel when it restarts an assembly
127 instruction sequence block, as well as when the kernel detects that
128 it is preempting or delivering a signal outside of the range
129 targeted by the rseq_cs. Also needs to be set to NULL by user-space
130 before reclaiming memory that contains the targeted struct rseq_cs.
131
132 Read and set by the kernel. Set by user-space with single-copy
133 atomicity semantics. This field should only be updated by the
134 thread which registered this data structure. Aligned on 64-bit. */
135 union
136 {
137 uint64_t ptr64;
138# ifdef __LP64__
139 uint64_t ptr;
140# else /* __LP64__ */
141 struct
142 {
143#if __BYTE_ORDER == __BIG_ENDIAN
144 uint32_t padding; /* Initialized to zero. */
145 uint32_t ptr32;
146# else /* LITTLE */
147 uint32_t ptr32;
148 uint32_t padding; /* Initialized to zero. */
149# endif /* ENDIAN */
150 } ptr;
151# endif /* __LP64__ */
152 } rseq_cs;
153
154 /* Restartable sequences flags field.
155
156 This field should only be updated by the thread which
157 registered this data structure. Read by the kernel.
158 Mainly used for single-stepping through rseq critical sections
159 with debuggers.
160
161 - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
162 Inhibit instruction sequence block restart on preemption
163 for this thread.
164 - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
165 Inhibit instruction sequence block restart on signal
166 delivery for this thread.
167 - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
168 Inhibit instruction sequence block restart on migration for
169 this thread. */
170 uint32_t flags;
171 } __attribute__ ((__aligned__ (32)));
172
173#endif /* __GLIBC_HAVE_KERNEL_RSEQ */
174
175/* Offset from the thread pointer to the rseq area. */
176extern const ptrdiff_t __rseq_offset;
177
178/* Size of the registered rseq area. 0 if the registration was
179 unsuccessful. */
180extern const unsigned int __rseq_size;
181
182/* Flags used during rseq registration. */
183extern const unsigned int __rseq_flags;
184
185#endif /* sys/rseq.h */
186