]>
git.ipfire.org Git - thirdparty/kernel/stable.git/blob - tools/testing/selftests/user_events/perf_test.c
1 // SPDX-License-Identifier: GPL-2.0
3 * User Events Perf Events Test Program
5 * Copyright (c) 2021 Beau Belgrave <beaub@linux.microsoft.com>
9 #include <linux/user_events.h>
10 #include <linux/perf_event.h>
14 #include <sys/ioctl.h>
17 #include <asm/unistd.h>
19 #include "../kselftest_harness.h"
20 #include "user_events_selftests.h"
22 const char *data_file
= "/sys/kernel/tracing/user_events_data";
23 const char *id_file
= "/sys/kernel/tracing/events/user_events/__test_event/id";
24 const char *fmt_file
= "/sys/kernel/tracing/events/user_events/__test_event/format";
32 static long perf_event_open(struct perf_event_attr
*pe
, pid_t pid
,
33 int cpu
, int group_fd
, unsigned long flags
)
35 return syscall(__NR_perf_event_open
, pe
, pid
, cpu
, group_fd
, flags
);
38 static int get_id(void)
40 FILE *fp
= fopen(id_file
, "r");
46 ret
= fscanf(fp
, "%d", &id
);
55 static int get_offset(void)
57 FILE *fp
= fopen(fmt_file
, "r");
58 int ret
, c
, last
= 0, offset
= 0;
63 /* Read until empty line */
70 if (last
== '\n' && c
== '\n')
76 ret
= fscanf(fp
, "\tfield:u32 field1;\toffset:%d;", &offset
);
85 static int clear(int *check
)
87 struct user_unreg unreg
= {0};
89 unreg
.size
= sizeof(unreg
);
90 unreg
.disable_bit
= 31;
91 unreg
.disable_addr
= (__u64
)check
;
93 int fd
= open(data_file
, O_RDWR
);
98 if (ioctl(fd
, DIAG_IOCSUNREG
, &unreg
) == -1)
102 if (ioctl(fd
, DIAG_IOCSDEL
, "__test_event") == -1)
116 FIXTURE_SETUP(user
) {
117 USER_EVENT_FIXTURE_SETUP(return);
119 self
->data_fd
= open(data_file
, O_RDWR
);
120 ASSERT_NE(-1, self
->data_fd
);
123 FIXTURE_TEARDOWN(user
) {
124 close(self
->data_fd
);
126 if (clear(&self
->check
) != 0)
127 printf("WARNING: Clear didn't work!\n");
130 TEST_F(user
, perf_write
) {
131 struct perf_event_attr pe
= {0};
132 struct user_reg reg
= {0};
134 struct perf_event_mmap_page
*perf_page
;
135 int page_size
= sysconf(_SC_PAGESIZE
);
139 reg
.size
= sizeof(reg
);
140 reg
.name_args
= (__u64
)"__test_event u32 field1; u32 field2";
142 reg
.enable_addr
= (__u64
)&self
->check
;
143 reg
.enable_size
= sizeof(self
->check
);
145 /* Register should work */
146 ASSERT_EQ(0, ioctl(self
->data_fd
, DIAG_IOCSREG
, ®
));
147 ASSERT_EQ(0, reg
.write_index
);
148 ASSERT_EQ(0, self
->check
);
150 /* Id should be there */
153 offset
= get_offset();
154 ASSERT_NE(-1, offset
);
156 pe
.type
= PERF_TYPE_TRACEPOINT
;
157 pe
.size
= sizeof(pe
);
159 pe
.sample_type
= PERF_SAMPLE_RAW
;
160 pe
.sample_period
= 1;
161 pe
.wakeup_events
= 1;
163 /* Tracepoint attach should work */
164 fd
= perf_event_open(&pe
, 0, -1, -1, 0);
167 perf_page
= mmap(NULL
, page_size
* 2, PROT_READ
, MAP_SHARED
, fd
, 0);
168 ASSERT_NE(MAP_FAILED
, perf_page
);
170 /* Status should be updated */
171 ASSERT_EQ(1 << reg
.enable_bit
, self
->check
);
173 event
.index
= reg
.write_index
;
174 event
.field1
= 0xc001;
175 event
.field2
= 0xc01a;
177 /* Ensure write shows up at correct offset */
178 ASSERT_NE(-1, write(self
->data_fd
, &event
, sizeof(event
)));
179 val
= (void *)(((char *)perf_page
) + perf_page
->data_offset
);
180 ASSERT_EQ(PERF_RECORD_SAMPLE
, *val
);
181 /* Skip over header and size, move to offset */
183 val
= (void *)((char *)val
) + offset
;
185 ASSERT_EQ(event
.field1
, *val
++);
186 ASSERT_EQ(event
.field2
, *val
++);
188 munmap(perf_page
, page_size
* 2);
191 /* Status should be updated */
192 ASSERT_EQ(0, self
->check
);
195 TEST_F(user
, perf_empty_events
) {
196 struct perf_event_attr pe
= {0};
197 struct user_reg reg
= {0};
198 struct perf_event_mmap_page
*perf_page
;
199 int page_size
= sysconf(_SC_PAGESIZE
);
203 reg
.size
= sizeof(reg
);
204 reg
.name_args
= (__u64
)"__test_event";
206 reg
.enable_addr
= (__u64
)&self
->check
;
207 reg
.enable_size
= sizeof(self
->check
);
209 /* Register should work */
210 ASSERT_EQ(0, ioctl(self
->data_fd
, DIAG_IOCSREG
, ®
));
211 ASSERT_EQ(0, reg
.write_index
);
212 ASSERT_EQ(0, self
->check
);
214 /* Id should be there */
218 pe
.type
= PERF_TYPE_TRACEPOINT
;
219 pe
.size
= sizeof(pe
);
221 pe
.sample_type
= PERF_SAMPLE_RAW
;
222 pe
.sample_period
= 1;
223 pe
.wakeup_events
= 1;
225 /* Tracepoint attach should work */
226 fd
= perf_event_open(&pe
, 0, -1, -1, 0);
229 perf_page
= mmap(NULL
, page_size
* 2, PROT_READ
, MAP_SHARED
, fd
, 0);
230 ASSERT_NE(MAP_FAILED
, perf_page
);
232 /* Status should be updated */
233 ASSERT_EQ(1 << reg
.enable_bit
, self
->check
);
235 /* Ensure write shows up at correct offset */
236 ASSERT_NE(-1, write(self
->data_fd
, ®
.write_index
,
237 sizeof(reg
.write_index
)));
238 val
= (void *)(((char *)perf_page
) + perf_page
->data_offset
);
239 ASSERT_EQ(PERF_RECORD_SAMPLE
, *val
);
241 munmap(perf_page
, page_size
* 2);
244 /* Status should be updated */
245 ASSERT_EQ(0, self
->check
);
248 int main(int argc
, char **argv
)
250 return test_harness_run(argc
, argv
);