mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/5] rseq: Various slice-ext changes
@ 2026-01-21 14:24 Peter Zijlstra
  2026-01-21 14:24 ` [PATCH 1/5] rseq: Allow registering RSEQ with slice extension Peter Zijlstra
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 14:24 UTC (permalink / raw)
  To: tglx, mathieu.desnoyers
  Cc: linux-kernel, peterz, paulmck, boqun.feng, corbet,
	prakash.sangappa, vineethr, kprateek.nayak, rostedt, bigeasy,
	arnd, rdunlap, rongevarg, longman

Hi!

On top of the patches from Thomas:

  https://lkml.kernel.org/r/20251215155615.870031952@linutronix.de

The combined set can be found in:

  git://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git sched/core

and I am planning to push that into tip/sched/core in the next few days.



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/5] rseq: Allow registering RSEQ with slice extension
  2026-01-21 14:24 [PATCH 0/5] rseq: Various slice-ext changes Peter Zijlstra
@ 2026-01-21 14:24 ` Peter Zijlstra
  2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
  2026-01-21 14:24 ` [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs Peter Zijlstra
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 14:24 UTC (permalink / raw)
  To: tglx, mathieu.desnoyers
  Cc: linux-kernel, peterz, paulmck, boqun.feng, corbet,
	prakash.sangappa, vineethr, kprateek.nayak, rostedt, bigeasy,
	arnd, rdunlap, rongevarg, longman

Since glibc cares about the number of syscalls required to initialize a new
thread, allow initializing rseq with slice extension on. This avoids having to
do another prctl().

Requested-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 include/uapi/linux/rseq.h |    3 ++-
 kernel/rseq.c             |   12 ++++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -19,7 +19,8 @@ enum rseq_cpu_id_state {
 };
 
 enum rseq_flags {
-	RSEQ_FLAG_UNREGISTER = (1 << 0),
+	RSEQ_FLAG_UNREGISTER			= (1 << 0),
+	RSEQ_FLAG_SLICE_EXT_DEFAULT_ON		= (1 << 1),
 };
 
 enum rseq_cs_flags_bit {
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -424,7 +424,7 @@ SYSCALL_DEFINE4(rseq, struct rseq __user
 		return 0;
 	}
 
-	if (unlikely(flags))
+	if (unlikely(flags & ~(RSEQ_FLAG_SLICE_EXT_DEFAULT_ON)))
 		return -EINVAL;
 
 	if (current->rseq.usrptr) {
@@ -459,8 +459,12 @@ SYSCALL_DEFINE4(rseq, struct rseq __user
 	if (!access_ok(rseq, rseq_len))
 		return -EFAULT;
 
-	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION))
+	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION)) {
 		rseqfl |= RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE;
+		if (rseq_slice_extension_enabled() &&
+		    (flags & RSEQ_FLAG_SLICE_EXT_DEFAULT_ON))
+			rseqfl |= RSEQ_CS_FLAG_SLICE_EXT_ENABLED;
+	}
 
 	scoped_user_write_access(rseq, efault) {
 		/*
@@ -488,6 +492,10 @@ SYSCALL_DEFINE4(rseq, struct rseq __user
 	current->rseq.len = rseq_len;
 	current->rseq.sig = sig;
 
+#ifdef CONFIG_RSEQ_SLICE_EXTENSION
+	current->rseq.slice.state.enabled = !!(rseqfl & RSEQ_CS_FLAG_SLICE_EXT_ENABLED);
+#endif
+
 	/*
 	 * If rseq was previously inactive, and has just been
 	 * registered, ensure the cpu_id_start and cpu_id fields



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs
  2026-01-21 14:24 [PATCH 0/5] rseq: Various slice-ext changes Peter Zijlstra
  2026-01-21 14:24 ` [PATCH 1/5] rseq: Allow registering RSEQ with slice extension Peter Zijlstra
