summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorKunwu Chan <kunwu.chan@gmail.com>2026-09-14 17:34:19 +0800
committerPaul E. McKenney <paulmck@kernel.org>2026-10-01 17:21:08 -0700
commit92747742d660f52ecccb71cd5f8ff93e27db265a (patch)
tree1aa06a8da119358dbdb734192ab9ac593bfbbbaf /kernel
parent7743179aaa22b6ecb499dbb7fdb4207c8fce6f3e (diff)
downloadlinux-next-92747742d660f52ecccb71cd5f8ff93e27db265a.tar.gz
linux-next-92747742d660f52ecccb71cd5f8ff93e27db265a.zip
rcutorture: Add atomic SRCU cross-CPU IRQ context mismatch test
Add testtype 7 to verify that lockdep detects an IRQ-context mismatch when an atomic SRCU read-side critical section is held with IRQs enabled on one CPU and synchronize_srcu_atomic() is called from an IPI handler on another CPU. This covers the cross-CPU case that cannot be detected by checking the current task's held locks. Co-developed-by: Zqiang <qiang.zhang@linux.dev> Signed-off-by: Zqiang <qiang.zhang@linux.dev> Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com> Acked-by: Boqun Feng <boqun@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcu/rcutorture.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 35dc61d871b9..968343be4e0d 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -4695,6 +4695,8 @@ DEFINE_STATIC_SRCU_ATOMIC(srcu7_atomic);
DEFINE_STATIC_SRCU_ATOMIC(srcu8_atomic);
DEFINE_STATIC_SRCU_ATOMIC(srcu9_atomic);
+DEFINE_STATIC_SRCU_ATOMIC(srcu_irq);
+
static int srcu_lockdep_next(const char *f, const char *fl, const char *fs, const char *fu, int i,
int cyclelen, int deadlock)
{
@@ -4709,6 +4711,11 @@ static int srcu_lockdep_next(const char *f, const char *fl, const char *fs, cons
return j;
}
+static void srcu_sync_irq(void *unused)
+{
+ synchronize_srcu_atomic(&srcu_irq);
+}
+
// Test lockdep on SRCU-based deadlock scenarios.
static void rcu_torture_init_srcu_lockdep(void)
{
@@ -4892,13 +4899,31 @@ static void rcu_torture_init_srcu_lockdep(void)
return;
}
+ if (testtype == 7) {
+ int cpu;
+
+ for (i = 0; i < cyclelen; i++) {
+ idx = srcu_read_lock_atomic(&srcu_irq);
+ cpu = cpumask_any_but(cpu_online_mask,
+ smp_processor_id());
+ if (cpu < nr_cpu_ids) {
+ pr_info("%s: CPU%d sending IPI to CPU%d\n",
+ __func__, smp_processor_id(), cpu);
+ smp_call_function_single(cpu, srcu_sync_irq,
+ NULL, 1);
+ }
+ srcu_read_unlock_atomic(&srcu_irq, idx);
+ }
+ return;
+ }
+
err_out:
pr_info("%s: test_srcu_lockdep = %05d does nothing.\n", __func__, test_srcu_lockdep);
pr_info("%s: test_srcu_lockdep = DNNL.\n", __func__);
pr_info("%s: D: Deadlock if nonzero.\n", __func__);
pr_info("%s: NN: Test number, 0=SRCU, 1=SRCU/mutex, 2=SRCU/rwsem, 3=SRCU/Tasks Trace RCU, 4=SRCU_ATOMIC, ",
__func__);
- pr_cont("5=SRCU_ATOMIC/raw_spinlock, 6=synchronize_srcu_atomic inside rcu_read_lock.\n");
+ pr_cont("5=SRCU_ATOMIC/raw_spinlock, 6=synchronize_srcu_atomic inside rcu_read_lock, 7=atomic SRCU cross-CPU IRQ context mismatch.\n");
pr_info("%s: L: Cycle length.\n", __func__);
if (!IS_ENABLED(CONFIG_TASKS_TRACE_RCU))
pr_info("%s: NN=3 disallowed because kernel is built with CONFIG_TASKS_TRACE_RCU=n\n", __func__);