dyn_test.c 6.1 KB

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