@ 2026-01-21 14:24 ` Peter Zijlstra
  2026-01-21 14:50   ` Thomas Weißschuh
  2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
  2026-01-21 14:25 ` [PATCH 3/5] rseq: Lower default slice extension Peter Zijlstra
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 14:24 UTC (permalink / raw)
  To: tglx, mathieu.desnoyers
  Cc: linux-kernel, peterz, paulmck, boqun.feng, corbet,
	prakash.sangappa, vineethr, kprateek.nayak, rostedt, bigeasy,
	arnd, rdunlap, rongevarg, longman

Move changing the slice ext duration to debugfs, a sliglty less permanent
interface.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 Documentation/admin-guide/sysctl/kernel.rst |   11 ----
 Documentation/userspace-api/rseq.rst        |    4 +
 kernel/rseq.c                               |   69 +++++++++++++++++++---------
 3 files changed, 51 insertions(+), 33 deletions(-)

--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -1248,17 +1248,6 @@ reboot-cmd (SPARC only)
 ROM/Flash boot loader. Maybe to tell it what to do after
 rebooting. ???
 
-rseq_slice_extension_nsec
-=========================
-
-A task can request to delay its scheduling if it is in a critical section
-via the prctl(PR_RSEQ_SLICE_EXTENSION_SET) mechanism. This sets the maximum
-allowed extension in nanoseconds before scheduling of the task is enforced.
-Default value is 10000ns (10us). The possible range is 10000ns (10us) to
-50000ns (50us).
-
-This value has a direct correlation to the worst case scheduling latency;
-increment at your own risk.
 
 sched_energy_aware
 ==================
--- a/Documentation/userspace-api/rseq.rst
+++ b/Documentation/userspace-api/rseq.rst
@@ -79,7 +79,9 @@ slice extension by setting rseq::slice_c
 interrupted and the interrupt results in a reschedule request in the
 kernel, then the kernel can grant a time slice extension and return to
 userspace instead of scheduling out. The length of the extension is
-determined by the ``rseq_slice_extension_nsec`` sysctl.
+determined by debugfs:rseq/slice_ext_nsec. The default value is 10 usec; which
+is the minimum value. It can be incremented to 50 usecs, however doing so
+can/will affect the minimum scheduling latency.
 
 The kernel indicates the grant by clearing rseq::slice_ctrl::request and
 setting rseq::slice_ctrl::granted to 1. If there is a reschedule of the
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -222,12 +222,16 @@ static const struct file_operations debu
 	.release	= single_release,
 };
 
+extern void rseq_slice_ext_init(struct dentry *root_dir);
+
 static int __init rseq_debugfs_init(void)
 {
 	struct dentry *root_dir = debugfs_create_dir("rseq", NULL);
 
 	debugfs_create_file("debug", 0644, root_dir, NULL, &debug_ops);
 	rseq_stats_init(root_dir);
+	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSIO))
+		rseq_slice_ext_init(root_dir);
 	return 0;
 }
 __initcall(rseq_debugfs_init);
@@ -515,7 +519,9 @@ struct slice_timer {
 	void		*cookie;
 };
 
-unsigned int rseq_slice_ext_nsecs __read_mostly = 10 * NSEC_PER_USEC;
+static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
+static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
+unsigned int rseq_slice_ext_nsecs __read_mostly = rseq_slice_ext_nsecs_min;
 static DEFINE_PER_CPU(struct slice_timer, slice_timer);
 DEFINE_STATIC_KEY_TRUE(rseq_slice_extension_key);
 
@@ -761,30 +767,52 @@ SYSCALL_DEFINE0(rseq_slice_yield)
 	return yielded;
 }
 
-#ifdef CONFIG_SYSCTL
-static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
-static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
+#ifdef CONFIG_DEBUG_FS
+static int rseq_slice_ext_show(struct seq_file *m, void *p)
+{
+	seq_printf(m, "%d\n", rseq_slice_ext_nsecs);
+	return 0;
+}
+
+static ssize_t rseq_slice_ext_write(struct file *file, const char __user *ubuf,
+				    size_t count, loff_t *ppos)
+{
+	unsigned int nsecs;
+
+	if (kstrtouint(ubuf, count, &nsecs))
+		return -EINVAL;
+
+	if (nsecs < rseq_slice_ext_nsecs_min)
+		return -ERANGE;
+
+	if (nsecs > rseq_slice_ext_nsecs_max)
+		return -ERANGE;
+
+	rseq_slice_ext_nsecs = nsecs;
+
+	return count;
+}
 
-static const struct ctl_table rseq_slice_ext_sysctl[] = {
-	{
-		.procname	= "rseq_slice_extension_nsec",
-		.data		= &rseq_slice_ext_nsecs,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_douintvec_minmax,
-		.extra1		= (unsigned int *)&rseq_slice_ext_nsecs_min,
-		.extra2		= (unsigned int *)&rseq_slice_ext_nsecs_max,
-	},
+static int rseq_slice_ext_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rseq_slice_ext_show, inode->i_private);
+}
+
+static const struct file_operations slice_ext_ops = {
+	.open		= rseq_slice_ext_open,
+	.read		= seq_read,
+	.write		= rseq_slice_ext_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
 };
 
-static void rseq_slice_sysctl_init(void)
+static void rseq_slice_ext_init(struct dentry *root_dir)
 {
-	if (rseq_slice_extension_enabled())
-		register_sysctl_init("kernel", rseq_slice_ext_sysctl);
+	debugfs_create_file("slice_ext_nsec", 0644, root_dir, NULL, &slice_ext_ops);
 }
-#else /* CONFIG_SYSCTL */
-static inline void rseq_slice_sysctl_init(void) { }
-#endif  /* !CONFIG_SYSCTL */
+#else
+static void rseq_slice_ext_init(struct dentry *root_dir) { }
+#endif
 
 static int __init rseq_slice_cmdline(char *str)
 {
@@ -807,7 +835,6 @@ static int __init rseq_slice_init(void)
 		hrtimer_setup(per_cpu_ptr(&slice_timer.timer, cpu), rseq_slice_expired,
 			      CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED_HARD);
 	}
-	rseq_slice_sysctl_init();
 	return 0;
 }
 device_initcall(rseq_slice_init);



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 3/5] rseq: Lower default slice extension
  2026-01-21 14:24 [PATCH 0/5] rseq: Various slice-ext changes Peter Zijlstra
  2026-01-21 14:24 ` [PATCH 1/5] rseq: Allow registering RSEQ with slice extension Peter Zijlstra
  2026-01-21 14:24 ` [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs Peter Zijlstra
@ 2026-01-21 14:25 ` Peter Zijlstra
  2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
  2026-01-21 14:25 ` [PATCH 4/5] hrtimer: Fix trace oddity Peter Zijlstra
  2026-01-21 14:25 ` [PATCH 5/5] selftests/rseq: Add rseq slice histogram script Peter Zijlstra
  4 siblings, 1 reply; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 14:25 UTC (permalink / raw)
  To: tglx, mathieu.desnoyers
  Cc: linux-kernel, peterz, paulmck, boqun.feng, corbet,
	prakash.sangappa, vineethr, kprateek.nayak, rostedt, bigeasy,
	arnd, rdunlap, rongevarg, longman

Change the minimum slice extension to 5 usec.

Since slice_test selftest reaches a staggering ~350 nsec extension:

Task: slice_test    Mean: 350.266 ns
  Latency (us)    | Count
  ------------------------------
  EXPIRED         | 238
  0 us            | 143189
  1 us            | 167
  2 us            | 26
  3 us            | 11
  4 us            | 28
  5 us            | 31
  6 us            | 22
  7 us            | 23
  8 us            | 32
  9 us            | 16
  10 us           | 35

Lower the minimal (and default) value to 5 usecs -- which is still massive.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 Documentation/userspace-api/rseq.rst |    2 +-
 kernel/rseq.c                        |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

--- a/Documentation/userspace-api/rseq.rst
+++ b/Documentation/userspace-api/rseq.rst
@@ -79,7 +79,7 @@ slice extension by setting rseq::slice_c
 interrupted and the interrupt results in a reschedule request in the
 kernel, then the kernel can grant a time slice extension and return to
 userspace instead of scheduling out. The length of the extension is
-determined by debugfs:rseq/slice_ext_nsec. The default value is 10 usec; which
+determined by debugfs:rseq/slice_ext_nsec. The default value is 5 usec; which
 is the minimum value. It can be incremented to 50 usecs, however doing so
 can/will affect the minimum scheduling latency.
 
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -519,7 +519,7 @@ struct slice_timer {
 	void		*cookie;
 };
 
-static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
+static const unsigned int rseq_slice_ext_nsecs_min =  5 * NSEC_PER_USEC;
 static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
 unsigned int rseq_slice_ext_nsecs __read_mostly = rseq_slice_ext_nsecs_min;
 static DEFINE_PER_CPU(struct slice_timer, slice_timer);



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 4/5] hrtimer: Fix trace oddity
  2026-01-21 14:24 [PATCH 0/5] rseq: Various slice-ext changes Peter Zijlstra
                   ` (2 preceding siblings ...)
  2026-01-21 14:25 ` [PATCH 3/5] rseq: Lower default slice extension Peter Zijlstra
@ 2026-01-21 14:25 ` Peter Zijlstra
  2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Thomas Gleixner
  2026-01-21 14:25 ` [PATCH 5/5] selftests/rseq: Add rseq slice histogram script Peter Zijlstra
  4 siblings, 1 reply; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 14:25 UTC (permalink / raw)
  To: tglx, mathieu.desnoyers
  Cc: linux-kernel, peterz, paulmck, boqun.feng, corbet,
	prakash.sangappa, vineethr, kprateek.nayak, rostedt, bigeasy,
	arnd, rdunlap, rongevarg, longman

It turns out that __run_hrtimer() will trace like:

          <idle>-0     [032] d.h2. 20705.474563: hrtimer_cancel:       hrtimer=0xff2db8f77f8226e8
          <idle>-0     [032] d.h1. 20705.474563: hrtimer_expire_entry: hrtimer=0xff2db8f77f8226e8 now=20699452001850 function=tick_nohz_handler/0x0

Which is a bit nonsensical, the timer doesn't get canceled on
expiration. The cause is the use of the incorrect debug helper.

Fixes: c6a2a1770245 ("hrtimer: Add tracepoint for hrtimers")
Reported-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 kernel/time/hrtimer.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1750,7 +1750,7 @@ static void __run_hrtimer(struct hrtimer
 
 	lockdep_assert_held(&cpu_base->lock);
 
-	debug_deactivate(timer);
+	debug_hrtimer_deactivate(timer);
 	base->running = timer;
 
 	/*



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 5/5] selftests/rseq: Add rseq slice histogram script
  2026-01-21 14:24 [PATCH 0/5] rseq: Various slice-ext changes Peter Zijlstra
                   ` (3 preceding siblings ...)
  2026-01-21 14:25 ` [PATCH 4/5] hrtimer: Fix trace oddity Peter Zijlstra
@ 2026-01-21 14:25 ` Peter Zijlstra
  2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
  4 siblings, 1 reply; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 14:25 UTC (permalink / raw)
  To: tglx, mathieu.desnoyers
  Cc: linux-kernel, peterz, paulmck, boqun.feng, corbet,
	prakash.sangappa, vineethr, kprateek.nayak, rostedt, bigeasy,
	arnd, rdunlap, rongevarg, longman

A script that processes trace-cmd data and generates a histogram of
rseq slice_ext durations for the recorded workload.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 Documentation/userspace-api/rseq.rst            |    3 
 tools/testing/selftests/rseq/rseq-slice-hist.py |  132 ++++++++++++++++++++++++
 2 files changed, 135 insertions(+)

--- a/Documentation/userspace-api/rseq.rst
+++ b/Documentation/userspace-api/rseq.rst
@@ -83,6 +83,9 @@ determined by debugfs:rseq/slice_ext_nse
 is the minimum value. It can be incremented to 50 usecs, however doing so
 can/will affect the minimum scheduling latency.
 
+Any proposed changes to this default will have to come with a selftest and
+rseq-slice-hist.py output that shows the new value has merrit.
+
 The kernel indicates the grant by clearing rseq::slice_ctrl::request and
 setting rseq::slice_ctrl::granted to 1. If there is a reschedule of the
 thread after granting the extension, the kernel clears the granted bit to
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-slice-hist.py
@@ -0,0 +1,132 @@
+#!/usr/bin/python3
+
+#
+# trace-cmd record -e hrtimer_start -e hrtimer_cancel -e hrtimer_expire_entry -- $cmd
+#
+
+from tracecmd import *
+
+def load_kallsyms(file_path='/proc/kallsyms'):
+    """
+    Parses /proc/kallsyms into a dictionary.
+    Returns: { address_int: symbol_name }
+    """
+    kallsyms_map = {}
+
+    try:
+        with open(file_path, 'r') as f:
+            for line in f:
+                # The format is: [address] [type] [name] [module]
+                parts = line.split()
+                if len(parts) < 3:
+                    continue
+
+                addr = int(parts[0], 16)
+                name = parts[2]
+
+                kallsyms_map[addr] = name
+
+    except PermissionError:
+        print(f"Error: Permission denied reading {file_path}. Try running with sudo.")
+    except FileNotFoundError:
+        print(f"Error: {file_path} not found.")
+
+    return kallsyms_map
+
+ksyms = load_kallsyms()
+
+# pending[timer_ptr] = {'ts': timestamp, 'comm': comm}
+pending = {}
+
+# histograms[comm][bucket] = count
+histograms = {}
+
+class OnlineHarmonicMean:
+    def __init__(self):
+        self.n = 0          # Count of elements
+        self.S = 0.0        # Cumulative sum of reciprocals
+
+    def update(self, x):
+        if x == 0:
+            raise ValueError("Harmonic mean is undefined for zero.")
+
+        self.n += 1
+        self.S += 1.0 / x
+        return self.n / self.S
+
+    @property
+    def mean(self):
+        return self.n / self.S if self.n > 0 else 0
+
+ohms = {}
+
+def handle_start(record):
+    func_name = ksyms[record.num_field("function")]
+    if "rseq_slice_expired" in func_name:
+        timer_ptr = record.num_field("hrtimer")
+        pending[timer_ptr] = {
+            'ts': record.ts,
+            'comm': record.comm
+        }
+    return None
+
+def handle_cancel(record):
+    timer_ptr = record.num_field("hrtimer")
+
+    if timer_ptr in pending:
+        start_data = pending.pop(timer_ptr)
+        duration_ns = record.ts - start_data['ts']
+        duration_us = duration_ns // 1000
+
+        comm = start_data['comm']
+
+        if comm not in ohms:
+            ohms[comm] = OnlineHarmonicMean()
+
+        ohms[comm].update(duration_ns)
+
+        if comm not in histograms:
+            histograms[comm] = {}
+
+        histograms[comm][duration_us] = histograms[comm].get(duration_us, 0) + 1
+    return None
+
+def handle_expire(record):
+    timer_ptr = record.num_field("hrtimer")
+
+    if timer_ptr in pending:
+        start_data = pending.pop(timer_ptr)
+        comm = start_data['comm']
+
+        if comm not in histograms:
+            histograms[comm] = {}
+
+        # Record -1 bucket for expired (failed to cancel)
+        histograms[comm][-1] = histograms[comm].get(-1, 0) + 1
+    return None
+
+if __name__ == "__main__":
+    t = Trace("trace.dat")
+    for cpu in range(0, t.cpus):
+        ev = t.read_event(cpu)
+        while ev:
+            if "hrtimer_start" in ev.name:
+                handle_start(ev)
+            if "hrtimer_cancel" in ev.name:
+                handle_cancel(ev)
+            if "hrtimer_expire_entry" in ev.name:
+                handle_expire(ev)
+
+            ev = t.read_event(cpu)
+
+    print("\n" + "="*40)
+    print("RSEQ SLICE HISTOGRAM (us)")
+    print("="*40)
+    for comm, buckets in histograms.items():
+        print(f"\nTask: {comm}    Mean: {ohms[comm].mean:.3f} ns")
+        print(f"  {'Latency (us)':<15} | {'Count'}")
+        print(f"  {'-'*30}")
+        # Sort buckets numerically, putting -1 at the top
+        for bucket in sorted(buckets.keys()):
+            label = "EXPIRED" if bucket == -1 else f"{bucket} us"
+            print(f"  {label:<15} | {buckets[bucket]}")



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs
  2026-01-21 14:24 ` [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs Peter Zijlstra
@ 2026-01-21 14:50   ` Thomas Weißschuh
  2026-01-21 14:56     ` Peter Zijlstra
  2026-01-21 15:15     ` Peter Zijlstra
  2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
  1 sibling, 2 replies; 14+ messages in thread
From: Thomas Weißschuh @ 2026-01-21 14:50 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: tglx, mathieu.desnoyers, linux-kernel, paulmck, boqun.feng,
	corbet, prakash.sangappa, vineethr, kprateek.nayak, rostedt,
	bigeasy, arnd, rdunlap, rongevarg, longman

On Wed, Jan 21, 2026 at 03:24:59PM +0100, Peter Zijlstra wrote:
> Move changing the slice ext duration to debugfs, a sliglty less permanent
> interface.
> 
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ---

(...)

> --- a/kernel/rseq.c
> +++ b/kernel/rseq.c
> @@ -222,12 +222,16 @@ static const struct file_operations debu
>  	.release	= single_release,
>  };
>  
> +extern void rseq_slice_ext_init(struct dentry *root_dir);

This is actually a static function.

> +
>  static int __init rseq_debugfs_init(void)
>  {
>  	struct dentry *root_dir = debugfs_create_dir("rseq", NULL);
>  
>  	debugfs_create_file("debug", 0644, root_dir, NULL, &debug_ops);
>  	rseq_stats_init(root_dir);
> +	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSIO))

Missing 'N' at the end.

> +		rseq_slice_ext_init(root_dir);
>  	return 0;
>  }
>  __initcall(rseq_debugfs_init);
> @@ -515,7 +519,9 @@ struct slice_timer {
>  	void		*cookie;
>  };

(...)

> +#ifdef CONFIG_DEBUG_FS

(...)

> +#else
> +static void rseq_slice_ext_init(struct dentry *root_dir) { }
> +#endif

It might be possible to just remove the CONFIG_DEBUG_FS ifdeffery and let the
compiler optimize away all of the debugfs-related code automatically.

(...)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs
  2026-01-21 14:50   ` Thomas Weißschuh
@ 2026-01-21 14:56     ` Peter Zijlstra
  2026-01-21 15:15     ` Peter Zijlstra
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 14:56 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: tglx, mathieu.desnoyers, linux-kernel, paulmck, boqun.feng,
	corbet, prakash.sangappa, vineethr, kprateek.nayak, rostedt,
	bigeasy, arnd, rdunlap, rongevarg, longman

On Wed, Jan 21, 2026 at 03:50:55PM +0100, Thomas Weißschuh wrote:
> On Wed, Jan 21, 2026 at 03:24:59PM +0100, Peter Zijlstra wrote:
> > Move changing the slice ext duration to debugfs, a sliglty less permanent
> > interface.
> > 
> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> > ---
> 
> (...)
> 
> > --- a/kernel/rseq.c
> > +++ b/kernel/rseq.c
> > @@ -222,12 +222,16 @@ static const struct file_operations debu
> >  	.release	= single_release,
> >  };
> >  
> > +extern void rseq_slice_ext_init(struct dentry *root_dir);
> 
> This is actually a static function.

Yes, but it is not always defined.

> > +
> >  static int __init rseq_debugfs_init(void)
> >  {
> >  	struct dentry *root_dir = debugfs_create_dir("rseq", NULL);
> >  
> >  	debugfs_create_file("debug", 0644, root_dir, NULL, &debug_ops);
> >  	rseq_stats_init(root_dir);
> > +	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSIO))
> 
> Missing 'N' at the end.

Argh. Some day my editor will tell me this :/

> > +		rseq_slice_ext_init(root_dir);
> >  	return 0;
> >  }
> >  __initcall(rseq_debugfs_init);
> > @@ -515,7 +519,9 @@ struct slice_timer {
> >  	void		*cookie;
> >  };
> 
> (...)
> 
> > +#ifdef CONFIG_DEBUG_FS
> 
> (...)
> 
> > +#else
> > +static void rseq_slice_ext_init(struct dentry *root_dir) { }
> > +#endif
> 
> It might be possible to just remove the CONFIG_DEBUG_FS ifdeffery and let the
> compiler optimize away all of the debugfs-related code automatically.

I'll check.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs
  2026-01-21 14:50   ` Thomas Weißschuh
  2026-01-21 14:56     ` Peter Zijlstra
@ 2026-01-21 15:15     ` Peter Zijlstra
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Zijlstra @ 2026-01-21 15:15 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: tglx, mathieu.desnoyers, linux-kernel, paulmck, boqun.feng,
	corbet, prakash.sangappa, vineethr, kprateek.nayak, rostedt,
	bigeasy, arnd, rdunlap, rongevarg, longman

On Wed, Jan 21, 2026 at 03:50:55PM +0100, Thomas Weißschuh wrote:

> > +#else
> > +static void rseq_slice_ext_init(struct dentry *root_dir) { }
> > +#endif
> 
> It might be possible to just remove the CONFIG_DEBUG_FS ifdeffery and let the
> compiler optimize away all of the debugfs-related code automatically.

Something like the below seems to actually build for SLICE_EXT=y,
DEBUG_FS=n (got there through allnoconfig)

Final image doesn't seem to have the various _ops,_show etc symbols
either.

--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -123,7 +123,6 @@ void __rseq_trace_ip_fixup(unsigned long
 }
 #endif /* CONFIG_TRACEPOINTS */
 
-#ifdef CONFIG_DEBUG_FS
 #ifdef CONFIG_RSEQ_STATS
 DEFINE_PER_CPU(struct rseq_stats, rseq_stats);
 
@@ -222,7 +221,7 @@ static const struct file_operations debu
 	.release	= single_release,
 };
 
-extern void rseq_slice_ext_init(struct dentry *root_dir);
+static void rseq_slice_ext_init(struct dentry *root_dir);
 
 static int __init rseq_debugfs_init(void)
 {
@@ -235,7 +234,6 @@ static int __init rseq_debugfs_init(void
 	return 0;
 }
 __initcall(rseq_debugfs_init);
-#endif /* CONFIG_DEBUG_FS */
 
 static bool rseq_set_ids(struct task_struct *t, struct rseq_ids *ids, u32 node_id)
 {
@@ -767,7 +765,6 @@ SYSCALL_DEFINE0(rseq_slice_yield)
 	return yielded;
 }
 
-#ifdef CONFIG_DEBUG_FS
 static int rseq_slice_ext_show(struct seq_file *m, void *p)
 {
 	seq_printf(m, "%d\n", rseq_slice_ext_nsecs);
@@ -810,9 +807,6 @@ static void rseq_slice_ext_init(struct d
 {
 	debugfs_create_file("slice_ext_nsec", 0644, root_dir, NULL, &slice_ext_ops);
 }
-#else
-static void rseq_slice_ext_init(struct dentry *root_dir) { }
-#endif
 
 static int __init rseq_slice_cmdline(char *str)
 {
@@ -838,4 +832,6 @@ static int __init rseq_slice_init(void)
 	return 0;
 }
 device_initcall(rseq_slice_init);
+#else
+static void rseq_slice_ext_init(struct dentry *root_dir) { }
 #endif /* CONFIG_RSEQ_SLICE_EXTENSION */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [tip: sched/core] selftests/rseq: Add rseq slice histogram script
  2026-01-21 14:25 ` [PATCH 5/5] selftests/rseq: Add rseq slice histogram script Peter Zijlstra
@ 2026-01-22 10:15   ` tip-bot2 for Peter Zijlstra
  0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2026-01-22 10:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the sched/core branch of tip:

Commit-ID:     bb332a9e5a057d2cb9b90e307b26cce9b1f6f660
Gitweb:        https://git.kernel.org/tip/bb332a9e5a057d2cb9b90e307b26cce9b1f6f660
Author:        Peter Zijlstra <peterz@infradead.org>
AuthorDate:    Wed, 21 Jan 2026 15:10:29 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 22 Jan 2026 11:11:20 +01:00

selftests/rseq: Add rseq slice histogram script

A script that processes trace-cmd data and generates a histogram of
rseq slice_ext durations for the recorded workload.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260121143208.340549136@infradead.org
---
 Documentation/userspace-api/rseq.rst            |   3 +-
 tools/testing/selftests/rseq/rseq-slice-hist.py | 132 +++++++++++++++-
 2 files changed, 135 insertions(+)
 create mode 100644 tools/testing/selftests/rseq/rseq-slice-hist.py

diff --git a/Documentation/userspace-api/rseq.rst b/Documentation/userspace-api/rseq.rst
index 468f6bb..3cd27a3 100644
--- a/Documentation/userspace-api/rseq.rst
+++ b/Documentation/userspace-api/rseq.rst
@@ -83,6 +83,9 @@ determined by debugfs:rseq/slice_ext_nsec. The default value is 5 usec; which
 is the minimum value. It can be incremented to 50 usecs, however doing so
 can/will affect the minimum scheduling latency.
 
+Any proposed changes to this default will have to come with a selftest and
+rseq-slice-hist.py output that shows the new value has merrit.
+
 The kernel indicates the grant by clearing rseq::slice_ctrl::request and
 setting rseq::slice_ctrl::granted to 1. If there is a reschedule of the
 thread after granting the extension, the kernel clears the granted bit to
diff --git a/tools/testing/selftests/rseq/rseq-slice-hist.py b/tools/testing/selftests/rseq/rseq-slice-hist.py
new file mode 100644
index 0000000..b7933ee
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-slice-hist.py
@@ -0,0 +1,132 @@
+#!/usr/bin/python3
+
+#
+# trace-cmd record -e hrtimer_start -e hrtimer_cancel -e hrtimer_expire_entry -- $cmd
+#
+
+from tracecmd import *
+
+def load_kallsyms(file_path='/proc/kallsyms'):
+    """
+    Parses /proc/kallsyms into a dictionary.
+    Returns: { address_int: symbol_name }
+    """
+    kallsyms_map = {}
+
+    try:
+        with open(file_path, 'r') as f:
+            for line in f:
+                # The format is: [address] [type] [name] [module]
+                parts = line.split()
+                if len(parts) < 3:
+                    continue
+
+                addr = int(parts[0], 16)
+                name = parts[2]
+
+                kallsyms_map[addr] = name
+
+    except PermissionError:
+        print(f"Error: Permission denied reading {file_path}. Try running with sudo.")
+    except FileNotFoundError:
+        print(f"Error: {file_path} not found.")
+
+    return kallsyms_map
+
+ksyms = load_kallsyms()
+
+# pending[timer_ptr] = {'ts': timestamp, 'comm': comm}
+pending = {}
+
+# histograms[comm][bucket] = count
+histograms = {}
+
+class OnlineHarmonicMean:
+    def __init__(self):
+        self.n = 0          # Count of elements
+        self.S = 0.0        # Cumulative sum of reciprocals
+
+    def update(self, x):
+        if x == 0:
+            raise ValueError("Harmonic mean is undefined for zero.")
+
+        self.n += 1
+        self.S += 1.0 / x
+        return self.n / self.S
+
+    @property
+    def mean(self):
+        return self.n / self.S if self.n > 0 else 0
+
+ohms = {}
+
+def handle_start(record):
+    func_name = ksyms[record.num_field("function")]
+    if "rseq_slice_expired" in func_name:
+        timer_ptr = record.num_field("hrtimer")
+        pending[timer_ptr] = {
+            'ts': record.ts,
+            'comm': record.comm
+        }
+    return None
+
+def handle_cancel(record):
+    timer_ptr = record.num_field("hrtimer")
+
+    if timer_ptr in pending:
+        start_data = pending.pop(timer_ptr)
+        duration_ns = record.ts - start_data['ts']
+        duration_us = duration_ns // 1000
+
+        comm = start_data['comm']
+
+        if comm not in ohms:
+            ohms[comm] = OnlineHarmonicMean()
+
+        ohms[comm].update(duration_ns)
+
+        if comm not in histograms:
+            histograms[comm] = {}
+
+        histograms[comm][duration_us] = histograms[comm].get(duration_us, 0) + 1
+    return None
+
+def handle_expire(record):
+    timer_ptr = record.num_field("hrtimer")
+
+    if timer_ptr in pending:
+        start_data = pending.pop(timer_ptr)
+        comm = start_data['comm']
+
+        if comm not in histograms:
+            histograms[comm] = {}
+
+        # Record -1 bucket for expired (failed to cancel)
+        histograms[comm][-1] = histograms[comm].get(-1, 0) + 1
+    return None
+
+if __name__ == "__main__":
+    t = Trace("trace.dat")
+    for cpu in range(0, t.cpus):
+        ev = t.read_event(cpu)
+        while ev:
+            if "hrtimer_start" in ev.name:
+                handle_start(ev)
+            if "hrtimer_cancel" in ev.name:
+                handle_cancel(ev)
+            if "hrtimer_expire_entry" in ev.name:
+                handle_expire(ev)
+
+            ev = t.read_event(cpu)
+
+    print("\n" + "="*40)
+    print("RSEQ SLICE HISTOGRAM (us)")
+    print("="*40)
+    for comm, buckets in histograms.items():
+        print(f"\nTask: {comm}    Mean: {ohms[comm].mean:.3f} ns")
+        print(f"  {'Latency (us)':<15} | {'Count'}")
+        print(f"  {'-'*30}")
+        # Sort buckets numerically, putting -1 at the top
+        for bucket in sorted(buckets.keys()):
+            label = "EXPIRED" if bucket == -1 else f"{bucket} us"
+            print(f"  {label:<15} | {buckets[bucket]}")

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [tip: sched/core] hrtimer: Fix trace oddity
  2026-01-21 14:25 ` [PATCH 4/5] hrtimer: Fix trace oddity Peter Zijlstra
@ 2026-01-22 10:15   ` tip-bot2 for Thomas Gleixner
  0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2026-01-22 10:15 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Peter Zijlstra (Intel), Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the sched/core branch of tip:

Commit-ID:     5d6446f409da00e5a389125ddb5ce09f5bc404c9
Gitweb:        https://git.kernel.org/tip/5d6446f409da00e5a389125ddb5ce09f5bc404c9
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 Jan 2026 11:38:34 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 22 Jan 2026 11:11:20 +01:00

hrtimer: Fix trace oddity

It turns out that __run_hrtimer() will trace like:

          <idle>-0     [032] d.h2. 20705.474563: hrtimer_cancel:       hrtimer=0xff2db8f77f8226e8
          <idle>-0     [032] d.h1. 20705.474563: hrtimer_expire_entry: hrtimer=0xff2db8f77f8226e8 now=20699452001850 function=tick_nohz_handler/0x0

Which is a bit nonsensical, the timer doesn't get canceled on
expiration. The cause is the use of the incorrect debug helper.

Fixes: c6a2a1770245 ("hrtimer: Add tracepoint for hrtimers")
Reported-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260121143208.219595606@infradead.org
---
 kernel/time/hrtimer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index f8ea8c8..d8935ab 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1742,7 +1742,7 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
 
 	lockdep_assert_held(&cpu_base->lock);
 
-	debug_deactivate(timer);
+	debug_hrtimer_deactivate(timer);
 	base->running = timer;
 
 	/*

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [tip: sched/core] rseq: Lower default slice extension
  2026-01-21 14:25 ` [PATCH 3/5] rseq: Lower default slice extension Peter Zijlstra
@ 2026-01-22 10:15   ` tip-bot2 for Peter Zijlstra
  0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2026-01-22 10:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the sched/core branch of tip:

Commit-ID:     21c0e92d0681fbd10ac024311bd09bca439e0bb1
Gitweb:        https://git.kernel.org/tip/21c0e92d0681fbd10ac024311bd09bca439e0bb1
Author:        Peter Zijlstra <peterz@infradead.org>
AuthorDate:    Wed, 21 Jan 2026 14:25:04 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 22 Jan 2026 11:11:20 +01:00

rseq: Lower default slice extension

Change the minimum slice extension to 5 usec.

Since slice_test selftest reaches a staggering ~350 nsec extension:

Task: slice_test    Mean: 350.266 ns
  Latency (us)    | Count
  ------------------------------
  EXPIRED         | 238
  0 us            | 143189
  1 us            | 167
  2 us            | 26
  3 us            | 11
  4 us            | 28
  5 us            | 31
  6 us            | 22
  7 us            | 23
  8 us            | 32
  9 us            | 16
  10 us           | 35

Lower the minimal (and default) value to 5 usecs -- which is still massive.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260121143208.073200729@infradead.org
---
 Documentation/userspace-api/rseq.rst | 2 +-
 kernel/rseq.c                        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/userspace-api/rseq.rst b/Documentation/userspace-api/rseq.rst
index 29af6c3..468f6bb 100644
--- a/Documentation/userspace-api/rseq.rst
+++ b/Documentation/userspace-api/rseq.rst
@@ -79,7 +79,7 @@ slice extension by setting rseq::slice_ctrl::request to 1. If the thread is
 interrupted and the interrupt results in a reschedule request in the
 kernel, then the kernel can grant a time slice extension and return to
 userspace instead of scheduling out. The length of the extension is
-determined by debugfs:rseq/slice_ext_nsec. The default value is 10 usec; which
+determined by debugfs:rseq/slice_ext_nsec. The default value is 5 usec; which
 is the minimum value. It can be incremented to 50 usecs, however doing so
 can/will affect the minimum scheduling latency.
 
diff --git a/kernel/rseq.c b/kernel/rseq.c
index e423a9b..b0973d1 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -517,7 +517,7 @@ struct slice_timer {
 	void		*cookie;
 };
 
-static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
+static const unsigned int rseq_slice_ext_nsecs_min =  5 * NSEC_PER_USEC;
 static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
 unsigned int rseq_slice_ext_nsecs __read_mostly = rseq_slice_ext_nsecs_min;
 static DEFINE_PER_CPU(struct slice_timer, slice_timer);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [tip: sched/core] rseq: Move slice_ext_nsec to debugfs
  2026-01-21 14:24 ` [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs Peter Zijlstra
  2026-01-21 14:50   ` Thomas Weißschuh
@ 2026-01-22 10:15   ` tip-bot2 for Peter Zijlstra
  1 sibling, 0 replies; 14+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2026-01-22 10:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the sched/core branch of tip:

Commit-ID:     e1d7f54900f1e1d3003a85b78cd7105a64203ff7
Gitweb:        https://git.kernel.org/tip/e1d7f54900f1e1d3003a85b78cd7105a64203ff7
Author:        Peter Zijlstra <peterz@infradead.org>
AuthorDate:    Wed, 21 Jan 2026 14:21:51 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 22 Jan 2026 11:11:20 +01:00

rseq: Move slice_ext_nsec to debugfs

Move changing the slice ext duration to debugfs, a sliglty less permanent
interface.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260121143207.923520192@infradead.org
---
 Documentation/admin-guide/sysctl/kernel.rst | 11 +---
 Documentation/userspace-api/rseq.rst        |  4 +-
 kernel/rseq.c                               | 69 +++++++++++++-------
 3 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
index b09d18e..239da22 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -1248,17 +1248,6 @@ reboot-cmd (SPARC only)
 ROM/Flash boot loader. Maybe to tell it what to do after
 rebooting. ???
 
-rseq_slice_extension_nsec
-=========================
-
-A task can request to delay its scheduling if it is in a critical section
-via the prctl(PR_RSEQ_SLICE_EXTENSION_SET) mechanism. This sets the maximum
-allowed extension in nanoseconds before scheduling of the task is enforced.
-Default value is 10000ns (10us). The possible range is 10000ns (10us) to
-50000ns (50us).
-
-This value has a direct correlation to the worst case scheduling latency;
-increment at your own risk.
 
 sched_energy_aware
 ==================
diff --git a/Documentation/userspace-api/rseq.rst b/Documentation/userspace-api/rseq.rst
index e1fdb0d..29af6c3 100644
--- a/Documentation/userspace-api/rseq.rst
+++ b/Documentation/userspace-api/rseq.rst
@@ -79,7 +79,9 @@ slice extension by setting rseq::slice_ctrl::request to 1. If the thread is
 interrupted and the interrupt results in a reschedule request in the
 kernel, then the kernel can grant a time slice extension and return to
 userspace instead of scheduling out. The length of the extension is
-determined by the ``rseq_slice_extension_nsec`` sysctl.
+determined by debugfs:rseq/slice_ext_nsec. The default value is 10 usec; which
+is the minimum value. It can be incremented to 50 usecs, however doing so
+can/will affect the minimum scheduling latency.
 
 The kernel indicates the grant by clearing rseq::slice_ctrl::request and
 setting rseq::slice_ctrl::granted to 1. If there is a reschedule of the
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 1c5490a..e423a9b 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -123,7 +123,6 @@ void __rseq_trace_ip_fixup(unsigned long ip, unsigned long start_ip,
 }
 #endif /* CONFIG_TRACEPOINTS */
 
-#ifdef CONFIG_DEBUG_FS
 #ifdef CONFIG_RSEQ_STATS
 DEFINE_PER_CPU(struct rseq_stats, rseq_stats);
 
@@ -222,16 +221,19 @@ static const struct file_operations debug_ops = {
 	.release	= single_release,
 };
 
+static void rseq_slice_ext_init(struct dentry *root_dir);
+
 static int __init rseq_debugfs_init(void)
 {
 	struct dentry *root_dir = debugfs_create_dir("rseq", NULL);
 
 	debugfs_create_file("debug", 0644, root_dir, NULL, &debug_ops);
 	rseq_stats_init(root_dir);
+	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION))
+		rseq_slice_ext_init(root_dir);
 	return 0;
 }
 __initcall(rseq_debugfs_init);
-#endif /* CONFIG_DEBUG_FS */
 
 static bool rseq_set_ids(struct task_struct *t, struct rseq_ids *ids, u32 node_id)
 {
@@ -515,7 +517,9 @@ struct slice_timer {
 	void		*cookie;
 };
 
-unsigned int rseq_slice_ext_nsecs __read_mostly = 10 * NSEC_PER_USEC;
+static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
+static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
+unsigned int rseq_slice_ext_nsecs __read_mostly = rseq_slice_ext_nsecs_min;
 static DEFINE_PER_CPU(struct slice_timer, slice_timer);
 DEFINE_STATIC_KEY_TRUE(rseq_slice_extension_key);
 
@@ -761,30 +765,48 @@ SYSCALL_DEFINE0(rseq_slice_yield)
 	return yielded;
 }
 
-#ifdef CONFIG_SYSCTL
-static const unsigned int rseq_slice_ext_nsecs_min = 10 * NSEC_PER_USEC;
-static const unsigned int rseq_slice_ext_nsecs_max = 50 * NSEC_PER_USEC;
+static int rseq_slice_ext_show(struct seq_file *m, void *p)
+{
+	seq_printf(m, "%d\n", rseq_slice_ext_nsecs);
+	return 0;
+}
+
+static ssize_t rseq_slice_ext_write(struct file *file, const char __user *ubuf,
+				    size_t count, loff_t *ppos)
+{
+	unsigned int nsecs;
+
+	if (kstrtouint_from_user(ubuf, count, 10, &nsecs))
+		return -EINVAL;
+
+	if (nsecs < rseq_slice_ext_nsecs_min)
+		return -ERANGE;
 
-static const struct ctl_table rseq_slice_ext_sysctl[] = {
-	{
-		.procname	= "rseq_slice_extension_nsec",
-		.data		= &rseq_slice_ext_nsecs,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_douintvec_minmax,
-		.extra1		= (unsigned int *)&rseq_slice_ext_nsecs_min,
-		.extra2		= (unsigned int *)&rseq_slice_ext_nsecs_max,
-	},
+	if (nsecs > rseq_slice_ext_nsecs_max)
+		return -ERANGE;
+
+	rseq_slice_ext_nsecs = nsecs;
+
+	return count;
+}
+
+static int rseq_slice_ext_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rseq_slice_ext_show, inode->i_private);
+}
+
+static const struct file_operations slice_ext_ops = {
+	.open		= rseq_slice_ext_open,
+	.read		= seq_read,
+	.write		= rseq_slice_ext_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
 };
 
