Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rseq: Add prctl() to enable time slice extensions

Implement a prctl() so that tasks can enable the time slice extension
mechanism. This fails, when time slice extensions are disabled at compile
time or on the kernel command line and when no rseq pointer is registered
in the kernel.

That allows to implement a single trivial check in the exit to user mode
hotpath, to decide whether the whole mechanism needs to be invoked.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251215155708.858717691@linutronix.de

authored by

Thomas Gleixner and committed by
Peter Zijlstra
28621ec2 b5b82824

+77
+9
include/linux/rseq.h
··· 163 163 static inline void rseq_syscall(struct pt_regs *regs) { } 164 164 #endif /* !CONFIG_DEBUG_RSEQ */ 165 165 166 + #ifdef CONFIG_RSEQ_SLICE_EXTENSION 167 + int rseq_slice_extension_prctl(unsigned long arg2, unsigned long arg3); 168 + #else /* CONFIG_RSEQ_SLICE_EXTENSION */ 169 + static inline int rseq_slice_extension_prctl(unsigned long arg2, unsigned long arg3) 170 + { 171 + return -ENOTSUPP; 172 + } 173 + #endif /* !CONFIG_RSEQ_SLICE_EXTENSION */ 174 + 166 175 #endif /* _LINUX_RSEQ_H */
+10
include/uapi/linux/prctl.h
··· 386 386 # define PR_FUTEX_HASH_SET_SLOTS 1 387 387 # define PR_FUTEX_HASH_GET_SLOTS 2 388 388 389 + /* RSEQ time slice extensions */ 390 + #define PR_RSEQ_SLICE_EXTENSION 79 391 + # define PR_RSEQ_SLICE_EXTENSION_GET 1 392 + # define PR_RSEQ_SLICE_EXTENSION_SET 2 393 + /* 394 + * Bits for RSEQ_SLICE_EXTENSION_GET/SET 395 + * PR_RSEQ_SLICE_EXT_ENABLE: Enable 396 + */ 397 + # define PR_RSEQ_SLICE_EXT_ENABLE 0x01 398 + 389 399 #endif /* _LINUX_PRCTL_H */
+52
kernel/rseq.c
··· 71 71 #define RSEQ_BUILD_SLOW_PATH 72 72 73 73 #include <linux/debugfs.h> 74 + #include <linux/prctl.h> 74 75 #include <linux/ratelimit.h> 75 76 #include <linux/rseq_entry.h> 76 77 #include <linux/sched.h> ··· 501 500 502 501 #ifdef CONFIG_RSEQ_SLICE_EXTENSION 503 502 DEFINE_STATIC_KEY_TRUE(rseq_slice_extension_key); 503 + 504 + int rseq_slice_extension_prctl(unsigned long arg2, unsigned long arg3) 505 + { 506 + switch (arg2) { 507 + case PR_RSEQ_SLICE_EXTENSION_GET: 508 + if (arg3) 509 + return -EINVAL; 510 + return current->rseq.slice.state.enabled ? PR_RSEQ_SLICE_EXT_ENABLE : 0; 511 + 512 + case PR_RSEQ_SLICE_EXTENSION_SET: { 513 + u32 rflags, valid = RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE; 514 + bool enable = !!(arg3 & PR_RSEQ_SLICE_EXT_ENABLE); 515 + 516 + if (arg3 & ~PR_RSEQ_SLICE_EXT_ENABLE) 517 + return -EINVAL; 518 + if (!rseq_slice_extension_enabled()) 519 + return -ENOTSUPP; 520 + if (!current->rseq.usrptr) 521 + return -ENXIO; 522 + 523 + /* No change? */ 524 + if (enable == !!current->rseq.slice.state.enabled) 525 + return 0; 526 + 527 + if (get_user(rflags, &current->rseq.usrptr->flags)) 528 + goto die; 529 + 530 + if (current->rseq.slice.state.enabled) 531 + valid |= RSEQ_CS_FLAG_SLICE_EXT_ENABLED; 532 + 533 + if ((rflags & valid) != valid) 534 + goto die; 535 + 536 + rflags &= ~RSEQ_CS_FLAG_SLICE_EXT_ENABLED; 537 + rflags |= RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE; 538 + if (enable) 539 + rflags |= RSEQ_CS_FLAG_SLICE_EXT_ENABLED; 540 + 541 + if (put_user(rflags, &current->rseq.usrptr->flags)) 542 + goto die; 543 + 544 + current->rseq.slice.state.enabled = enable; 545 + return 0; 546 + } 547 + default: 548 + return -EINVAL; 549 + } 550 + die: 551 + force_sig(SIGSEGV); 552 + return -EFAULT; 553 + } 504 554 505 555 static int __init rseq_slice_cmdline(char *str) 506 556 {
+6
kernel/sys.c
··· 53 53 #include <linux/time_namespace.h> 54 54 #include <linux/binfmts.h> 55 55 #include <linux/futex.h> 56 + #include <linux/rseq.h> 56 57 57 58 #include <linux/sched.h> 58 59 #include <linux/sched/autogroup.h> ··· 2868 2867 break; 2869 2868 case PR_FUTEX_HASH: 2870 2869 error = futex_hash_prctl(arg2, arg3, arg4); 2870 + break; 2871 + case PR_RSEQ_SLICE_EXTENSION: 2872 + if (arg4 || arg5) 2873 + return -EINVAL; 2874 + error = rseq_slice_extension_prctl(arg2, arg3); 2871 2875 break; 2872 2876 default: 2873 2877 trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5);