Introduce common generic header file
[librseq.git] / include / rseq / arch / x86.h
CommitLineData
90702366 1/* SPDX-License-Identifier: MIT */
abac6819 2/* SPDX-FileCopyrightText: 2016-2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> */
f2d7b530 3
784b0012 4/*
44ec21eb 5 * rseq/arch/x86.h
784b0012
MD
6 */
7
44ec21eb
MJ
8#ifndef _RSEQ_RSEQ_H
9#error "Never use <rseq/arch/x86.h> directly; include <rseq/rseq.h> instead."
809f5ee3
MD
10#endif
11
784b0012
MD
12#include <stdint.h>
13
abac6819
MD
14/*
15 * RSEQ_ASM_*() macro helpers are internal to the librseq headers. Those
16 * are not part of the public API.
17 */
18
a5fe9e95
MD
19/*
20 * RSEQ_SIG is used with the following reserved undefined instructions, which
21 * trap in user-space:
22 *
23 * x86-32: 0f b9 3d 53 30 05 53 ud1 0x53053053,%edi
24 * x86-64: 0f b9 3d 53 30 05 53 ud1 0x53053053(%rip),%edi
25 */
784b0012
MD
26#define RSEQ_SIG 0x53053053
27
809f5ee3
MD
28/*
29 * Due to a compiler optimization bug in gcc-8 with asm goto and TLS asm input
30 * operands, we cannot use "m" input operands, and rather pass the __rseq_abi
31 * address through a "r" input operand.
32 */
33
abac6819
MD
34/*
35 * Offset of cpu_id, rseq_cs, and mm_cid fields in struct rseq. Those
36 * are defined explicitly as macros to be used from assembly.
37 */
d9c11a15
MD
38#define RSEQ_ASM_CPU_ID_OFFSET 4
39#define RSEQ_ASM_CS_OFFSET 8
40#define RSEQ_ASM_MM_CID_OFFSET 24
05ebd3f9 41
abac6819
MD
42/*
43 * Refer to the Linux kernel memory model (LKMM) for documentation of
44 * the memory barriers. Expect all x86 hardware to be x86-TSO (Total
45 * Store Order).
46 */
47
48/* CPU memory barrier. */
784b0012
MD
49#define rseq_smp_mb() \
50 __asm__ __volatile__ ("lock; addl $0,-128(%%rsp)" ::: "memory", "cc")
abac6819 51/* CPU read memory barrier */
784b0012 52#define rseq_smp_rmb() rseq_barrier()
abac6819 53/* CPU write memory barrier */
784b0012
MD
54#define rseq_smp_wmb() rseq_barrier()
55
abac6819 56/* Acquire: One-way permeable barrier. */
784b0012
MD
57#define rseq_smp_load_acquire(p) \
58__extension__ ({ \
3664a718 59 rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
784b0012
MD
60 rseq_barrier(); \
61 ____p1; \
62})
63
abac6819 64/* Acquire barrier after control dependency. */
784b0012
MD
65#define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
66
abac6819 67/* Release: One-way permeable barrier. */
784b0012
MD
68#define rseq_smp_store_release(p, v) \
69do { \
70 rseq_barrier(); \
809f5ee3 71 RSEQ_WRITE_ONCE(*(p), v); \
784b0012
MD
72} while (0)
73
abac6819 74/* Segment selector for the thread pointer. */
b52031b2
MD
75#ifdef RSEQ_ARCH_AMD64
76# define RSEQ_ASM_TP_SEGMENT %%fs
77#else
78# define RSEQ_ASM_TP_SEGMENT %%gs
79#endif
784b0012 80
90d9876e 81/*
b52031b2
MD
82 * Helper macro to define a variable of pointer type stored in a 64-bit
83 * integer. Only used internally in rseq headers.
90d9876e 84 */
b52031b2
MD
85#ifdef RSEQ_ARCH_AMD64
86# define RSEQ_ASM_U64_PTR(x) ".quad " x
87#else
88# define RSEQ_ASM_U64_PTR(x) ".long " x ", 0x0"
89#endif
90d9876e 90
78951921
MD
91#define RSEQ_ASM_U32(x) ".long " x
92
ed21bf6d
MD
93/* Common architecture support macros. */
94#include "rseq/arch/generic/common.h"
90d9876e 95
abac6819
MD
96/*
97 * Define a critical section abort handler.
98 *
99 * @label:
100 * Local label to the abort handler.
101 * @teardown:
102 * Sequence of instructions to run on abort.
103 * @abort_label:
104 * C label to jump to at the end of the sequence.
105 */
784b0012
MD
106#define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label) \
107 ".pushsection __rseq_failure, \"ax\"\n\t" \
abac6819
MD
108 /* \
109 * Disassembler-friendly signature: \
110 * x86-32: ud1 <sig>,%edi \
111 * x86-64: ud1 <sig>(%rip),%edi \
112 */ \
a5fe9e95 113 ".byte 0x0f, 0xb9, 0x3d\n\t" \
784b0012
MD
114 ".long " __rseq_str(RSEQ_SIG) "\n\t" \
115 __rseq_str(label) ":\n\t" \
116 teardown \
117 "jmp %l[" __rseq_str(abort_label) "]\n\t" \
118 ".popsection\n\t"
119
abac6819
MD
120/*
121 * Define a critical section teardown handler.
122 *
123 * @label:
124 * Local label to the teardown handler.
125 * @teardown:
126 * Sequence of instructions to run on teardown.
127 * @target_label:
128 * C label to jump to at the end of the sequence.
129 */
559d824f 130#define RSEQ_ASM_DEFINE_TEARDOWN(label, teardown, target_label) \
784b0012
MD
131 ".pushsection __rseq_failure, \"ax\"\n\t" \
132 __rseq_str(label) ":\n\t" \
133 teardown \
559d824f 134 "jmp %l[" __rseq_str(target_label) "]\n\t" \
784b0012
MD
135 ".popsection\n\t"
136
ed21bf6d
MD
137/*
138 * Store the address of the critical section descriptor structure at
139 * @cs_label into the @rseq_cs pointer and emit the label @label, which
140 * is the beginning of the sequence of consecutive assembly instructions.
141 *
142 * @label:
143 * Local label to the beginning of the sequence of consecutive assembly
144 * instructions.
145 * @cs_label:
146 * Source local label to the critical section descriptor structure.
147 * @rseq_cs:
148 * Destination pointer where to store the address of the critical
149 * section descriptor structure.
150 */
151#ifdef RSEQ_ARCH_AMD64
152#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
153 RSEQ_INJECT_ASM(1) \
154 "leaq " __rseq_str(cs_label) "(%%rip), %%rax\n\t" \
155 "movq %%rax, " __rseq_str(rseq_cs) "\n\t" \
156 __rseq_str(label) ":\n\t"
157#else
158# define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
159 RSEQ_INJECT_ASM(1) \
160 "movl $" __rseq_str(cs_label) ", " __rseq_str(rseq_cs) "\n\t" \
161 __rseq_str(label) ":\n\t"
162#endif
163
abac6819
MD
164/* Jump to local label @label when @cpu_id != @current_cpu_id. */
165#define RSEQ_ASM_CBNE_CPU_ID(cpu_id, current_cpu_id, label) \
166 RSEQ_INJECT_ASM(2) \
167 "cmpl %[" __rseq_str(cpu_id) "], " __rseq_str(current_cpu_id) "\n\t" \
168 "jnz " __rseq_str(label) "\n\t"
784b0012 169
809f5ee3 170/* Per-cpu-id indexing. */
784b0012 171
abf9e855 172#define RSEQ_TEMPLATE_INDEX_CPU_ID
809f5ee3 173#define RSEQ_TEMPLATE_MO_RELAXED
44ec21eb 174#include "rseq/arch/x86/bits.h"
809f5ee3 175#undef RSEQ_TEMPLATE_MO_RELAXED
784b0012 176
809f5ee3 177#define RSEQ_TEMPLATE_MO_RELEASE
44ec21eb 178#include "rseq/arch/x86/bits.h"
809f5ee3 179#undef RSEQ_TEMPLATE_MO_RELEASE
abf9e855 180#undef RSEQ_TEMPLATE_INDEX_CPU_ID
784b0012 181
809f5ee3 182/* Per-mm-cid indexing. */
784b0012 183
abf9e855 184#define RSEQ_TEMPLATE_INDEX_MM_CID
809f5ee3 185#define RSEQ_TEMPLATE_MO_RELAXED
44ec21eb 186#include "rseq/arch/x86/bits.h"
809f5ee3 187#undef RSEQ_TEMPLATE_MO_RELAXED
784b0012 188
809f5ee3 189#define RSEQ_TEMPLATE_MO_RELEASE
44ec21eb 190#include "rseq/arch/x86/bits.h"
809f5ee3 191#undef RSEQ_TEMPLATE_MO_RELEASE
abf9e855 192#undef RSEQ_TEMPLATE_INDEX_MM_CID
de28c254 193
abf9e855 194/* APIs which are not indexed. */
de28c254 195
abf9e855 196#define RSEQ_TEMPLATE_INDEX_NONE
809f5ee3 197#define RSEQ_TEMPLATE_MO_RELAXED
44ec21eb 198#include "rseq/arch/x86/bits.h"
809f5ee3 199#undef RSEQ_TEMPLATE_MO_RELAXED
abf9e855 200#undef RSEQ_TEMPLATE_INDEX_NONE
This page took 0.053395 seconds and 4 git commands to generate.