aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-test.c')
-rw-r--r--tools/perf/builtin-test.c353
1 files changed, 337 insertions, 16 deletions
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 1d592f5cbea9..484f26cc0c00 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -14,11 +14,13 @@
14#include "util/symbol.h" 14#include "util/symbol.h"
15#include "util/thread_map.h" 15#include "util/thread_map.h"
16#include "util/pmu.h" 16#include "util/pmu.h"
17#include "event-parse.h"
17#include "../../include/linux/hw_breakpoint.h" 18#include "../../include/linux/hw_breakpoint.h"
18 19
19#include <sys/mman.h> 20#include <sys/mman.h>
20 21
21static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) 22static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
23 struct symbol *sym)
22{ 24{
23 bool *visited = symbol__priv(sym); 25 bool *visited = symbol__priv(sym);
24 *visited = true; 26 *visited = true;
@@ -294,7 +296,7 @@ static int test__open_syscall_event(void)
294 goto out_thread_map_delete; 296 goto out_thread_map_delete;
295 } 297 }
296 298
297 if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) { 299 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
298 pr_debug("failed to open counter: %s, " 300 pr_debug("failed to open counter: %s, "
299 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 301 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
300 strerror(errno)); 302 strerror(errno));
@@ -369,7 +371,7 @@ static int test__open_syscall_event_on_all_cpus(void)
369 goto out_thread_map_delete; 371 goto out_thread_map_delete;
370 } 372 }
371 373
372 if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) { 374 if (perf_evsel__open(evsel, cpus, threads) < 0) {
373 pr_debug("failed to open counter: %s, " 375 pr_debug("failed to open counter: %s, "
374 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 376 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
375 strerror(errno)); 377 strerror(errno));
@@ -533,7 +535,7 @@ static int test__basic_mmap(void)
533 535
534 perf_evlist__add(evlist, evsels[i]); 536 perf_evlist__add(evlist, evsels[i]);
535 537
536 if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) { 538 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
537 pr_debug("failed to open counter: %s, " 539 pr_debug("failed to open counter: %s, "
538 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 540 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
539 strerror(errno)); 541 strerror(errno));
@@ -562,7 +564,7 @@ static int test__basic_mmap(void)
562 goto out_munmap; 564 goto out_munmap;
563 } 565 }
564 566
565 err = perf_evlist__parse_sample(evlist, event, &sample, false); 567 err = perf_evlist__parse_sample(evlist, event, &sample);
566 if (err) { 568 if (err) {
567 pr_err("Can't parse sample, err = %d\n", err); 569 pr_err("Can't parse sample, err = %d\n", err);
568 goto out_munmap; 570 goto out_munmap;
@@ -710,7 +712,7 @@ static int test__PERF_RECORD(void)
710 /* 712 /*
711 * Config the evsels, setting attr->comm on the first one, etc. 713 * Config the evsels, setting attr->comm on the first one, etc.
712 */ 714 */
713 evsel = list_entry(evlist->entries.next, struct perf_evsel, node); 715 evsel = perf_evlist__first(evlist);
714 evsel->attr.sample_type |= PERF_SAMPLE_CPU; 716 evsel->attr.sample_type |= PERF_SAMPLE_CPU;
715 evsel->attr.sample_type |= PERF_SAMPLE_TID; 717 evsel->attr.sample_type |= PERF_SAMPLE_TID;
716 evsel->attr.sample_type |= PERF_SAMPLE_TIME; 718 evsel->attr.sample_type |= PERF_SAMPLE_TIME;
@@ -737,7 +739,7 @@ static int test__PERF_RECORD(void)
737 * Call sys_perf_event_open on all the fds on all the evsels, 739 * Call sys_perf_event_open on all the fds on all the evsels,
738 * grouping them if asked to. 740 * grouping them if asked to.
739 */ 741 */
740 err = perf_evlist__open(evlist, opts.group); 742 err = perf_evlist__open(evlist);
741 if (err < 0) { 743 if (err < 0) {
742 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 744 pr_debug("perf_evlist__open: %s\n", strerror(errno));
743 goto out_delete_evlist; 745 goto out_delete_evlist;
@@ -779,7 +781,7 @@ static int test__PERF_RECORD(void)
779 if (type < PERF_RECORD_MAX) 781 if (type < PERF_RECORD_MAX)
780 nr_events[type]++; 782 nr_events[type]++;
781 783
782 err = perf_evlist__parse_sample(evlist, event, &sample, false); 784 err = perf_evlist__parse_sample(evlist, event, &sample);
783 if (err < 0) { 785 if (err < 0) {
784 if (verbose) 786 if (verbose)
785 perf_event__fprintf(event, stderr); 787 perf_event__fprintf(event, stderr);
@@ -996,7 +998,9 @@ static u64 mmap_read_self(void *addr)
996/* 998/*
997 * If the RDPMC instruction faults then signal this back to the test parent task: 999 * If the RDPMC instruction faults then signal this back to the test parent task:
998 */ 1000 */
999static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used) 1001static void segfault_handler(int sig __maybe_unused,
1002 siginfo_t *info __maybe_unused,
1003 void *uc __maybe_unused)
1000{ 1004{
1001 exit(-1); 1005 exit(-1);
1002} 1006}
@@ -1023,14 +1027,16 @@ static int __test__rdpmc(void)
1023 1027
1024 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 1028 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
1025 if (fd < 0) { 1029 if (fd < 0) {
1026 die("Error: sys_perf_event_open() syscall returned " 1030 pr_err("Error: sys_perf_event_open() syscall returned "
1027 "with %d (%s)\n", fd, strerror(errno)); 1031 "with %d (%s)\n", fd, strerror(errno));
1032 return -1;
1028 } 1033 }
1029 1034
1030 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); 1035 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
1031 if (addr == (void *)(-1)) { 1036 if (addr == (void *)(-1)) {
1032 die("Error: mmap() syscall returned " 1037 pr_err("Error: mmap() syscall returned with (%s)\n",
1033 "with (%s)\n", strerror(errno)); 1038 strerror(errno));
1039 goto out_close;
1034 } 1040 }
1035 1041
1036 for (n = 0; n < 6; n++) { 1042 for (n = 0; n < 6; n++) {
@@ -1051,9 +1057,9 @@ static int __test__rdpmc(void)
1051 } 1057 }
1052 1058
1053 munmap(addr, page_size); 1059 munmap(addr, page_size);
1054 close(fd);
1055
1056 pr_debug(" "); 1060 pr_debug(" ");
1061out_close:
1062 close(fd);
1057 1063
1058 if (!delta_sum) 1064 if (!delta_sum)
1059 return -1; 1065 return -1;
@@ -1092,6 +1098,309 @@ static int test__perf_pmu(void)
1092 return perf_pmu__test(); 1098 return perf_pmu__test();
1093} 1099}
1094 1100
1101static int perf_evsel__roundtrip_cache_name_test(void)
1102{
1103 char name[128];
1104 int type, op, err = 0, ret = 0, i, idx;
1105 struct perf_evsel *evsel;
1106 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
1107
1108 if (evlist == NULL)
1109 return -ENOMEM;
1110
1111 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1112 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
1113 /* skip invalid cache type */
1114 if (!perf_evsel__is_cache_op_valid(type, op))
1115 continue;
1116
1117 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
1118 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
1119 name, sizeof(name));
1120 err = parse_events(evlist, name, 0);
1121 if (err)
1122 ret = err;
1123 }
1124 }
1125 }
1126
1127 idx = 0;
1128 evsel = perf_evlist__first(evlist);
1129
1130 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1131 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
1132 /* skip invalid cache type */
1133 if (!perf_evsel__is_cache_op_valid(type, op))
1134 continue;
1135
1136 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
1137 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
1138 name, sizeof(name));
1139 if (evsel->idx != idx)
1140 continue;
1141
1142 ++idx;
1143
1144 if (strcmp(perf_evsel__name(evsel), name)) {
1145 pr_debug("%s != %s\n", perf_evsel__name(evsel), name);
1146 ret = -1;
1147 }
1148
1149 evsel = perf_evsel__next(evsel);
1150 }
1151 }
1152 }
1153
1154 perf_evlist__delete(evlist);
1155 return ret;
1156}
1157
1158static int __perf_evsel__name_array_test(const char *names[], int nr_names)
1159{
1160 int i, err;
1161 struct perf_evsel *evsel;
1162 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
1163
1164 if (evlist == NULL)
1165 return -ENOMEM;
1166
1167 for (i = 0; i < nr_names; ++i) {
1168 err = parse_events(evlist, names[i], 0);
1169 if (err) {
1170 pr_debug("failed to parse event '%s', err %d\n",
1171 names[i], err);
1172 goto out_delete_evlist;
1173 }
1174 }
1175
1176 err = 0;
1177 list_for_each_entry(evsel, &evlist->entries, node) {
1178 if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
1179 --err;
1180 pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
1181 }
1182 }
1183
1184out_delete_evlist:
1185 perf_evlist__delete(evlist);
1186 return err;
1187}
1188
1189#define perf_evsel__name_array_test(names) \
1190 __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
1191
1192static int perf_evsel__roundtrip_name_test(void)
1193{
1194 int err = 0, ret = 0;
1195
1196 err = perf_evsel__name_array_test(perf_evsel__hw_names);
1197 if (err)
1198 ret = err;
1199
1200 err = perf_evsel__name_array_test(perf_evsel__sw_names);
1201 if (err)
1202 ret = err;
1203
1204 err = perf_evsel__roundtrip_cache_name_test();
1205 if (err)
1206 ret = err;
1207
1208 return ret;
1209}
1210
1211static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
1212 int size, bool should_be_signed)
1213{
1214 struct format_field *field = perf_evsel__field(evsel, name);
1215 int is_signed;
1216 int ret = 0;
1217
1218 if (field == NULL) {
1219 pr_debug("%s: \"%s\" field not found!\n", evsel->name, name);
1220 return -1;
1221 }
1222
1223 is_signed = !!(field->flags | FIELD_IS_SIGNED);
1224 if (should_be_signed && !is_signed) {
1225 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
1226 evsel->name, name, is_signed, should_be_signed);
1227 ret = -1;
1228 }
1229
1230 if (field->size != size) {
1231 pr_debug("%s: \"%s\" size (%d) should be %d!\n",
1232 evsel->name, name, field->size, size);
1233 ret = -1;
1234 }
1235
1236 return ret;
1237}
1238
1239static int perf_evsel__tp_sched_test(void)
1240{
1241 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0);
1242 int ret = 0;
1243
1244 if (evsel == NULL) {
1245 pr_debug("perf_evsel__new\n");
1246 return -1;
1247 }
1248
1249 if (perf_evsel__test_field(evsel, "prev_comm", 16, true))
1250 ret = -1;
1251
1252 if (perf_evsel__test_field(evsel, "prev_pid", 4, true))
1253 ret = -1;
1254
1255 if (perf_evsel__test_field(evsel, "prev_prio", 4, true))
1256 ret = -1;
1257
1258 if (perf_evsel__test_field(evsel, "prev_state", 8, true))
1259 ret = -1;
1260
1261 if (perf_evsel__test_field(evsel, "next_comm", 16, true))
1262 ret = -1;
1263
1264 if (perf_evsel__test_field(evsel, "next_pid", 4, true))
1265 ret = -1;
1266
1267 if (perf_evsel__test_field(evsel, "next_prio", 4, true))
1268 ret = -1;
1269
1270 perf_evsel__delete(evsel);
1271
1272 evsel = perf_evsel__newtp("sched", "sched_wakeup", 0);
1273
1274 if (perf_evsel__test_field(evsel, "comm", 16, true))
1275 ret = -1;
1276
1277 if (perf_evsel__test_field(evsel, "pid", 4, true))
1278 ret = -1;
1279
1280 if (perf_evsel__test_field(evsel, "prio", 4, true))
1281 ret = -1;
1282
1283 if (perf_evsel__test_field(evsel, "success", 4, true))
1284 ret = -1;
1285
1286 if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
1287 ret = -1;
1288
1289 return ret;
1290}
1291
1292static int test__syscall_open_tp_fields(void)
1293{
1294 struct perf_record_opts opts = {
1295 .target = {
1296 .uid = UINT_MAX,
1297 .uses_mmap = true,
1298 },
1299 .no_delay = true,
1300 .freq = 1,
1301 .mmap_pages = 256,
1302 .raw_samples = true,
1303 };
1304 const char *filename = "/etc/passwd";
1305 int flags = O_RDONLY | O_DIRECTORY;
1306 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
1307 struct perf_evsel *evsel;
1308 int err = -1, i, nr_events = 0, nr_polls = 0;
1309
1310 if (evlist == NULL) {
1311 pr_debug("%s: perf_evlist__new\n", __func__);
1312 goto out;
1313 }
1314
1315 evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
1316 if (evsel == NULL) {
1317 pr_debug("%s: perf_evsel__newtp\n", __func__);
1318 goto out_delete_evlist;
1319 }
1320
1321 perf_evlist__add(evlist, evsel);
1322
1323 err = perf_evlist__create_maps(evlist, &opts.target);
1324 if (err < 0) {
1325 pr_debug("%s: perf_evlist__create_maps\n", __func__);
1326 goto out_delete_evlist;
1327 }
1328
1329 perf_evsel__config(evsel, &opts, evsel);
1330
1331 evlist->threads->map[0] = getpid();
1332
1333 err = perf_evlist__open(evlist);
1334 if (err < 0) {
1335 pr_debug("perf_evlist__open: %s\n", strerror(errno));
1336 goto out_delete_evlist;
1337 }
1338
1339 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1340 if (err < 0) {
1341 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
1342 goto out_delete_evlist;
1343 }
1344
1345 perf_evlist__enable(evlist);
1346
1347 /*
1348 * Generate the event:
1349 */
1350 open(filename, flags);
1351
1352 while (1) {
1353 int before = nr_events;
1354
1355 for (i = 0; i < evlist->nr_mmaps; i++) {
1356 union perf_event *event;
1357
1358 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1359 const u32 type = event->header.type;
1360 int tp_flags;
1361 struct perf_sample sample;
1362
1363 ++nr_events;
1364
1365 if (type != PERF_RECORD_SAMPLE)
1366 continue;
1367
1368 err = perf_evsel__parse_sample(evsel, event, &sample);
1369 if (err) {
1370 pr_err("Can't parse sample, err = %d\n", err);
1371 goto out_munmap;
1372 }
1373
1374 tp_flags = perf_evsel__intval(evsel, &sample, "flags");
1375
1376 if (flags != tp_flags) {
1377 pr_debug("%s: Expected flags=%#x, got %#x\n",
1378 __func__, flags, tp_flags);
1379 goto out_munmap;
1380 }
1381
1382 goto out_ok;
1383 }
1384 }
1385
1386 if (nr_events == before)
1387 poll(evlist->pollfd, evlist->nr_fds, 10);
1388
1389 if (++nr_polls > 5) {
1390 pr_debug("%s: no events!\n", __func__);
1391 goto out_munmap;
1392 }
1393 }
1394out_ok:
1395 err = 0;
1396out_munmap:
1397 perf_evlist__munmap(evlist);
1398out_delete_evlist:
1399 perf_evlist__delete(evlist);
1400out:
1401 return err;
1402}
1403
1095static struct test { 1404static struct test {
1096 const char *desc; 1405 const char *desc;
1097 int (*func)(void); 1406 int (*func)(void);
@@ -1135,6 +1444,18 @@ static struct test {
1135 .func = dso__test_data, 1444 .func = dso__test_data,
1136 }, 1445 },
1137 { 1446 {
1447 .desc = "roundtrip evsel->name check",
1448 .func = perf_evsel__roundtrip_name_test,
1449 },
1450 {
1451 .desc = "Check parsing of sched tracepoints fields",
1452 .func = perf_evsel__tp_sched_test,
1453 },
1454 {
1455 .desc = "Generate and check syscalls:sys_enter_open event fields",
1456 .func = test__syscall_open_tp_fields,
1457 },
1458 {
1138 .func = NULL, 1459 .func = NULL,
1139 }, 1460 },
1140}; 1461};
@@ -1199,7 +1520,7 @@ static int perf_test__list(int argc, const char **argv)
1199 return 0; 1520 return 0;
1200} 1521}
1201 1522
1202int cmd_test(int argc, const char **argv, const char *prefix __used) 1523int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
1203{ 1524{
1204 const char * const test_usage[] = { 1525 const char * const test_usage[] = {
1205 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", 1526 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",