Linux Trace Kernel
 help / color / mirror / Atom feed
From: "Paul E. McKenney" <paulmck@kernel.org>
To: Josef Bacik <josef@toxicpanda.com>
Cc: Frederic Weisbecker <frederic@kernel.org>,
	Neeraj Upadhyay <neeraj.upadhyay@kernel.org>,
	Joel Fernandes <joelagnelf@nvidia.com>,
	Boqun Feng <boqun@kernel.org>, Thomas Gleixner <tglx@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>, Jiri Olsa <jolsa@kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	x86@kernel.org, Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,
	Puranjay Mohan <puranjay@kernel.org>,
	Xu Kuohai <xukuohai@huaweicloud.com>,
	Andy Lutomirski <luto@kernel.org>,
	Josh Triplett <josh@joshtriplett.org>,
	Uladzislau Rezki <urezki@gmail.com>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
	Lai Jiangshan <jiangshanlai@gmail.com>,
	Zqiang <qiang.zhang@linux.dev>, Juergen Gross <jgross@suse.com>,
	Luis Chamberlain <mcgrof@kernel.org>,
	Ihor Solodrai <ihor.solodrai@linux.dev>,
	linux-kernel@vger.kernel.org, rcu@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	xen-devel@lists.xenproject.org
Subject: Re: [PATCH RFC v2 01/15] rcu-tasks: Add per-task trampoline nesting count
Date: Fri, 11 Sep 2026 10:23:16 -0700	[thread overview]
Message-ID: <90c2dfbe-e796-4125-b178-e854b40f68cd@paulmck-laptop> (raw)
In-Reply-To: <20260911-b4-rcu-tasks-preempt-qs-v2-1-eaaa61ed2da4@toxicpanda.com>

On Fri, Sep 11, 2026 at 02:08:39PM +0000, Josef Bacik wrote:
> Tasks RCU exists so that ftrace, BPF and kprobes can free trampoline
> text once no task can still be executing in it.  Today the only way a
> task tells Tasks RCU "I am not in a trampoline" is a voluntary context
> switch, so a preempted task is always assumed to be inside one.
> 
> Add task_struct::rcu_tramp_nesting so that trampolines can say so
> directly: a trampoline increments it before calling out and decrements
> it before returning, and while it is non-zero the task must not be
> treated as Tasks-RCU quiescent.  Provide rcu_tasks_trampoline_enter()
> and rcu_tasks_trampoline_exit() for C users, report the count in the
> Tasks RCU stall output, and, under CONFIG_PROVE_RCU, assert that it is
> zero on every return to userspace since no task can legitimately reach
> userspace with a trampoline on its stack.
> 
> Only current ever writes the count and every nested user (interrupts
> running their own trampolines) is balanced, so plain accesses suffice.
> 
> The callbacks reached from static trampolines (return_to_handler, the
> rethook and kretprobe trampolines) are covered by the preempt_disable()
> in the ftrace recursion protection rather than by the count; note that
> dependency in trace_recursion.h so it is not lost if the
> preempt_disable() is ever removed from there.
> 
> Nothing increments the count and nothing consults it for quiescent-state
> decisions yet; both come in later patches.
> 
> Assisted-by: LLM
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Please see below for a line-saving nit.

							Thanx, Paul

> ---
>  include/linux/irq-entry-common.h |  2 ++
>  include/linux/rcupdate.h         | 37 +++++++++++++++++++++++++++++++++++++
>  include/linux/sched.h            |  1 +
>  include/linux/trace_recursion.h  | 11 +++++++++++
>  kernel/fork.c                    |  1 +
>  kernel/rcu/tasks.h               |  3 ++-
>  6 files changed, 54 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
> index 0bb6c03481fa..8da571622000 100644
> --- a/include/linux/irq-entry-common.h
> +++ b/include/linux/irq-entry-common.h
> @@ -5,6 +5,7 @@
>  #include <linux/context_tracking.h>
>  #include <linux/hrtimer_rearm.h>
>  #include <linux/kmsan.h>
> +#include <linux/rcupdate.h>
>  #include <linux/rseq_entry.h>
>  #include <linux/static_call_types.h>
>  #include <linux/syscalls.h>
> @@ -214,6 +215,7 @@ static __always_inline void __exit_to_user_mode_validate(void)
>  {
>  	/* Ensure that kernel state is sane for a return to userspace */
>  	kmap_assert_nomap();
> +	rcu_tasks_trampoline_assert_none();
>  	lockdep_assert_irqs_disabled();
>  	lockdep_sys_exit();
>  }
> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> index 44c07a66edff..b5c666c82479 100644
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -180,6 +180,37 @@ static inline void rcu_nocb_flush_deferred_wakeup(void) { }
>  #ifdef CONFIG_TASKS_RCU_GENERIC
>  
>  # ifdef CONFIG_TASKS_RCU
> +
> +/*
> + * Trampoline nesting: dynamically allocated text (ftrace trampolines, BPF
> + * trampoline images, kprobe optinsn slots) that relies on Tasks RCU for its
> + * lifetime brackets itself with an increment/decrement of
> + * current->rcu_tramp_nesting.  While the count is non-zero the task is inside,
> + * or was called from, such text and an involuntary context switch must not be
> + * treated as a Tasks RCU quiescent state.
> + *
> + * Only current writes the count and only current (or an interrupt on the same
> + * CPU) reads it, so plain accesses suffice.
> + */
> +static __always_inline void rcu_tasks_trampoline_enter(void)
> +{
> +	current->rcu_tramp_nesting++;
> +	barrier();
> +}
> +
> +static __always_inline void rcu_tasks_trampoline_exit(void)
> +{
> +	barrier();
> +	current->rcu_tramp_nesting--;
> +}
> +
> +/* A task must never reach userspace with a trampoline on its stack. */
> +static __always_inline void rcu_tasks_trampoline_assert_none(void)
> +{
> +	if (IS_ENABLED(CONFIG_PROVE_RCU))
> +		WARN_ON_ONCE(current->rcu_tramp_nesting);

Save a line as follows?

	WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && current->rcu_tramp_nesting);

