1 /* SPDX-License-Identifier: MIT */
2 /* SPDX-FileCopyrightText: 2018 MIPS Tech LLC */
3 /* SPDX-FileCopyrightText: 2016-2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> */
6 * Author: Paul Burton <paul.burton@mips.com>
10 #error "Never use <rseq/arch/mips.h> directly; include <rseq/rseq.h> instead."
13 #include <asm/byteorder.h>
16 * RSEQ_ASM_*() macro helpers are internal to the librseq headers. Those
17 * are not part of the public API.
20 #if (RSEQ_BITS_PER_LONG != 64) && (RSEQ_BITS_PER_LONG != 32)
21 # error unsupported RSEQ_BITS_PER_LONG
25 * RSEQ_SIG uses the break instruction. The instruction pattern is:
28 * 0350000d break 0x350
31 * 00100350 break 0x350
34 * 0000d407 break 0x350
36 * For nanoMIPS32 and microMIPS, the instruction stream is encoded as 16-bit
37 * halfwords, so the signature halfwords need to be swapped accordingly for
40 #if defined(__nanomips__)
42 # define RSEQ_SIG 0x03500010
44 # define RSEQ_SIG 0x00100350
46 #elif defined(__mips_micromips)
48 # define RSEQ_SIG 0xd4070000
50 # define RSEQ_SIG 0x0000d407
52 #elif defined(__mips__)
53 # define RSEQ_SIG 0x0350000d
55 /* Unknown MIPS architecture. */
59 * Refer to the Linux kernel memory model (LKMM) for documentation of
60 * the memory barriers.
63 /* CPU memory barrier. */
64 #define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory")
65 /* CPU read memory barrier */
66 #define rseq_smp_rmb() rseq_smp_mb()
67 /* CPU write memory barrier */
68 #define rseq_smp_wmb() rseq_smp_mb()
70 /* Acquire: One-way permeable barrier. */
71 #define rseq_smp_load_acquire(p) \
73 rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
78 /* Acquire barrier after control dependency. */
79 #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
81 /* Release: One-way permeable barrier. */
82 #define rseq_smp_store_release(p, v) \
85 RSEQ_WRITE_ONCE(*(p), v); \
89 * Helper macros to define and access a variable of long integer type.
90 * Only used internally in rseq headers.
92 #if RSEQ_BITS_PER_LONG == 64
93 # define RSEQ_ASM_LONG ".dword"
94 # define RSEQ_ASM_LONG_LA "dla"
95 # define RSEQ_ASM_LONG_L "ld"
96 # define RSEQ_ASM_LONG_S "sd"
97 # define RSEQ_ASM_LONG_ADDI "daddiu"
99 # define RSEQ_ASM_LONG ".word"
100 # define RSEQ_ASM_LONG_LA "la"
101 # define RSEQ_ASM_LONG_L "lw"
102 # define RSEQ_ASM_LONG_S "sw"
103 # define RSEQ_ASM_LONG_ADDI "addiu"
107 * Helper macros to define a variable of pointer type stored in a 64-bit
108 * integer. Only used internally in rseq headers.
110 #if RSEQ_BITS_PER_LONG == 64
111 # define RSEQ_ASM_U64_PTR(x) ".dword " x
113 # if defined(__BYTE_ORDER) ? (__BYTE_ORDER == __BIG_ENDIAN) : defined(__BIG_ENDIAN)
114 # define RSEQ_ASM_U64_PTR(x) ".word 0x0, " x
116 # define RSEQ_ASM_U64_PTR(x) ".word " x ", 0x0"
120 #define RSEQ_ASM_U32(x) ".word " x
122 /* Common architecture support macros. */
123 #include "rseq/arch/generic/common.h"
125 /* Only used in RSEQ_ASM_DEFINE_ABORT. */
126 #define __RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label, \
127 table_label, version, flags, \
128 start_ip, post_commit_offset, abort_ip) \
130 __rseq_str(table_label) ":\n\t" \
131 RSEQ_ASM_U32(__rseq_str(version)) "\n\t" \
132 RSEQ_ASM_U32(__rseq_str(flags)) "\n\t" \
133 RSEQ_ASM_U64_PTR(__rseq_str(start_ip)) "\n\t" \
134 RSEQ_ASM_U64_PTR(__rseq_str(post_commit_offset)) "\n\t" \
135 RSEQ_ASM_U64_PTR(__rseq_str(abort_ip)) "\n\t" \
136 RSEQ_ASM_U32(__rseq_str(RSEQ_SIG)) "\n\t" \
137 __rseq_str(label) ":\n\t" \
139 "b %l[" __rseq_str(abort_label) "]\n\t"
142 * Define a critical section abort handler.
145 * Local label to the abort handler.
147 * Sequence of instructions to run on abort.
149 * C label to jump to at the end of the sequence.
151 * Local label to the critical section descriptor copy placed near
152 * the program counter. This is done for performance reasons because
153 * computing this address is faster than accessing the program data.
155 * The purpose of @start_ip, @post_commit_ip, and @abort_ip are
156 * documented in RSEQ_ASM_DEFINE_TABLE.
158 #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label, \
159 table_label, start_ip, post_commit_ip, abort_ip) \
160 __RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label, \
161 table_label, 0x0, 0x0, start_ip, \
162 (post_commit_ip) - (start_ip), abort_ip)
165 * Define a critical section teardown handler.
168 * Local label to the teardown handler.
170 * Sequence of instructions to run on teardown.
172 * C label to jump to at the end of the sequence.
174 #define RSEQ_ASM_DEFINE_TEARDOWN(label, teardown, target_label) \
175 __rseq_str(label) ":\n\t" \
177 "b %l[" __rseq_str(target_label) "]\n\t"
180 * Store the address of the critical section descriptor structure at
181 * @cs_label into the @rseq_cs pointer and emit the label @label, which
182 * is the beginning of the sequence of consecutive assembly instructions.
185 * Local label to the beginning of the sequence of consecutive assembly
188 * Source local label to the critical section descriptor structure.
190 * Destination pointer where to store the address of the critical
191 * section descriptor structure.
193 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
195 RSEQ_ASM_LONG_LA " $4, " __rseq_str(cs_label) "\n\t" \
196 RSEQ_ASM_LONG_S " $4, %[" __rseq_str(rseq_cs) "]\n\t" \
197 __rseq_str(label) ":\n\t"
199 /* Jump to local label @label when @cpu_id != @current_cpu_id. */
200 #define RSEQ_ASM_CBNE_CPU_ID(cpu_id, current_cpu_id, label) \
202 "lw $4, %[" __rseq_str(current_cpu_id) "]\n\t" \
203 "bne $4, %[" __rseq_str(cpu_id) "], " __rseq_str(label) "\n\t"
205 /* Per-cpu-id indexing. */
207 #define RSEQ_TEMPLATE_INDEX_CPU_ID
208 #define RSEQ_TEMPLATE_MO_RELAXED
209 #include "rseq/arch/mips/bits.h"
210 #undef RSEQ_TEMPLATE_MO_RELAXED
212 #define RSEQ_TEMPLATE_MO_RELEASE
213 #include "rseq/arch/mips/bits.h"
214 #undef RSEQ_TEMPLATE_MO_RELEASE
215 #undef RSEQ_TEMPLATE_INDEX_CPU_ID
217 /* Per-mm-cid indexing. */
219 #define RSEQ_TEMPLATE_INDEX_MM_CID
220 #define RSEQ_TEMPLATE_MO_RELAXED
221 #include "rseq/arch/mips/bits.h"
222 #undef RSEQ_TEMPLATE_MO_RELAXED
224 #define RSEQ_TEMPLATE_MO_RELEASE
225 #include "rseq/arch/mips/bits.h"
226 #undef RSEQ_TEMPLATE_MO_RELEASE
227 #undef RSEQ_TEMPLATE_INDEX_MM_CID
229 /* APIs which are not indexed. */
231 #define RSEQ_TEMPLATE_INDEX_NONE
232 #define RSEQ_TEMPLATE_MO_RELAXED
233 #include "rseq/arch/mips/bits.h"
234 #undef RSEQ_TEMPLATE_MO_RELAXED
235 #undef RSEQ_TEMPLATE_INDEX_NONE
This page took 0.034685 seconds and 4 git commands to generate.