Skip to content

Commit d7d70f7

Browse files
kkdwvdKernel Patches Daemon
authored andcommitted
selftests/bpf: Add ABBCCA case for rqspinlock stress test
Introduce a new mode for the rqspinlock stress test that exercises a deadlock that won't be detected by the AA and ABBA checks, such that we always reliably trigger the timeout fallback. We need 4 CPUs for this particular case, as CPU 0 is untouched, and three participant CPUs for triggering the ABBCCA case. Refactor the lock acquisition paths in the module to better reflect the three modes and choose the right lock depending on the context. Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> Acked-by: Eduard Zingerman <[email protected]>
1 parent d4664e4 commit d7d70f7

File tree

2 files changed

+72
-24
lines changed

2 files changed

+72
-24
lines changed

tools/testing/selftests/bpf/prog_tests/res_spin_lock.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,16 @@ void serial_test_res_spin_lock_stress(void)
111111
sleep(5);
112112
unload_module("bpf_test_rqspinlock", false);
113113

114-
ASSERT_OK(load_module_params("bpf_test_rqspinlock.ko", "test_ab=1", false), "load module ABBA");
114+
ASSERT_OK(load_module_params("bpf_test_rqspinlock.ko", "test_mode=1", false), "load module ABBA");
115+
sleep(5);
116+
unload_module("bpf_test_rqspinlock", false);
117+
118+
if (libbpf_num_possible_cpus() < 4) {
119+
test__skip();
120+
return;
121+
}
122+
123+
ASSERT_OK(load_module_params("bpf_test_rqspinlock.ko", "test_mode=2", false), "load module ABBCCA");
115124
sleep(5);
116125
unload_module("bpf_test_rqspinlock", false);
117126
}