> +}
> +
>  # define rcu_tasks_classic_qs(t, preempt)				\
>  	do {								\
>  		if (!(preempt) && READ_ONCE((t)->rcu_tasks_holdout))	\
> @@ -192,6 +223,9 @@ void rcu_tasks_torture_stats_print(char *tt, char *tf);
>  # define rcu_tasks_classic_qs(t, preempt) do { } while (0)
>  # define call_rcu_tasks call_rcu
>  # define synchronize_rcu_tasks synchronize_rcu
> +static inline void rcu_tasks_trampoline_enter(void) { }
> +static inline void rcu_tasks_trampoline_exit(void) { }
> +static inline void rcu_tasks_trampoline_assert_none(void) { }
>  # endif
>  
>  #define rcu_tasks_qs(t, preempt) rcu_tasks_classic_qs((t), (preempt))
> @@ -208,6 +242,9 @@ void exit_tasks_rcu_finish(void);
>  #define rcu_tasks_classic_qs(t, preempt) do { } while (0)
>  #define rcu_tasks_qs(t, preempt) do { } while (0)
>  #define rcu_note_voluntary_context_switch(t) do { } while (0)
> +static inline void rcu_tasks_trampoline_enter(void) { }
> +static inline void rcu_tasks_trampoline_exit(void) { }
> +static inline void rcu_tasks_trampoline_assert_none(void) { }
>  #define call_rcu_tasks call_rcu
>  #define synchronize_rcu_tasks synchronize_rcu
>  static inline void exit_tasks_rcu_start(void) { }
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 8b3d47a325cc..d2e7b1b3c9d2 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -956,6 +956,7 @@ struct task_struct {
>  	unsigned long			rcu_tasks_nvcsw;
>  	u8				rcu_tasks_holdout;
>  	u8				rcu_tasks_idx;
> +	int				rcu_tramp_nesting;
>  	int				rcu_tasks_idle_cpu;
>  	struct list_head		rcu_tasks_holdout_list;
>  	int				rcu_tasks_exit_cpu;
> diff --git a/include/linux/trace_recursion.h b/include/linux/trace_recursion.h
> index e6ca052b2a85..2da23a52ca4a 100644
> --- a/include/linux/trace_recursion.h
> +++ b/include/linux/trace_recursion.h
> @@ -153,6 +153,17 @@ static __always_inline int trace_test_and_set_recursion(unsigned long ip, unsign
>  	current->trace_recursion = val;
>  	barrier();
>  
> +	/*
> +	 * Callbacks reached from static trampoline text (return_to_handler,
> +	 * the rethook and kretprobe trampolines) do not maintain
> +	 * current->rcu_tramp_nesting themselves; they rely on this
> +	 * preempt_disable() to keep the task from being preempted, and thus
> +	 * from reporting a Tasks RCU quiescent state, while an ftrace_ops or
> +	 * its data is in use.  If the preempt_disable() is ever removed from
> +	 * the recursion protection, this must rcu_tasks_trampoline_enter()
> +	 * here and rcu_tasks_trampoline_exit() in trace_clear_recursion()
> +	 * instead.  See CONFIG_RCU_TASKS_PREEMPT_QS.
> +	 */
>  	preempt_disable_notrace();
>  
>  	return bit;
> diff --git a/kernel/fork.c b/kernel/fork.c
> index 416758c8a3d4..cfe3a8e53fbd 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1869,6 +1869,7 @@ static inline void rcu_copy_process(struct task_struct *p)
>  #endif /* #ifdef CONFIG_PREEMPT_RCU */
>  #ifdef CONFIG_TASKS_RCU
>  	p->rcu_tasks_holdout = false;
> +	p->rcu_tramp_nesting = 0;
>  	INIT_LIST_HEAD(&p->rcu_tasks_holdout_list);
>  	p->rcu_tasks_idle_cpu = -1;
>  	INIT_LIST_HEAD(&p->rcu_tasks_exit_list);
> diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
> index 627295396cd9..1662ba18bf34 100644
> --- a/kernel/rcu/tasks.h
> +++ b/kernel/rcu/tasks.h
> @@ -1113,10 +1113,11 @@ static void check_holdout_task(struct task_struct *t,
>  		*firstreport = false;
>  	}
>  	cpu = task_cpu(t);
> -	pr_alert("%p: %c%c nvcsw: %lu/%lu holdout: %d idle_cpu: %d/%d\n",
> +	pr_alert("%p: %c%c nvcsw: %lu/%lu holdout: %d tramp_nesting: %d idle_cpu: %d/%d\n",
>  		 t, ".I"[is_idle_task(t)],
>  		 "N."[cpu < 0 || !tick_nohz_full_cpu(cpu)],
>  		 t->rcu_tasks_nvcsw, t->nvcsw, t->rcu_tasks_holdout,
> +		 data_race(t->rcu_tramp_nesting),
>  		 data_race(t->rcu_tasks_idle_cpu), cpu);
>  	sched_show_task(t);
>  }
> 
> -- 
> 2.55.0
> 

  reply	other threads:[~2026-09-11 17:23 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-11 14:08 [PATCH RFC v2 00/15] rcu-tasks: let preemption outside trampolines be a quiescent state Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 01/15] rcu-tasks: Add per-task trampoline nesting count Josef Bacik
2026-09-11 17:23   ` Paul E. McKenney [this message]
2026-09-11 14:08 ` [PATCH RFC v2 02/15] entry: Pass pt_regs to irqentry_exit_cond_resched() Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 03/15] rcu-tasks: Hold trampoline nesting across irq-exit preemption in trampoline text Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 04/15] kprobes: Let Tasks RCU recognise tasks preempted in an optprobe jump window Josef Bacik
2026-09-11 14:26   ` sashiko-bot
2026-09-11 17:27     ` Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 05/15] ftrace: Mark modules hosting direct-call trampolines for Tasks RCU Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 06/15] x86/ftrace: Maintain Tasks RCU trampoline nesting in ftrace_caller Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 07/15] x86/kprobes: Maintain Tasks RCU trampoline nesting in the optprobe template Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 08/15] bpf, x86: Maintain Tasks RCU trampoline nesting in the BPF trampoline Josef Bacik
2026-09-12  3:27   ` Alexei Starovoitov
2026-09-12  5:10     ` Paul E. McKenney
2026-09-12 17:18       ` Alexei Starovoitov
2026-09-12 18:03         ` Paul E. McKenney
2026-09-12 19:40           ` Alexei Starovoitov
2026-09-12 22:28             ` Paul E. McKenney
2026-09-12 23:59               ` Alexei Starovoitov
2026-09-13  3:07                 ` Paul E. McKenney
2026-09-12 21:14           ` David Laight
2026-09-12 22:31             ` Paul E. McKenney
2026-09-13 11:28               ` David Laight
2026-09-13 18:20                 ` Paul E. McKenney
2026-09-11 14:08 ` [PATCH RFC v2 09/15] arm64: ftrace: Maintain Tasks RCU trampoline nesting in ftrace_caller Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 10/15] bpf, arm64: Maintain Tasks RCU trampoline nesting in the BPF trampoline Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 11/15] samples: ftrace: Maintain Tasks RCU trampoline nesting in direct-call trampolines Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 12/15] rcutorture: Bracket Tasks RCU readers with trampoline nesting Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 13/15] rcu-tasks: Treat preemption outside trampolines as a quiescent state Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 14/15] rcu-tasks: Retire switched-out tasks with no trampoline nesting at scan time Josef Bacik
2026-09-11 14:08 ` [PATCH RFC v2 15/15] rcu-tasks: Kick running holdouts through the scheduler Josef Bacik
2026-09-11 18:46   ` Paul E. McKenney
2026-09-13  7:13 ` [PATCH RFC v2 00/15] rcu-tasks: let preemption outside trampolines be a quiescent state Yafang Shao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=90c2dfbe-e796-4125-b178-e854b40f68cd@paulmck-laptop \
    --to=paulmck@kernel.org \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=boqun@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=daniel@iogearbox.net \
    --cc=frederic@kernel.org \
    --cc=ihor.solodrai@linux.dev \
    --cc=jgross@suse.com \
    --cc=jiangshanlai@gmail.com \
    --cc=joelagnelf@nvidia.com \
    --cc=jolsa@kernel.org \
    --cc=josef@toxicpanda.com \
    --cc=josh@joshtriplett.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mcgrof@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=neeraj.upadhyay@kernel.org \
    --cc=peterz@infradead.org \
    --cc=puranjay@kernel.org \
    --cc=qiang.zhang@linux.dev \
    --cc=rcu@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@kernel.org \
    --cc=urezki@gmail.com \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    --cc=xukuohai@huaweicloud.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox