Merge tag 'powerpc-6.6-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[platform/kernel/linux-starfive.git] / tools / testing / selftests / user_events / dyn_test.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * User Events Dyn Events Test Program
4  *
5  * Copyright (c) 2021 Beau Belgrave <beaub@linux.microsoft.com>
6  */
7
8 #include <errno.h>
9 #include <linux/user_events.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16
17 #include "../kselftest_harness.h"
18 #include "user_events_selftests.h"
19
20 const char *abi_file = "/sys/kernel/tracing/user_events_data";
21 const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable";
22
23 static bool wait_for_delete(void)
24 {
25         int i;
26
27         for (i = 0; i < 1000; ++i) {
28                 int fd = open(enable_file, O_RDONLY);
29
30                 if (fd == -1)
31                         return true;
32
33                 close(fd);
34                 usleep(1000);
35         }
36
37         return false;
38 }
39
40 static int reg_event(int fd, int *check, int bit, const char *value)
41 {
42         struct user_reg reg = {0};
43
44         reg.size = sizeof(reg);
45         reg.name_args = (__u64)value;
46         reg.enable_bit = bit;
47         reg.enable_addr = (__u64)check;
48         reg.enable_size = sizeof(*check);
49
50         if (ioctl(fd, DIAG_IOCSREG, &reg) == -1)
51                 return -1;
52
53         return 0;
54 }
55
56 static int unreg_event(int fd, int *check, int bit)
57 {
58         struct user_unreg unreg = {0};
59
60         unreg.size = sizeof(unreg);
61         unreg.disable_bit = bit;
62         unreg.disable_addr = (__u64)check;
63
64         return ioctl(fd, DIAG_IOCSUNREG, &unreg);
65 }
66
67 static int parse(int *check, const char *value)
68 {
69         int fd = open(abi_file, O_RDWR);
70         int ret;
71
72         if (fd == -1)
73                 return -1;
74
75         /* Until we have persist flags via dynamic events, use the base name */
76         if (value[0] != 'u' || value[1] != ':') {
77                 close(fd);
78                 return -1;
79         }
80
81         ret = reg_event(fd, check, 31, value + 2);
82
83         if (ret != -1) {
84                 if (unreg_event(fd, check, 31) == -1)
85                         printf("WARN: Couldn't unreg event\n");
86         }
87
88         close(fd);
89
90         return ret;
91 }
92
93 static int check_match(int *check, const char *first, const char *second, bool *match)
94 {
95         int fd = open(abi_file, O_RDWR);
96         int ret = -1;
97
98         if (fd == -1)
99                 return -1;
100
101         if (reg_event(fd, check, 31, first) == -1)
102                 goto cleanup;
103
104         if (reg_event(fd, check, 30, second) == -1) {
105                 if (errno == EADDRINUSE) {
106                         /* Name is in use, with different fields */
107                         *match = false;
108                         ret = 0;
109                 }
110
111                 goto cleanup;
112         }
113
114         *match = true;
115         ret = 0;
116 cleanup:
117         unreg_event(fd, check, 31);
118         unreg_event(fd, check, 30);
119
120         close(fd);
121
122         wait_for_delete();
123
124         return ret;
125 }
126
127 #define TEST_MATCH(x, y) \
128 do { \
129         bool match; \
130         ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \
131         ASSERT_EQ(true, match); \
132 } while (0)
133
134 #define TEST_NMATCH(x, y) \
135 do { \
136         bool match; \
137         ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \
138         ASSERT_EQ(false, match); \
139 } while (0)
140
141 #define TEST_PARSE(x) ASSERT_NE(-1, parse(&self->check, x))
142
143 #define TEST_NPARSE(x) ASSERT_EQ(-1, parse(&self->check, x))
144
145 FIXTURE(user) {
146         int check;
147         bool umount;
148 };
149
150 FIXTURE_SETUP(user) {
151         USER_EVENT_FIXTURE_SETUP(return, self->umount);
152 }
153
154 FIXTURE_TEARDOWN(user) {
155         USER_EVENT_FIXTURE_TEARDOWN(self->umount);
156
157         wait_for_delete();
158 }
159
160 TEST_F(user, basic_types) {
161         /* All should work */
162         TEST_PARSE("u:__test_event u64 a");
163         TEST_PARSE("u:__test_event u32 a");
164         TEST_PARSE("u:__test_event u16 a");
165         TEST_PARSE("u:__test_event u8 a");
166         TEST_PARSE("u:__test_event char a");
167         TEST_PARSE("u:__test_event unsigned char a");
168         TEST_PARSE("u:__test_event int a");
169         TEST_PARSE("u:__test_event unsigned int a");
170         TEST_PARSE("u:__test_event short a");
171         TEST_PARSE("u:__test_event unsigned short a");
172         TEST_PARSE("u:__test_event char[20] a");
173         TEST_PARSE("u:__test_event unsigned char[20] a");
174         TEST_PARSE("u:__test_event char[0x14] a");
175         TEST_PARSE("u:__test_event unsigned char[0x14] a");
176         /* Bad size format should fail */
177         TEST_NPARSE("u:__test_event char[aa] a");
178         /* Large size should fail */
179         TEST_NPARSE("u:__test_event char[9999] a");
180         /* Long size string should fail */
181         TEST_NPARSE("u:__test_event char[0x0000000000001] a");
182 }
183
184 TEST_F(user, loc_types) {
185         /* All should work */
186         TEST_PARSE("u:__test_event __data_loc char[] a");
187         TEST_PARSE("u:__test_event __data_loc unsigned char[] a");
188         TEST_PARSE("u:__test_event __rel_loc char[] a");
189         TEST_PARSE("u:__test_event __rel_loc unsigned char[] a");
190 }
191
192 TEST_F(user, size_types) {
193         /* Should work */
194         TEST_PARSE("u:__test_event struct custom a 20");
195         /* Size not specified on struct should fail */
196         TEST_NPARSE("u:__test_event struct custom a");
197         /* Size specified on non-struct should fail */
198         TEST_NPARSE("u:__test_event char a 20");
199 }
200
201 TEST_F(user, matching) {
202         /* Single name matches */
203         TEST_MATCH("__test_event u32 a",
204                    "__test_event u32 a");
205
206         /* Multiple names match */
207         TEST_MATCH("__test_event u32 a; u32 b",
208                    "__test_event u32 a; u32 b");
209
210         /* Multiple names match with dangling ; */
211         TEST_MATCH("__test_event u32 a; u32 b",
212                    "__test_event u32 a; u32 b;");
213
214         /* Single name doesn't match */
215         TEST_NMATCH("__test_event u32 a",
216                     "__test_event u32 b");
217
218         /* Multiple names don't match */
219         TEST_NMATCH("__test_event u32 a; u32 b",
220                     "__test_event u32 b; u32 a");
221
222         /* Types don't match */
223         TEST_NMATCH("__test_event u64 a; u64 b",
224                     "__test_event u32 a; u32 b");
225
226         /* Struct name and size matches */
227         TEST_MATCH("__test_event struct my_struct a 20",
228                    "__test_event struct my_struct a 20");
229
230         /* Struct name don't match */
231         TEST_NMATCH("__test_event struct my_struct a 20",
232                     "__test_event struct my_struct b 20");
233
234         /* Struct size don't match */
235         TEST_NMATCH("__test_event struct my_struct a 20",
236                     "__test_event struct my_struct a 21");
237 }
238
239 int main(int argc, char **argv)
240 {
241         return test_harness_run(argc, argv);
242 }