tools/testing/selftests/bpf/test_kmods/bpf_test_rqspinlock.c

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,61 @@ static struct perf_event_attr hw_attr = {
2222

2323
static rqspinlock_t lock_a;
2424
static rqspinlock_t lock_b;
25+
static rqspinlock_t lock_c;
26+
27+
enum rqsl_mode {
28+
RQSL_MODE_AA = 0,
29+
RQSL_MODE_ABBA,
30+
RQSL_MODE_ABBCCA,
31+
};
32+
33+
static int test_mode = RQSL_MODE_AA;
34+
module_param(test_mode, int, 0644);
35+
MODULE_PARM_DESC(test_mode,
36+
"rqspinlock test mode: 0 = AA, 1 = ABBA, 2 = ABBCCA");
2537

2638
static struct perf_event **rqsl_evts;
2739
static int rqsl_nevts;
2840

29-
static bool test_ab = false;
30-
module_param(test_ab, bool, 0644);
31-
MODULE_PARM_DESC(test_ab, "Test ABBA situations instead of AA situations");
32-
3341
static struct task_struct **rqsl_threads;
3442
static int rqsl_nthreads;
3543
static atomic_t rqsl_ready_cpus = ATOMIC_INIT(0);
3644

3745
static int pause = 0;
3846

39-
static bool nmi_locks_a(int cpu)
47+
static const char *rqsl_mode_names[] = {
48+
[RQSL_MODE_AA] = "AA",
49+
[RQSL_MODE_ABBA] = "ABBA",
50+
[RQSL_MODE_ABBCCA] = "ABBCCA",
51+
};
52+
53+
struct rqsl_lock_pair {
54+
rqspinlock_t *worker_lock;
55+
rqspinlock_t *nmi_lock;
56+
};
57+
58+
static struct rqsl_lock_pair rqsl_get_lock_pair(int cpu)
4059
{
41-
return (cpu & 1) && test_ab;
60+
int mode = READ_ONCE(test_mode);
61+
62+
switch (mode) {
63+
default:
64+
case RQSL_MODE_AA:
65+
return (struct rqsl_lock_pair){ &lock_a, &lock_a };
66+
case RQSL_MODE_ABBA:
67+
if (cpu & 1)
68+
return (struct rqsl_lock_pair){ &lock_b, &lock_a };
69+
return (struct rqsl_lock_pair){ &lock_a, &lock_b };
70+
case RQSL_MODE_ABBCCA:
71+
switch (cpu % 3) {
72+
case 0:
73+
return (struct rqsl_lock_pair){ &lock_a, &lock_b };
74+
case 1:
75+
return (struct rqsl_lock_pair){ &lock_b, &lock_c };
76+
default:
77+
return (struct rqsl_lock_pair){ &lock_c, &lock_a };
78+
}
79+
}
4280
}
4381

4482
static int rqspinlock_worker_fn(void *arg)
@@ -51,19 +89,17 @@ static int rqspinlock_worker_fn(void *arg)
5189
atomic_inc(&rqsl_ready_cpus);
5290

5391
while (!kthread_should_stop()) {
92+
struct rqsl_lock_pair locks = rqsl_get_lock_pair(cpu);
93+
rqspinlock_t *worker_lock = locks.worker_lock;
94+
5495
if (READ_ONCE(pause)) {
5596
msleep(1000);
5697
continue;
5798
}
58-
if (nmi_locks_a(cpu))
59-
ret = raw_res_spin_lock_irqsave(&lock_b, flags);
60-
else
61-
ret = raw_res_spin_lock_irqsave(&lock_a, flags);
99+
ret = raw_res_spin_lock_irqsave(worker_lock, flags);
62100
mdelay(20);
63-
if (nmi_locks_a(cpu) && !ret)
64-
raw_res_spin_unlock_irqrestore(&lock_b, flags);
65-
else if (!ret)
66-
raw_res_spin_unlock_irqrestore(&lock_a, flags);
101+
if (!ret)
102+
raw_res_spin_unlock_irqrestore(worker_lock, flags);
67103
cpu_relax();
68104
}
69105
return 0;
@@ -91,24 +127,21 @@ static int rqspinlock_worker_fn(void *arg)
91127
static void nmi_cb(struct perf_event *event, struct perf_sample_data *data,
92128
struct pt_regs *regs)
93129
{
130+
struct rqsl_lock_pair locks;
94131
int cpu = smp_processor_id();
95132
unsigned long flags;
96133
int ret;
97134

98135
if (!cpu || READ_ONCE(pause))
99136
return;
100137

101-
if (nmi_locks_a(cpu))
102-
ret = raw_res_spin_lock_irqsave(&lock_a, flags);
103-
else
104-
ret = raw_res_spin_lock_irqsave(test_ab ? &lock_b : &lock_a, flags);
138+
locks = rqsl_get_lock_pair(cpu);
139+
ret = raw_res_spin_lock_irqsave(locks.nmi_lock, flags);
105140

106141
mdelay(10);
107142

108-
if (nmi_locks_a(cpu) && !ret)
109-
raw_res_spin_unlock_irqrestore(&lock_a, flags);
110-
else if (!ret)
111-
raw_res_spin_unlock_irqrestore(test_ab ? &lock_b : &lock_a, flags);
143+
if (!ret)
144+
raw_res_spin_unlock_irqrestore(locks.nmi_lock, flags);
112145
}
113146

114147
static void free_rqsl_threads(void)
@@ -142,13 +175,19 @@ static int bpf_test_rqspinlock_init(void)
142175
int i, ret;
143176
int ncpus = num_online_cpus();
144177

145-
pr_err("Mode = %s\n", test_ab ? "ABBA" : "AA");
178+
if (test_mode < RQSL_MODE_AA || test_mode > RQSL_MODE_ABBCCA) {
179+
pr_err("Invalid mode %d\n", test_mode);
180+
return -EINVAL;
181+
}
182+
183+
pr_err("Mode = %s\n", rqsl_mode_names[test_mode]);
146184

147185
if (ncpus < 3)
148186
return -ENOTSUPP;
149187

150188
raw_res_spin_lock_init(&lock_a);
151189
raw_res_spin_lock_init(&lock_b);
190+
raw_res_spin_lock_init(&lock_c);
152191

153192
rqsl_evts = kcalloc(ncpus - 1, sizeof(*rqsl_evts), GFP_KERNEL);
154193
if (!rqsl_evts)

0 commit comments

Comments
 (0)