1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2022, Athira Rajeev, IBM Corp.
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 
9 #include "../event.h"
10 #include "misc.h"
11 #include "utils.h"
12 
13 /*
14  * A perf sampling test to check bhrb filter
15  * map. All the branch filters are not supported
16  * in powerpc. Supported filters in:
17  * power10: any, any_call, ind_call, cond
18  * power9: any, any_call
19  *
20  * Testcase checks event open for invalid bhrb filter
21  * types should fail and valid filter types should pass.
22  * Testcase does validity check for these branch
23  * sample types.
24  */
25 
26 /* Invalid types for powerpc */
27 /* Valid bhrb filters in power9/power10 */
28 int bhrb_filter_map_valid_common[] = {
29 	PERF_SAMPLE_BRANCH_ANY,
30 	PERF_SAMPLE_BRANCH_ANY_CALL,
31 };
32 
33 /* Valid bhrb filters in power10 */
34 int bhrb_filter_map_valid_p10[] = {
35 	PERF_SAMPLE_BRANCH_IND_CALL,
36 	PERF_SAMPLE_BRANCH_COND,
37 };
38 
39 #define EventCode 0x1001e
40 
41 static int bhrb_filter_map_test(void)
42 {
43 	struct event event;
44 	int i;
45 
46 	/* Check for platform support for the test */
47 	SKIP_IF(platform_check_for_tests());
48 
49 	/*
50 	 * Skip for Generic compat PMU since
51 	 * bhrb filters is not supported
52 	 */
53 	SKIP_IF(check_for_generic_compat_pmu());
54 
55 	/* Init the event for the sampling test */
56 	event_init(&event, EventCode);
57 
58 	event.attr.sample_period = 1000;
59 	event.attr.sample_type = PERF_SAMPLE_BRANCH_STACK;
60 	event.attr.disabled = 1;
61 
62 	/* Invalid filter maps which are expected to fail in event_open */
63 	for (i = PERF_SAMPLE_BRANCH_USER_SHIFT; i < PERF_SAMPLE_BRANCH_MAX_SHIFT; i++) {
64 		/* Skip the valid branch sample type */
65 		if (i == PERF_SAMPLE_BRANCH_ANY_SHIFT || i == PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT \
66 			|| i == PERF_SAMPLE_BRANCH_IND_CALL_SHIFT || i == PERF_SAMPLE_BRANCH_COND_SHIFT)
67 			continue;
68 		event.attr.branch_sample_type = 1U << i;
69 		FAIL_IF(!event_open(&event));
70 	}
71 
72 	/* valid filter maps for power9/power10 which are expected to pass in event_open */
73 	for (i = 0; i < ARRAY_SIZE(bhrb_filter_map_valid_common); i++) {
74 		event.attr.branch_sample_type = bhrb_filter_map_valid_common[i];
75 		FAIL_IF(event_open(&event));
76 		event_close(&event);
77 	}
78 
79 	/*
80 	 * filter maps which are valid in power10 and invalid in power9.
81 	 * PVR check is used here since PMU specific data like bhrb filter
82 	 * alternative tests is handled by respective PMU driver code and
83 	 * using PVR will work correctly for all cases including generic
84 	 * compat mode.
85 	 */
86 	if (PVR_VER(mfspr(SPRN_PVR)) == POWER10) {
87 		for (i = 0; i < ARRAY_SIZE(bhrb_filter_map_valid_p10); i++) {
88 			event.attr.branch_sample_type = bhrb_filter_map_valid_p10[i];
89 			FAIL_IF(event_open(&event));
90 			event_close(&event);
91 		}
92 	} else {
93 		for (i = 0; i < ARRAY_SIZE(bhrb_filter_map_valid_p10); i++) {
94 			event.attr.branch_sample_type = bhrb_filter_map_valid_p10[i];
95 			FAIL_IF(!event_open(&event));
96 		}
97 	}
98 
99 	/*
100 	 * Combine filter maps which includes a valid branch filter and an invalid branch
101 	 * filter. Example: any ( PERF_SAMPLE_BRANCH_ANY) and any_call
102 	 * (PERF_SAMPLE_BRANCH_ANY_CALL).
103 	 * The perf_event_open should fail in this case.
104 	 */
105 	event.attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY | PERF_SAMPLE_BRANCH_ANY_CALL;
106 	FAIL_IF(!event_open(&event));
107 
108 	return 0;
109 }
110 
111 int main(void)
112 {
113 	return test_harness(bhrb_filter_map_test, "bhrb_filter_map_test");
114 }
115