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, ¤t->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