162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef LINUX_POWERPC_PERF_REQ_GEN_PERF_H_
362306a36Sopenharmony_ci#define LINUX_POWERPC_PERF_REQ_GEN_PERF_H_
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/perf_event.h>
662306a36Sopenharmony_ci#include <linux/stringify.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef REQUEST_FILE
962306a36Sopenharmony_ci#error "REQUEST_FILE must be defined before including"
1062306a36Sopenharmony_ci#endif
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifndef NAME_LOWER
1362306a36Sopenharmony_ci#error "NAME_LOWER must be defined before including"
1462306a36Sopenharmony_ci#endif
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#ifndef NAME_UPPER
1762306a36Sopenharmony_ci#error "NAME_UPPER must be defined before including"
1862306a36Sopenharmony_ci#endif
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define BE_TYPE_b1 __u8
2162306a36Sopenharmony_ci#define BE_TYPE_b2 __be16
2262306a36Sopenharmony_ci#define BE_TYPE_b4 __be32
2362306a36Sopenharmony_ci#define BE_TYPE_b8 __be64
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define BYTES_TO_BE_TYPE(bytes) \
2662306a36Sopenharmony_ci		BE_TYPE_b##bytes
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define CAT2_(a, b) a ## b
2962306a36Sopenharmony_ci#define CAT2(a, b) CAT2_(a, b)
3062306a36Sopenharmony_ci#define CAT3_(a, b, c) a ## b ## c
3162306a36Sopenharmony_ci#define CAT3(a, b, c) CAT3_(a, b, c)
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/*
3462306a36Sopenharmony_ci * enumerate the request values as
3562306a36Sopenharmony_ci * <NAME_UPPER>_<request name> = <request value>
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_ci#define REQUEST_VALUE__(name_upper, r_name) name_upper ## _ ## r_name
3862306a36Sopenharmony_ci#define REQUEST_VALUE_(name_upper, r_name) REQUEST_VALUE__(name_upper, r_name)
3962306a36Sopenharmony_ci#define REQUEST_VALUE(r_name) REQUEST_VALUE_(NAME_UPPER, r_name)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#include "_clear.h"
4262306a36Sopenharmony_ci#define REQUEST_(r_name, r_value, r_idx_1, r_fields) \
4362306a36Sopenharmony_ci	REQUEST_VALUE(r_name) = r_value,
4462306a36Sopenharmony_cienum CAT2(NAME_LOWER, _requests) {
4562306a36Sopenharmony_ci#include REQUEST_FILE
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/*
4962306a36Sopenharmony_ci * For each request:
5062306a36Sopenharmony_ci * struct <NAME_LOWER>_<request name> {
5162306a36Sopenharmony_ci *	r_fields
5262306a36Sopenharmony_ci * };
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_ci#include "_clear.h"
5562306a36Sopenharmony_ci#define STRUCT_NAME__(name_lower, r_name) name_lower ## _ ## r_name
5662306a36Sopenharmony_ci#define STRUCT_NAME_(name_lower, r_name) STRUCT_NAME__(name_lower, r_name)
5762306a36Sopenharmony_ci#define STRUCT_NAME(r_name) STRUCT_NAME_(NAME_LOWER, r_name)
5862306a36Sopenharmony_ci#define REQUEST_(r_name, r_value, r_idx_1, r_fields)	\
5962306a36Sopenharmony_cistruct STRUCT_NAME(r_name) {				\
6062306a36Sopenharmony_ci	r_fields					\
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci#define __field_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) \
6362306a36Sopenharmony_ci	BYTES_TO_BE_TYPE(f_bytes) f_name;
6462306a36Sopenharmony_ci#define __count_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) \
6562306a36Sopenharmony_ci	__field_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name)
6662306a36Sopenharmony_ci#define __array_(r_name, r_value, r_idx_1, a_offset, a_bytes, a_name) \
6762306a36Sopenharmony_ci	__u8 a_name[a_bytes];
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#include REQUEST_FILE
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * Generate a check of the field offsets
7362306a36Sopenharmony_ci * <NAME_LOWER>_assert_offsets_correct()
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_ci#include "_clear.h"
7662306a36Sopenharmony_ci#define REQUEST_(r_name, r_value, index, r_fields)			\
7762306a36Sopenharmony_cir_fields
7862306a36Sopenharmony_ci#define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name) \
7962306a36Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct STRUCT_NAME(r_name), f_name) != f_offset);
8062306a36Sopenharmony_ci#define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) \
8162306a36Sopenharmony_ci	__field_(r_name, r_value, r_idx_1, c_offset, c_size, c_name)
8262306a36Sopenharmony_ci#define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) \
8362306a36Sopenharmony_ci	__field_(r_name, r_value, r_idx_1, a_offset, a_size, a_name)
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic inline void CAT2(NAME_LOWER, _assert_offsets_correct)(void)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci#include REQUEST_FILE
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/*
9162306a36Sopenharmony_ci * Generate event attributes:
9262306a36Sopenharmony_ci * PMU_EVENT_ATTR_STRING(<request name>_<field name>,
9362306a36Sopenharmony_ci *	<NAME_LOWER>_event_attr_<request name>_<field name>,
9462306a36Sopenharmony_ci *		"request=<request value>"
9562306a36Sopenharmony_ci *		"starting_index=<starting index type>"
9662306a36Sopenharmony_ci *		"counter_info_version=CURRENT_COUNTER_INFO_VERSION"
9762306a36Sopenharmony_ci *		"length=<f_size>"
9862306a36Sopenharmony_ci *		"offset=<f_offset>")
9962306a36Sopenharmony_ci *
10062306a36Sopenharmony_ci *	TODO: counter_info_version may need to vary, we should interperate the
10162306a36Sopenharmony_ci *	value to some extent
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_ci#define EVENT_ATTR_NAME__(name, r_name, c_name) \
10462306a36Sopenharmony_ci	name ## _event_attr_ ## r_name ## _ ## c_name
10562306a36Sopenharmony_ci#define EVENT_ATTR_NAME_(name, r_name, c_name) \
10662306a36Sopenharmony_ci	EVENT_ATTR_NAME__(name, r_name, c_name)
10762306a36Sopenharmony_ci#define EVENT_ATTR_NAME(r_name, c_name) \
10862306a36Sopenharmony_ci	EVENT_ATTR_NAME_(NAME_LOWER, r_name, c_name)
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#include "_clear.h"
11162306a36Sopenharmony_ci#define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name)
11262306a36Sopenharmony_ci#define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name)
11362306a36Sopenharmony_ci#define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name)	\
11462306a36Sopenharmony_ciPMU_EVENT_ATTR_STRING(							\
11562306a36Sopenharmony_ci		CAT3(r_name, _, c_name),				\
11662306a36Sopenharmony_ci		EVENT_ATTR_NAME(r_name, c_name),			\
11762306a36Sopenharmony_ci		"request=" __stringify(r_value) ","			\
11862306a36Sopenharmony_ci		r_idx_1 ","						\
11962306a36Sopenharmony_ci		"counter_info_version="					\
12062306a36Sopenharmony_ci			__stringify(COUNTER_INFO_VERSION_CURRENT) ","	\
12162306a36Sopenharmony_ci		"length=" #c_size ","					\
12262306a36Sopenharmony_ci		"offset=" #c_offset)
12362306a36Sopenharmony_ci#define REQUEST_(r_name, r_value, r_idx_1, r_fields)			\
12462306a36Sopenharmony_ci	r_fields
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci#include REQUEST_FILE
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/*
12962306a36Sopenharmony_ci * Define event attribute array
13062306a36Sopenharmony_ci * static struct attribute *hv_gpci_event_attrs[] = {
13162306a36Sopenharmony_ci *	&<NAME_LOWER>_event_attr_<request name>_<field name>.attr,
13262306a36Sopenharmony_ci * };
13362306a36Sopenharmony_ci */
13462306a36Sopenharmony_ci#include "_clear.h"
13562306a36Sopenharmony_ci#define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name)
13662306a36Sopenharmony_ci#define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name)	\
13762306a36Sopenharmony_ci	&EVENT_ATTR_NAME(r_name, c_name).attr.attr,
13862306a36Sopenharmony_ci#define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name)
13962306a36Sopenharmony_ci#define REQUEST_(r_name, r_value, r_idx_1, r_fields)			\
14062306a36Sopenharmony_ci	r_fields
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci/* Generate event list for platforms with counter_info_version 0x6 or below */
14362306a36Sopenharmony_cistatic __maybe_unused struct attribute *hv_gpci_event_attrs_v6[] = {
14462306a36Sopenharmony_ci#include REQUEST_FILE
14562306a36Sopenharmony_ci	NULL
14662306a36Sopenharmony_ci};
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/*
14962306a36Sopenharmony_ci * Based on getPerfCountInfo v1.018 documentation, some of the hv-gpci
15062306a36Sopenharmony_ci * events were deprecated for platform firmware that supports
15162306a36Sopenharmony_ci * counter_info_version 0x8 or above.
15262306a36Sopenharmony_ci * Those deprecated events are still part of platform firmware that
15362306a36Sopenharmony_ci * support counter_info_version 0x6 and below. As per the getPerfCountInfo
15462306a36Sopenharmony_ci * v1.018 documentation there is no counter_info_version 0x7.
15562306a36Sopenharmony_ci * Undefining macro ENABLE_EVENTS_COUNTERINFO_V6, to disable the addition of
15662306a36Sopenharmony_ci * deprecated events in "hv_gpci_event_attrs" attribute group, for platforms
15762306a36Sopenharmony_ci * that supports counter_info_version 0x8 or above.
15862306a36Sopenharmony_ci */
15962306a36Sopenharmony_ci#undef ENABLE_EVENTS_COUNTERINFO_V6
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/* Generate event list for platforms with counter_info_version 0x8 or above*/
16262306a36Sopenharmony_cistatic __maybe_unused struct attribute *hv_gpci_event_attrs[] = {
16362306a36Sopenharmony_ci#include REQUEST_FILE
16462306a36Sopenharmony_ci	NULL
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* cleanup */
16862306a36Sopenharmony_ci#include "_clear.h"
16962306a36Sopenharmony_ci#undef EVENT_ATTR_NAME
17062306a36Sopenharmony_ci#undef EVENT_ATTR_NAME_
17162306a36Sopenharmony_ci#undef BIT_NAME
17262306a36Sopenharmony_ci#undef BIT_NAME_
17362306a36Sopenharmony_ci#undef STRUCT_NAME
17462306a36Sopenharmony_ci#undef REQUEST_VALUE
17562306a36Sopenharmony_ci#undef REQUEST_VALUE_
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci#endif
178