rseq: Implement sys_rseq_slice_yield()

Provide a new syscall which has the only purpose to yield the CPU after the
kernel granted a time slice extension.

sched_yield() is not suitable for that because it unconditionally
schedules, but the end of the time slice extension is not required to
schedule when the task was already preempted. This also allows to have a
strict check for termination to catch user space invoking random syscalls
including sched_yield() from a time slice extension region.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Link: https://patch.msgid.link/20251215155708.929634896@linutronix.de
This commit is contained in:
Thomas Gleixner
2025-12-15 17:52:15 +01:00
committed by Peter Zijlstra
parent 28621ec2d4
commit 99d2592023
22 changed files with 46 additions and 1 deletions

View File

@@ -510,3 +510,4 @@
578 common file_getattr sys_file_getattr 578 common file_getattr sys_file_getattr
579 common file_setattr sys_file_setattr 579 common file_setattr sys_file_setattr
580 common listns sys_listns 580 common listns sys_listns
581 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -485,3 +485,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -482,3 +482,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -470,3 +470,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -476,3 +476,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -409,3 +409,4 @@
468 n32 file_getattr sys_file_getattr 468 n32 file_getattr sys_file_getattr
469 n32 file_setattr sys_file_setattr 469 n32 file_setattr sys_file_setattr
470 n32 listns sys_listns 470 n32 listns sys_listns
471 n32 rseq_slice_yield sys_rseq_slice_yield

View File

@@ -385,3 +385,4 @@
468 n64 file_getattr sys_file_getattr 468 n64 file_getattr sys_file_getattr
469 n64 file_setattr sys_file_setattr 469 n64 file_setattr sys_file_setattr
470 n64 listns sys_listns 470 n64 listns sys_listns
471 n64 rseq_slice_yield sys_rseq_slice_yield

View File

@@ -458,3 +458,4 @@
468 o32 file_getattr sys_file_getattr 468 o32 file_getattr sys_file_getattr
469 o32 file_setattr sys_file_setattr 469 o32 file_setattr sys_file_setattr
470 o32 listns sys_listns 470 o32 listns sys_listns
471 o32 rseq_slice_yield sys_rseq_slice_yield

View File

@@ -469,3 +469,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -561,3 +561,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 nospu rseq_slice_yield sys_rseq_slice_yield

View File

@@ -397,3 +397,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -474,3 +474,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -516,3 +516,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -476,3 +476,4 @@
468 i386 file_getattr sys_file_getattr 468 i386 file_getattr sys_file_getattr
469 i386 file_setattr sys_file_setattr 469 i386 file_setattr sys_file_setattr
470 i386 listns sys_listns 470 i386 listns sys_listns
471 i386 rseq_slice_yield sys_rseq_slice_yield

View File

@@ -395,6 +395,7 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield
# #
# Due to a historical design error, certain syscalls are numbered differently # Due to a historical design error, certain syscalls are numbered differently

View File

@@ -441,3 +441,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield

View File

@@ -89,9 +89,11 @@ union rseq_slice_state {
/** /**
* struct rseq_slice - Status information for rseq time slice extension * struct rseq_slice - Status information for rseq time slice extension
* @state: Time slice extension state * @state: Time slice extension state
* @yielded: Indicator for rseq_slice_yield()
*/ */
struct rseq_slice { struct rseq_slice {
union rseq_slice_state state; union rseq_slice_state state;
u8 yielded;
}; };
/** /**

View File

@@ -961,6 +961,7 @@ asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags,
unsigned mask, struct statx __user *buffer); unsigned mask, struct statx __user *buffer);
asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len, asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len,
int flags, uint32_t sig); int flags, uint32_t sig);
asmlinkage long sys_rseq_slice_yield(void);
asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags); asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags);
asmlinkage long sys_open_tree_attr(int dfd, const char __user *path, asmlinkage long sys_open_tree_attr(int dfd, const char __user *path,
unsigned flags, unsigned flags,

View File

@@ -860,8 +860,11 @@ __SYSCALL(__NR_file_setattr, sys_file_setattr)
#define __NR_listns 470 #define __NR_listns 470
__SYSCALL(__NR_listns, sys_listns) __SYSCALL(__NR_listns, sys_listns)
#define __NR_rseq_slice_yield 471
__SYSCALL(__NR_rseq_slice_yield, sys_rseq_slice_yield)
#undef __NR_syscalls #undef __NR_syscalls
#define __NR_syscalls 471 #define __NR_syscalls 472
/* /*
* 32 bit systems traditionally used different * 32 bit systems traditionally used different

View File

@@ -553,6 +553,27 @@ die:
return -EFAULT; return -EFAULT;
} }
/**
* sys_rseq_slice_yield - yield the current processor side effect free if a
* task granted with a time slice extension is done with
* the critical work before being forced out.
*
* Return: 1 if the task successfully yielded the CPU within the granted slice.
* 0 if the slice extension was either never granted or was revoked by
* going over the granted extension, using a syscall other than this one
* or being scheduled out earlier due to a subsequent interrupt.
*
* The syscall does not schedule because the syscall entry work immediately
* relinquishes the CPU and schedules if required.
*/
SYSCALL_DEFINE0(rseq_slice_yield)
{
int yielded = !!current->rseq.slice.yielded;
current->rseq.slice.yielded = 0;
return yielded;
}
static int __init rseq_slice_cmdline(char *str) static int __init rseq_slice_cmdline(char *str)
{ {
bool on; bool on;

View File

@@ -390,6 +390,7 @@ COND_SYSCALL(setuid16);
/* restartable sequence */ /* restartable sequence */
COND_SYSCALL(rseq); COND_SYSCALL(rseq);
COND_SYSCALL(rseq_slice_yield);
COND_SYSCALL(uretprobe); COND_SYSCALL(uretprobe);
COND_SYSCALL(uprobe); COND_SYSCALL(uprobe);

View File

@@ -411,3 +411,4 @@
468 common file_getattr sys_file_getattr 468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr 469 common file_setattr sys_file_setattr
470 common listns sys_listns 470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield