1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021 Facebook */
3 #include <test_progs.h>
4 #include "get_branch_snapshot.skel.h"
5 
6 static int *pfd_array;
7 static int cpu_cnt;
8 
9 static int create_perf_events(void)
10 {
11 	struct perf_event_attr attr = {0};
12 	int cpu;
13 
14 	/* create perf event */
15 	attr.size = sizeof(attr);
16 	attr.type = PERF_TYPE_RAW;
17 	attr.config = 0x1b00;
18 	attr.sample_type = PERF_SAMPLE_BRANCH_STACK;
19 	attr.branch_sample_type = PERF_SAMPLE_BRANCH_KERNEL |
20 		PERF_SAMPLE_BRANCH_USER | PERF_SAMPLE_BRANCH_ANY;
21 
22 	cpu_cnt = libbpf_num_possible_cpus();
23 	pfd_array = malloc(sizeof(int) * cpu_cnt);
24 	if (!pfd_array) {
25 		cpu_cnt = 0;
26 		return 1;
27 	}
28 
29 	for (cpu = 0; cpu < cpu_cnt; cpu++) {
30 		pfd_array[cpu] = syscall(__NR_perf_event_open, &attr,
31 					 -1, cpu, -1, PERF_FLAG_FD_CLOEXEC);
32 		if (pfd_array[cpu] < 0)
33 			break;
34 	}
35 
36 	return cpu == 0;
37 }
38 
39 static void close_perf_events(void)
40 {
41 	int cpu, fd;
42 
43 	for (cpu = 0; cpu < cpu_cnt; cpu++) {
44 		fd = pfd_array[cpu];
45 		if (fd < 0)
46 			break;
47 		close(fd);
48 	}
49 	free(pfd_array);
50 }
51 
52 void test_get_branch_snapshot(void)
53 {
54 	struct get_branch_snapshot *skel = NULL;
55 	int err;
56 
57 	if (create_perf_events()) {
58 		test__skip();  /* system doesn't support LBR */
59 		goto cleanup;
60 	}
61 
62 	skel = get_branch_snapshot__open_and_load();
63 	if (!ASSERT_OK_PTR(skel, "get_branch_snapshot__open_and_load"))
64 		goto cleanup;
65 
66 	err = kallsyms_find("bpf_testmod_loop_test", &skel->bss->address_low);
67 	if (!ASSERT_OK(err, "kallsyms_find"))
68 		goto cleanup;
69 
70 	err = kallsyms_find_next("bpf_testmod_loop_test", &skel->bss->address_high);
71 	if (!ASSERT_OK(err, "kallsyms_find_next"))
72 		goto cleanup;
73 
74 	err = get_branch_snapshot__attach(skel);
75 	if (!ASSERT_OK(err, "get_branch_snapshot__attach"))
76 		goto cleanup;
77 
78 	trigger_module_test_read(100);
79 
80 	if (skel->bss->total_entries < 16) {
81 		/* too few entries for the hit/waste test */
82 		test__skip();
83 		goto cleanup;
84 	}
85 
86 	ASSERT_GT(skel->bss->test1_hits, 6, "find_looptest_in_lbr");
87 
88 	/* Given we stop LBR in software, we will waste a few entries.
89 	 * But we should try to waste as few as possible entries. We are at
90 	 * about 7 on x86_64 systems.
91 	 * Add a check for < 10 so that we get heads-up when something
92 	 * changes and wastes too many entries.
93 	 */
94 	ASSERT_LT(skel->bss->wasted_entries, 10, "check_wasted_entries");
95 
96 cleanup:
97 	get_branch_snapshot__destroy(skel);
98 	close_perf_events();
99 }
100