-static void rseq_slice_sysctl_init(void)
+static void rseq_slice_ext_init(struct dentry *root_dir)
 {
-	if (rseq_slice_extension_enabled())
-		register_sysctl_init("kernel", rseq_slice_ext_sysctl);
+	debugfs_create_file("slice_ext_nsec", 0644, root_dir, NULL, &slice_ext_ops);
 }
-#else /* CONFIG_SYSCTL */
-static inline void rseq_slice_sysctl_init(void) { }
-#endif  /* !CONFIG_SYSCTL */
 
 static int __init rseq_slice_cmdline(char *str)
 {
@@ -807,8 +829,9 @@ static int __init rseq_slice_init(void)
 		hrtimer_setup(per_cpu_ptr(&slice_timer.timer, cpu), rseq_slice_expired,
 			      CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED_HARD);
 	}
-	rseq_slice_sysctl_init();
 	return 0;
 }
 device_initcall(rseq_slice_init);
+#else
+static void rseq_slice_ext_init(struct dentry *root_dir) { }
 #endif /* CONFIG_RSEQ_SLICE_EXTENSION */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [tip: sched/core] rseq: Allow registering RSEQ with slice extension
  2026-01-21 14:24 ` [PATCH 1/5] rseq: Allow registering RSEQ with slice extension Peter Zijlstra
@ 2026-01-22 10:15   ` tip-bot2 for Peter Zijlstra
  0 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2026-01-22 10:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the sched/core branch of tip:

