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 */
28int bhrb_filter_map_valid_common[] = {
29	PERF_SAMPLE_BRANCH_ANY,
30	PERF_SAMPLE_BRANCH_ANY_CALL,
31};
32
33/* Valid bhrb filters in power10 */
34int bhrb_filter_map_valid_p10[] = {
35	PERF_SAMPLE_BRANCH_IND_CALL,
36	PERF_SAMPLE_BRANCH_COND,
37};
38
39#define EventCode 0x1001e
40
41static 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
111int main(void)
112{
113	return test_harness(bhrb_filter_map_test, "bhrb_filter_map_test");
114}
115