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.c188
1 files changed, 179 insertions, 9 deletions
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 3854e869dce1..3e087ce8daa6 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -15,6 +15,8 @@
15#include "util/thread_map.h" 15#include "util/thread_map.h"
16#include "../../include/linux/hw_breakpoint.h" 16#include "../../include/linux/hw_breakpoint.h"
17 17
18#include <sys/mman.h>
19
18static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) 20static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
19{ 21{
20 bool *visited = symbol__priv(sym); 22 bool *visited = symbol__priv(sym);
@@ -276,7 +278,7 @@ static int test__open_syscall_event(void)
276 return -1; 278 return -1;
277 } 279 }
278 280
279 threads = thread_map__new(-1, getpid()); 281 threads = thread_map__new(-1, getpid(), UINT_MAX);
280 if (threads == NULL) { 282 if (threads == NULL) {
281 pr_debug("thread_map__new\n"); 283 pr_debug("thread_map__new\n");
282 return -1; 284 return -1;
@@ -342,7 +344,7 @@ static int test__open_syscall_event_on_all_cpus(void)
342 return -1; 344 return -1;
343 } 345 }
344 346
345 threads = thread_map__new(-1, getpid()); 347 threads = thread_map__new(-1, getpid(), UINT_MAX);
346 if (threads == NULL) { 348 if (threads == NULL) {
347 pr_debug("thread_map__new\n"); 349 pr_debug("thread_map__new\n");
348 return -1; 350 return -1;
@@ -490,7 +492,7 @@ static int test__basic_mmap(void)
490 expected_nr_events[i] = random() % 257; 492 expected_nr_events[i] = random() % 257;
491 } 493 }
492 494
493 threads = thread_map__new(-1, getpid()); 495 threads = thread_map__new(-1, getpid(), UINT_MAX);
494 if (threads == NULL) { 496 if (threads == NULL) {
495 pr_debug("thread_map__new\n"); 497 pr_debug("thread_map__new\n");
496 return -1; 498 return -1;
@@ -1008,12 +1010,9 @@ realloc:
1008static int test__PERF_RECORD(void) 1010static int test__PERF_RECORD(void)
1009{ 1011{
1010 struct perf_record_opts opts = { 1012 struct perf_record_opts opts = {
1011 .target_pid = -1,
1012 .target_tid = -1,
1013 .no_delay = true, 1013 .no_delay = true,
1014 .freq = 10, 1014 .freq = 10,
1015 .mmap_pages = 256, 1015 .mmap_pages = 256,
1016 .sample_id_all_avail = true,
1017 }; 1016 };
1018 cpu_set_t *cpu_mask = NULL; 1017 cpu_set_t *cpu_mask = NULL;
1019 size_t cpu_mask_size = 0; 1018 size_t cpu_mask_size = 0;
@@ -1054,7 +1053,7 @@ static int test__PERF_RECORD(void)
1054 * we're monitoring, the one forked there. 1053 * we're monitoring, the one forked there.
1055 */ 1054 */
1056 err = perf_evlist__create_maps(evlist, opts.target_pid, 1055 err = perf_evlist__create_maps(evlist, opts.target_pid,
1057 opts.target_tid, opts.cpu_list); 1056 opts.target_tid, UINT_MAX, opts.cpu_list);
1058 if (err < 0) { 1057 if (err < 0) {
1059 pr_debug("Not enough memory to create thread/cpu maps\n"); 1058 pr_debug("Not enough memory to create thread/cpu maps\n");
1060 goto out_delete_evlist; 1059 goto out_delete_evlist;
@@ -1296,6 +1295,173 @@ out:
1296 return (err < 0 || errs > 0) ? -1 : 0; 1295 return (err < 0 || errs > 0) ? -1 : 0;
1297} 1296}
1298 1297
1298
1299#if defined(__x86_64__) || defined(__i386__)
1300
1301#define barrier() asm volatile("" ::: "memory")
1302
1303static u64 rdpmc(unsigned int counter)
1304{
1305 unsigned int low, high;
1306
1307 asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
1308
1309 return low | ((u64)high) << 32;
1310}
1311
1312static u64 rdtsc(void)
1313{
1314 unsigned int low, high;
1315
1316 asm volatile("rdtsc" : "=a" (low), "=d" (high));
1317
1318 return low | ((u64)high) << 32;
1319}
1320
1321static u64 mmap_read_self(void *addr)
1322{
1323 struct perf_event_mmap_page *pc = addr;
1324 u32 seq, idx, time_mult = 0, time_shift = 0;
1325 u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
1326
1327 do {
1328 seq = pc->lock;
1329 barrier();
1330
1331 enabled = pc->time_enabled;
1332 running = pc->time_running;
1333
1334 if (enabled != running) {
1335 cyc = rdtsc();
1336 time_mult = pc->time_mult;
1337 time_shift = pc->time_shift;
1338 time_offset = pc->time_offset;
1339 }
1340
1341 idx = pc->index;
1342 count = pc->offset;
1343 if (idx)
1344 count += rdpmc(idx - 1);
1345
1346 barrier();
1347 } while (pc->lock != seq);
1348
1349 if (enabled != running) {
1350 u64 quot, rem;
1351
1352 quot = (cyc >> time_shift);
1353 rem = cyc & ((1 << time_shift) - 1);
1354 delta = time_offset + quot * time_mult +
1355 ((rem * time_mult) >> time_shift);
1356
1357 enabled += delta;
1358 if (idx)
1359 running += delta;
1360
1361 quot = count / running;
1362 rem = count % running;
1363 count = quot * enabled + (rem * enabled) / running;
1364 }
1365
1366 return count;
1367}
1368
1369/*
1370 * If the RDPMC instruction faults then signal this back to the test parent task:
1371 */
1372static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used)
1373{
1374 exit(-1);
1375}
1376
1377static int __test__rdpmc(void)
1378{
1379 long page_size = sysconf(_SC_PAGE_SIZE);
1380 volatile int tmp = 0;
1381 u64 i, loops = 1000;
1382 int n;
1383 int fd;
1384 void *addr;
1385 struct perf_event_attr attr = {
1386 .type = PERF_TYPE_HARDWARE,
1387 .config = PERF_COUNT_HW_INSTRUCTIONS,
1388 .exclude_kernel = 1,
1389 };
1390 u64 delta_sum = 0;
1391 struct sigaction sa;
1392
1393 sigfillset(&sa.sa_mask);
1394 sa.sa_sigaction = segfault_handler;
1395 sigaction(SIGSEGV, &sa, NULL);
1396
1397 fprintf(stderr, "\n\n");
1398
1399 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
1400 if (fd < 0) {
1401 die("Error: sys_perf_event_open() syscall returned "
1402 "with %d (%s)\n", fd, strerror(errno));
1403 }
1404
1405 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
1406 if (addr == (void *)(-1)) {
1407 die("Error: mmap() syscall returned "
1408 "with (%s)\n", strerror(errno));
1409 }
1410
1411 for (n = 0; n < 6; n++) {
1412 u64 stamp, now, delta;
1413
1414 stamp = mmap_read_self(addr);
1415
1416 for (i = 0; i < loops; i++)
1417 tmp++;
1418
1419 now = mmap_read_self(addr);
1420 loops *= 10;
1421
1422 delta = now - stamp;
1423 fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta);
1424
1425 delta_sum += delta;
1426 }
1427
1428 munmap(addr, page_size);
1429 close(fd);
1430
1431 fprintf(stderr, " ");
1432
1433 if (!delta_sum)
1434 return -1;
1435
1436 return 0;
1437}
1438
1439static int test__rdpmc(void)
1440{
1441 int status = 0;
1442 int wret = 0;
1443 int ret;
1444 int pid;
1445
1446 pid = fork();
1447 if (pid < 0)
1448 return -1;
1449
1450 if (!pid) {
1451 ret = __test__rdpmc();
1452
1453 exit(ret);
1454 }
1455
1456 wret = waitpid(pid, &status, 0);
1457 if (wret < 0 || status)
1458 return -1;
1459
1460 return 0;
1461}
1462
1463#endif
1464
1299static struct test { 1465static struct test {
1300 const char *desc; 1466 const char *desc;
1301 int (*func)(void); 1467 int (*func)(void);
@@ -1320,6 +1486,12 @@ static struct test {
1320 .desc = "parse events tests", 1486 .desc = "parse events tests",
1321 .func = test__parse_events, 1487 .func = test__parse_events,
1322 }, 1488 },
1489#if defined(__x86_64__) || defined(__i386__)
1490 {
1491 .desc = "x86 rdpmc test",
1492 .func = test__rdpmc,
1493 },
1494#endif
1323 { 1495 {
1324 .desc = "Validate PERF_RECORD_* events & perf_sample fields", 1496 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
1325 .func = test__PERF_RECORD, 1497 .func = test__PERF_RECORD,
@@ -1412,7 +1584,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __used)
1412 if (symbol__init() < 0) 1584 if (symbol__init() < 0)
1413 return -1; 1585 return -1;
1414 1586
1415 setup_pager();
1416
1417 return __cmd_test(argc, argv); 1587 return __cmd_test(argc, argv);
1418} 1588}