Commit-ID:     d6200245c75e832af2087bc60ba2e6641a90eee9
Gitweb:        https://git.kernel.org/tip/d6200245c75e832af2087bc60ba2e6641a90eee9
Author:        Peter Zijlstra <peterz@infradead.org>
AuthorDate:    Mon, 19 Jan 2026 11:23:57 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 22 Jan 2026 11:11:19 +01:00

rseq: Allow registering RSEQ with slice extension

Since glibc cares about the number of syscalls required to initialize a new
thread, allow initializing rseq with slice extension on. This avoids having to
do another prctl().

Requested-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260121143207.814193010@infradead.org
---
 include/uapi/linux/rseq.h |  3 ++-
 kernel/rseq.c             | 12 ++++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
index 6afc219..863c4a0 100644
--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -19,7 +19,8 @@ enum rseq_cpu_id_state {
 };
 
 enum rseq_flags {
-	RSEQ_FLAG_UNREGISTER = (1 << 0),
+	RSEQ_FLAG_UNREGISTER			= (1 << 0),
+	RSEQ_FLAG_SLICE_EXT_DEFAULT_ON		= (1 << 1),
 };
 
 enum rseq_cs_flags_bit {
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 275d701..1c5490a 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -424,7 +424,7 @@ SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32
 		return 0;
 	}
 
