xref: /linux-6.15/include/linux/rseq.h (revision 932562a6)
1*932562a6SKent Overstreet /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
2*932562a6SKent Overstreet #ifndef _LINUX_RSEQ_H
3*932562a6SKent Overstreet #define _LINUX_RSEQ_H
4*932562a6SKent Overstreet 
5*932562a6SKent Overstreet #ifdef CONFIG_RSEQ
6*932562a6SKent Overstreet 
7*932562a6SKent Overstreet #include <linux/preempt.h>
8*932562a6SKent Overstreet #include <linux/sched.h>
9*932562a6SKent Overstreet 
10*932562a6SKent Overstreet /*
11*932562a6SKent Overstreet  * Map the event mask on the user-space ABI enum rseq_cs_flags
12*932562a6SKent Overstreet  * for direct mask checks.
13*932562a6SKent Overstreet  */
14*932562a6SKent Overstreet enum rseq_event_mask_bits {
15*932562a6SKent Overstreet 	RSEQ_EVENT_PREEMPT_BIT	= RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT,
16*932562a6SKent Overstreet 	RSEQ_EVENT_SIGNAL_BIT	= RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT,
17*932562a6SKent Overstreet 	RSEQ_EVENT_MIGRATE_BIT	= RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT,
18*932562a6SKent Overstreet };
19*932562a6SKent Overstreet 
20*932562a6SKent Overstreet enum rseq_event_mask {
21*932562a6SKent Overstreet 	RSEQ_EVENT_PREEMPT	= (1U << RSEQ_EVENT_PREEMPT_BIT),
22*932562a6SKent Overstreet 	RSEQ_EVENT_SIGNAL	= (1U << RSEQ_EVENT_SIGNAL_BIT),
23*932562a6SKent Overstreet 	RSEQ_EVENT_MIGRATE	= (1U << RSEQ_EVENT_MIGRATE_BIT),
24*932562a6SKent Overstreet };
25*932562a6SKent Overstreet 
rseq_set_notify_resume(struct task_struct * t)26*932562a6SKent Overstreet static inline void rseq_set_notify_resume(struct task_struct *t)
27*932562a6SKent Overstreet {
28*932562a6SKent Overstreet 	if (t->rseq)
29*932562a6SKent Overstreet 		set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
30*932562a6SKent Overstreet }
31*932562a6SKent Overstreet 
32*932562a6SKent Overstreet void __rseq_handle_notify_resume(struct ksignal *sig, struct pt_regs *regs);
33*932562a6SKent Overstreet 
rseq_handle_notify_resume(struct ksignal * ksig,struct pt_regs * regs)34*932562a6SKent Overstreet static inline void rseq_handle_notify_resume(struct ksignal *ksig,
35*932562a6SKent Overstreet 					     struct pt_regs *regs)
36*932562a6SKent Overstreet {
37*932562a6SKent Overstreet 	if (current->rseq)
38*932562a6SKent Overstreet 		__rseq_handle_notify_resume(ksig, regs);
39*932562a6SKent Overstreet }
40*932562a6SKent Overstreet 
rseq_signal_deliver(struct ksignal * ksig,struct pt_regs * regs)41*932562a6SKent Overstreet static inline void rseq_signal_deliver(struct ksignal *ksig,
42*932562a6SKent Overstreet 				       struct pt_regs *regs)
43*932562a6SKent Overstreet {
44*932562a6SKent Overstreet 	preempt_disable();
45*932562a6SKent Overstreet 	__set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
46*932562a6SKent Overstreet 	preempt_enable();
47*932562a6SKent Overstreet 	rseq_handle_notify_resume(ksig, regs);
48*932562a6SKent Overstreet }
49*932562a6SKent Overstreet 
50*932562a6SKent Overstreet /* rseq_preempt() requires preemption to be disabled. */
rseq_preempt(struct task_struct * t)51*932562a6SKent Overstreet static inline void rseq_preempt(struct task_struct *t)
52*932562a6SKent Overstreet {
53*932562a6SKent Overstreet 	__set_bit(RSEQ_EVENT_PREEMPT_BIT, &t->rseq_event_mask);
54*932562a6SKent Overstreet 	rseq_set_notify_resume(t);
55*932562a6SKent Overstreet }
56*932562a6SKent Overstreet 
57*932562a6SKent Overstreet /* rseq_migrate() requires preemption to be disabled. */
rseq_migrate(struct task_struct * t)58*932562a6SKent Overstreet static inline void rseq_migrate(struct task_struct *t)
59*932562a6SKent Overstreet {
60*932562a6SKent Overstreet 	__set_bit(RSEQ_EVENT_MIGRATE_BIT, &t->rseq_event_mask);
61*932562a6SKent Overstreet 	rseq_set_notify_resume(t);
62*932562a6SKent Overstreet }
63*932562a6SKent Overstreet 
64*932562a6SKent Overstreet /*
65*932562a6SKent Overstreet  * If parent process has a registered restartable sequences area, the
66*932562a6SKent Overstreet  * child inherits. Unregister rseq for a clone with CLONE_VM set.
67*932562a6SKent Overstreet  */
rseq_fork(struct task_struct * t,unsigned long clone_flags)68*932562a6SKent Overstreet static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
69*932562a6SKent Overstreet {
70*932562a6SKent Overstreet 	if (clone_flags & CLONE_VM) {
71*932562a6SKent Overstreet 		t->rseq = NULL;
72*932562a6SKent Overstreet 		t->rseq_len = 0;
73*932562a6SKent Overstreet 		t->rseq_sig = 0;
74*932562a6SKent Overstreet 		t->rseq_event_mask = 0;
75*932562a6SKent Overstreet 	} else {
76*932562a6SKent Overstreet 		t->rseq = current->rseq;
77*932562a6SKent Overstreet 		t->rseq_len = current->rseq_len;
78*932562a6SKent Overstreet 		t->rseq_sig = current->rseq_sig;
79*932562a6SKent Overstreet 		t->rseq_event_mask = current->rseq_event_mask;
80*932562a6SKent Overstreet 	}
81*932562a6SKent Overstreet }
82*932562a6SKent Overstreet 
rseq_execve(struct task_struct * t)83*932562a6SKent Overstreet static inline void rseq_execve(struct task_struct *t)
84*932562a6SKent Overstreet {
85*932562a6SKent Overstreet 	t->rseq = NULL;
86*932562a6SKent Overstreet 	t->rseq_len = 0;
87*932562a6SKent Overstreet 	t->rseq_sig = 0;
88*932562a6SKent Overstreet 	t->rseq_event_mask = 0;
89*932562a6SKent Overstreet }
90*932562a6SKent Overstreet 
91*932562a6SKent Overstreet #else
92*932562a6SKent Overstreet 
rseq_set_notify_resume(struct task_struct * t)93*932562a6SKent Overstreet static inline void rseq_set_notify_resume(struct task_struct *t)
94*932562a6SKent Overstreet {
95*932562a6SKent Overstreet }
rseq_handle_notify_resume(struct ksignal * ksig,struct pt_regs * regs)96*932562a6SKent Overstreet static inline void rseq_handle_notify_resume(struct ksignal *ksig,
97*932562a6SKent Overstreet 					     struct pt_regs *regs)
98*932562a6SKent Overstreet {
99*932562a6SKent Overstreet }
rseq_signal_deliver(struct ksignal * ksig,struct pt_regs * regs)100*932562a6SKent Overstreet static inline void rseq_signal_deliver(struct ksignal *ksig,
101*932562a6SKent Overstreet 				       struct pt_regs *regs)
102*932562a6SKent Overstreet {
103*932562a6SKent Overstreet }
rseq_preempt(struct task_struct * t)104*932562a6SKent Overstreet static inline void rseq_preempt(struct task_struct *t)
105*932562a6SKent Overstreet {
106*932562a6SKent Overstreet }
rseq_migrate(struct task_struct * t)107*932562a6SKent Overstreet static inline void rseq_migrate(struct task_struct *t)
108*932562a6SKent Overstreet {
109*932562a6SKent Overstreet }
rseq_fork(struct task_struct * t,unsigned long clone_flags)110*932562a6SKent Overstreet static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
111*932562a6SKent Overstreet {
112*932562a6SKent Overstreet }
rseq_execve(struct task_struct * t)113*932562a6SKent Overstreet static inline void rseq_execve(struct task_struct *t)
114*932562a6SKent Overstreet {
115*932562a6SKent Overstreet }
116*932562a6SKent Overstreet 
117*932562a6SKent Overstreet #endif
118*932562a6SKent Overstreet 
119*932562a6SKent Overstreet #ifdef CONFIG_DEBUG_RSEQ
120*932562a6SKent Overstreet 
121*932562a6SKent Overstreet void rseq_syscall(struct pt_regs *regs);
122*932562a6SKent Overstreet 
123*932562a6SKent Overstreet #else
124*932562a6SKent Overstreet 
rseq_syscall(struct pt_regs * regs)125*932562a6SKent Overstreet static inline void rseq_syscall(struct pt_regs *regs)
126*932562a6SKent Overstreet {
127*932562a6SKent Overstreet }
128*932562a6SKent Overstreet 
129*932562a6SKent Overstreet #endif
130*932562a6SKent Overstreet 
131*932562a6SKent Overstreet #endif /* _LINUX_RSEQ_H */
132