xref: /openbmc/linux/tools/testing/selftests/perf_events/sigtrap_threads.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1f2c3c32fSMarco Elver // SPDX-License-Identifier: GPL-2.0
2f2c3c32fSMarco Elver /*
3f2c3c32fSMarco Elver  * Test for perf events with SIGTRAP across all threads.
4f2c3c32fSMarco Elver  *
5f2c3c32fSMarco Elver  * Copyright (C) 2021, Google LLC.
6f2c3c32fSMarco Elver  */
7f2c3c32fSMarco Elver 
8f2c3c32fSMarco Elver #define _GNU_SOURCE
9f2c3c32fSMarco Elver 
10f2c3c32fSMarco Elver /* We need the latest siginfo from the kernel repo. */
11f2c3c32fSMarco Elver #include <sys/types.h>
12f2c3c32fSMarco Elver #include <asm/siginfo.h>
13f2c3c32fSMarco Elver #define __have_siginfo_t 1
14f2c3c32fSMarco Elver #define __have_sigval_t 1
15f2c3c32fSMarco Elver #define __have_sigevent_t 1
16f2c3c32fSMarco Elver #define __siginfo_t_defined
17f2c3c32fSMarco Elver #define __sigval_t_defined
18f2c3c32fSMarco Elver #define __sigevent_t_defined
19f2c3c32fSMarco Elver #define _BITS_SIGINFO_CONSTS_H 1
20f2c3c32fSMarco Elver #define _BITS_SIGEVENT_CONSTS_H 1
21f2c3c32fSMarco Elver 
22f2c3c32fSMarco Elver #include <stdbool.h>
23f2c3c32fSMarco Elver #include <stddef.h>
24f2c3c32fSMarco Elver #include <stdint.h>
25f2c3c32fSMarco Elver #include <stdio.h>
26f2c3c32fSMarco Elver #include <linux/hw_breakpoint.h>
27f2c3c32fSMarco Elver #include <linux/perf_event.h>
28f2c3c32fSMarco Elver #include <pthread.h>
29f2c3c32fSMarco Elver #include <signal.h>
30f2c3c32fSMarco Elver #include <sys/ioctl.h>
31f2c3c32fSMarco Elver #include <sys/syscall.h>
32f2c3c32fSMarco Elver #include <unistd.h>
33f2c3c32fSMarco Elver 
34f2c3c32fSMarco Elver #include "../kselftest_harness.h"
35f2c3c32fSMarco Elver 
36f2c3c32fSMarco Elver #define NUM_THREADS 5
37f2c3c32fSMarco Elver 
38f2c3c32fSMarco Elver /* Data shared between test body, threads, and signal handler. */
39f2c3c32fSMarco Elver static struct {
40f2c3c32fSMarco Elver 	int tids_want_signal;		/* Which threads still want a signal. */
41f2c3c32fSMarco Elver 	int signal_count;		/* Sanity check number of signals received. */
42f2c3c32fSMarco Elver 	volatile int iterate_on;	/* Variable to set breakpoint on. */
43f2c3c32fSMarco Elver 	siginfo_t first_siginfo;	/* First observed siginfo_t. */
44f2c3c32fSMarco Elver } ctx;
45f2c3c32fSMarco Elver 
460683b531SEric W. Biederman /* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */
4795d29fa1SMarco Elver #define TEST_SIG_DATA(addr, id) (~(unsigned long)(addr) + id)
48f2c3c32fSMarco Elver 
make_event_attr(bool enabled,volatile void * addr,unsigned long id)4995d29fa1SMarco Elver static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr,
5095d29fa1SMarco Elver 					      unsigned long id)
51f2c3c32fSMarco Elver {
52f2c3c32fSMarco Elver 	struct perf_event_attr attr = {
53f2c3c32fSMarco Elver 		.type		= PERF_TYPE_BREAKPOINT,
54f2c3c32fSMarco Elver 		.size		= sizeof(attr),
55f2c3c32fSMarco Elver 		.sample_period	= 1,
56f2c3c32fSMarco Elver 		.disabled	= !enabled,
57f2c3c32fSMarco Elver 		.bp_addr	= (unsigned long)addr,
58f2c3c32fSMarco Elver 		.bp_type	= HW_BREAKPOINT_RW,
59f2c3c32fSMarco Elver 		.bp_len		= HW_BREAKPOINT_LEN_1,
60f2c3c32fSMarco Elver 		.inherit	= 1, /* Children inherit events ... */
61f2c3c32fSMarco Elver 		.inherit_thread = 1, /* ... but only cloned with CLONE_THREAD. */
62f2c3c32fSMarco Elver 		.remove_on_exec = 1, /* Required by sigtrap. */
63f2c3c32fSMarco Elver 		.sigtrap	= 1, /* Request synchronous SIGTRAP on event. */
6495d29fa1SMarco Elver 		.sig_data	= TEST_SIG_DATA(addr, id),
65*23488ec6SMarco Elver 		.exclude_kernel = 1, /* To allow */
66*23488ec6SMarco Elver 		.exclude_hv     = 1, /* running as !root */
67f2c3c32fSMarco Elver 	};
68f2c3c32fSMarco Elver 	return attr;
69f2c3c32fSMarco Elver }
70f2c3c32fSMarco Elver 
sigtrap_handler(int signum,siginfo_t * info,void * ucontext)71f2c3c32fSMarco Elver static void sigtrap_handler(int signum, siginfo_t *info, void *ucontext)
72f2c3c32fSMarco Elver {
73f2c3c32fSMarco Elver 	if (info->si_code != TRAP_PERF) {
74f2c3c32fSMarco Elver 		fprintf(stderr, "%s: unexpected si_code %d\n", __func__, info->si_code);
75f2c3c32fSMarco Elver 		return;
76f2c3c32fSMarco Elver 	}
77f2c3c32fSMarco Elver 
78f2c3c32fSMarco Elver 	/*
79f2c3c32fSMarco Elver 	 * The data in siginfo_t we're interested in should all be the same
80f2c3c32fSMarco Elver 	 * across threads.
81f2c3c32fSMarco Elver 	 */
82f2c3c32fSMarco Elver 	if (!__atomic_fetch_add(&ctx.signal_count, 1, __ATOMIC_RELAXED))
83f2c3c32fSMarco Elver 		ctx.first_siginfo = *info;
84f2c3c32fSMarco Elver 	__atomic_fetch_sub(&ctx.tids_want_signal, syscall(__NR_gettid), __ATOMIC_RELAXED);
85f2c3c32fSMarco Elver }
86f2c3c32fSMarco Elver 
test_thread(void * arg)87f2c3c32fSMarco Elver static void *test_thread(void *arg)
88f2c3c32fSMarco Elver {
89f2c3c32fSMarco Elver 	pthread_barrier_t *barrier = (pthread_barrier_t *)arg;
90f2c3c32fSMarco Elver 	pid_t tid = syscall(__NR_gettid);
91f2c3c32fSMarco Elver 	int iter;
92f2c3c32fSMarco Elver 	int i;
93f2c3c32fSMarco Elver 
94f2c3c32fSMarco Elver 	pthread_barrier_wait(barrier);
95f2c3c32fSMarco Elver 
96f2c3c32fSMarco Elver 	__atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
97f2c3c32fSMarco Elver 	iter = ctx.iterate_on; /* read */
98*23488ec6SMarco Elver 	if (iter >= 0) {
99f2c3c32fSMarco Elver 		for (i = 0; i < iter - 1; i++) {
100f2c3c32fSMarco Elver 			__atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
101f2c3c32fSMarco Elver 			ctx.iterate_on = iter; /* idempotent write */
102f2c3c32fSMarco Elver 		}
103*23488ec6SMarco Elver 	} else {
104*23488ec6SMarco Elver 		while (ctx.iterate_on);
105*23488ec6SMarco Elver 	}
106f2c3c32fSMarco Elver 
107f2c3c32fSMarco Elver 	return NULL;
108f2c3c32fSMarco Elver }
109f2c3c32fSMarco Elver 
FIXTURE(sigtrap_threads)110f2c3c32fSMarco Elver FIXTURE(sigtrap_threads)
111f2c3c32fSMarco Elver {
112f2c3c32fSMarco Elver 	struct sigaction oldact;
113f2c3c32fSMarco Elver 	pthread_t threads[NUM_THREADS];
114f2c3c32fSMarco Elver 	pthread_barrier_t barrier;
115f2c3c32fSMarco Elver 	int fd;
116f2c3c32fSMarco Elver };
117f2c3c32fSMarco Elver 
FIXTURE_SETUP(sigtrap_threads)118f2c3c32fSMarco Elver FIXTURE_SETUP(sigtrap_threads)
119f2c3c32fSMarco Elver {
12095d29fa1SMarco Elver 	struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on, 0);
121f2c3c32fSMarco Elver 	struct sigaction action = {};
122f2c3c32fSMarco Elver 	int i;
123f2c3c32fSMarco Elver 
124f2c3c32fSMarco Elver 	memset(&ctx, 0, sizeof(ctx));
125f2c3c32fSMarco Elver 
126f2c3c32fSMarco Elver 	/* Initialize sigtrap handler. */
127f2c3c32fSMarco Elver 	action.sa_flags = SA_SIGINFO | SA_NODEFER;
128f2c3c32fSMarco Elver 	action.sa_sigaction = sigtrap_handler;
129f2c3c32fSMarco Elver 	sigemptyset(&action.sa_mask);
130f2c3c32fSMarco Elver 	ASSERT_EQ(sigaction(SIGTRAP, &action, &self->oldact), 0);
131f2c3c32fSMarco Elver 
132f2c3c32fSMarco Elver 	/* Initialize perf event. */
133f2c3c32fSMarco Elver 	self->fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC);
134f2c3c32fSMarco Elver 	ASSERT_NE(self->fd, -1);
135f2c3c32fSMarco Elver 
136f2c3c32fSMarco Elver 	/* Spawn threads inheriting perf event. */
137f2c3c32fSMarco Elver 	pthread_barrier_init(&self->barrier, NULL, NUM_THREADS + 1);
138f2c3c32fSMarco Elver 	for (i = 0; i < NUM_THREADS; i++)
139f2c3c32fSMarco Elver 		ASSERT_EQ(pthread_create(&self->threads[i], NULL, test_thread, &self->barrier), 0);
140f2c3c32fSMarco Elver }
141f2c3c32fSMarco Elver 
FIXTURE_TEARDOWN(sigtrap_threads)142f2c3c32fSMarco Elver FIXTURE_TEARDOWN(sigtrap_threads)
143f2c3c32fSMarco Elver {
144f2c3c32fSMarco Elver 	pthread_barrier_destroy(&self->barrier);
145f2c3c32fSMarco Elver 	close(self->fd);
146f2c3c32fSMarco Elver 	sigaction(SIGTRAP, &self->oldact, NULL);
147f2c3c32fSMarco Elver }
148f2c3c32fSMarco Elver 
run_test_threads(struct __test_metadata * _metadata,FIXTURE_DATA (sigtrap_threads)* self)149f2c3c32fSMarco Elver static void run_test_threads(struct __test_metadata *_metadata,
150f2c3c32fSMarco Elver 			     FIXTURE_DATA(sigtrap_threads) *self)
151f2c3c32fSMarco Elver {
152f2c3c32fSMarco Elver 	int i;
153f2c3c32fSMarco Elver 
154f2c3c32fSMarco Elver 	pthread_barrier_wait(&self->barrier);
155f2c3c32fSMarco Elver 	for (i = 0; i < NUM_THREADS; i++)
156f2c3c32fSMarco Elver 		ASSERT_EQ(pthread_join(self->threads[i], NULL), 0);
157f2c3c32fSMarco Elver }
158f2c3c32fSMarco Elver 
TEST_F(sigtrap_threads,remain_disabled)159f2c3c32fSMarco Elver TEST_F(sigtrap_threads, remain_disabled)
160f2c3c32fSMarco Elver {
161f2c3c32fSMarco Elver 	run_test_threads(_metadata, self);
162f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.signal_count, 0);
163f2c3c32fSMarco Elver 	EXPECT_NE(ctx.tids_want_signal, 0);
164f2c3c32fSMarco Elver }
165f2c3c32fSMarco Elver 
TEST_F(sigtrap_threads,enable_event)166f2c3c32fSMarco Elver TEST_F(sigtrap_threads, enable_event)
167f2c3c32fSMarco Elver {
168f2c3c32fSMarco Elver 	EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
169f2c3c32fSMarco Elver 	run_test_threads(_metadata, self);
170f2c3c32fSMarco Elver 
171f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.signal_count, NUM_THREADS);
172f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.tids_want_signal, 0);
173f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
1740683b531SEric W. Biederman 	EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
17595d29fa1SMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
176f2c3c32fSMarco Elver 
177f2c3c32fSMarco Elver 	/* Check enabled for parent. */
178f2c3c32fSMarco Elver 	ctx.iterate_on = 0;
179f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.signal_count, NUM_THREADS + 1);
180f2c3c32fSMarco Elver }
181f2c3c32fSMarco Elver 
182f2c3c32fSMarco Elver /* Test that modification propagates to all inherited events. */
TEST_F(sigtrap_threads,modify_and_enable_event)183f2c3c32fSMarco Elver TEST_F(sigtrap_threads, modify_and_enable_event)
184f2c3c32fSMarco Elver {
18595d29fa1SMarco Elver 	struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on, 42);
186f2c3c32fSMarco Elver 
187f2c3c32fSMarco Elver 	EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0);
188f2c3c32fSMarco Elver 	run_test_threads(_metadata, self);
189f2c3c32fSMarco Elver 
190f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.signal_count, NUM_THREADS);
191f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.tids_want_signal, 0);
192f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
1930683b531SEric W. Biederman 	EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
19495d29fa1SMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 42));
195f2c3c32fSMarco Elver 
196f2c3c32fSMarco Elver 	/* Check enabled for parent. */
197f2c3c32fSMarco Elver 	ctx.iterate_on = 0;
198f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.signal_count, NUM_THREADS + 1);
199f2c3c32fSMarco Elver }
200f2c3c32fSMarco Elver 
201f2c3c32fSMarco Elver /* Stress test event + signal handling. */
TEST_F(sigtrap_threads,signal_stress)202f2c3c32fSMarco Elver TEST_F(sigtrap_threads, signal_stress)
203f2c3c32fSMarco Elver {
204f2c3c32fSMarco Elver 	ctx.iterate_on = 3000;
205f2c3c32fSMarco Elver 
206f2c3c32fSMarco Elver 	EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
207f2c3c32fSMarco Elver 	run_test_threads(_metadata, self);
208f2c3c32fSMarco Elver 	EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
209f2c3c32fSMarco Elver 
210f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.signal_count, NUM_THREADS * ctx.iterate_on);
211f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.tids_want_signal, 0);
212f2c3c32fSMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
2130683b531SEric W. Biederman 	EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
21495d29fa1SMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
215f2c3c32fSMarco Elver }
216f2c3c32fSMarco Elver 
TEST_F(sigtrap_threads,signal_stress_with_disable)217*23488ec6SMarco Elver TEST_F(sigtrap_threads, signal_stress_with_disable)
218*23488ec6SMarco Elver {
219*23488ec6SMarco Elver 	const int target_count = NUM_THREADS * 3000;
220*23488ec6SMarco Elver 	int i;
221*23488ec6SMarco Elver 
222*23488ec6SMarco Elver 	ctx.iterate_on = -1;
223*23488ec6SMarco Elver 
224*23488ec6SMarco Elver 	EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
225*23488ec6SMarco Elver 	pthread_barrier_wait(&self->barrier);
226*23488ec6SMarco Elver 	while (__atomic_load_n(&ctx.signal_count, __ATOMIC_RELAXED) < target_count) {
227*23488ec6SMarco Elver 		EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
228*23488ec6SMarco Elver 		EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
229*23488ec6SMarco Elver 	}
230*23488ec6SMarco Elver 	ctx.iterate_on = 0;
231*23488ec6SMarco Elver 	for (i = 0; i < NUM_THREADS; i++)
232*23488ec6SMarco Elver 		ASSERT_EQ(pthread_join(self->threads[i], NULL), 0);
233*23488ec6SMarco Elver 	EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
234*23488ec6SMarco Elver 
235*23488ec6SMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
236*23488ec6SMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
237*23488ec6SMarco Elver 	EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
238*23488ec6SMarco Elver }
239*23488ec6SMarco Elver 
240f2c3c32fSMarco Elver TEST_HARNESS_MAIN
241