-	if (unlikely(flags))
+	if (unlikely(flags & ~(RSEQ_FLAG_SLICE_EXT_DEFAULT_ON)))
 		return -EINVAL;
 
 	if (current->rseq.usrptr) {
@@ -459,8 +459,12 @@ SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32
 	if (!access_ok(rseq, rseq_len))
 		return -EFAULT;
 
-	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION))
+	if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION)) {
 		rseqfl |= RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE;
+		if (rseq_slice_extension_enabled() &&
+		    (flags & RSEQ_FLAG_SLICE_EXT_DEFAULT_ON))
+			rseqfl |= RSEQ_CS_FLAG_SLICE_EXT_ENABLED;
+	}
 
 	scoped_user_write_access(rseq, efault) {
 		/*
@@ -488,6 +492,10 @@ SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32
 	current->rseq.len = rseq_len;
 	current->rseq.sig = sig;
 
+#ifdef CONFIG_RSEQ_SLICE_EXTENSION
+	current->rseq.slice.state.enabled = !!(rseqfl & RSEQ_CS_FLAG_SLICE_EXT_ENABLED);
+#endif
+
 	/*
 	 * If rseq was previously inactive, and has just been
 	 * registered, ensure the cpu_id_start and cpu_id fields

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-01-22 10:15 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-21 14:24 [PATCH 0/5] rseq: Various slice-ext changes Peter Zijlstra
2026-01-21 14:24 ` [PATCH 1/5] rseq: Allow registering RSEQ with slice extension Peter Zijlstra
2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
2026-01-21 14:24 ` [PATCH 2/5] rseq: Move slice_ext_nsec to debugfs Peter Zijlstra
2026-01-21 14:50   ` Thomas Weißschuh
2026-01-21 14:56     ` Peter Zijlstra
2026-01-21 15:15     ` Peter Zijlstra
2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
2026-01-21 14:25 ` [PATCH 3/5] rseq: Lower default slice extension Peter Zijlstra
2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
2026-01-21 14:25 ` [PATCH 4/5] hrtimer: Fix trace oddity Peter Zijlstra
2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Thomas Gleixner
2026-01-21 14:25 ` [PATCH 5/5] selftests/rseq: Add rseq slice histogram script Peter Zijlstra
2026-01-22 10:15   ` [tip: sched/core] " tip-bot2 for Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®