/* SPDX-License-Identifier: GPL-2.0 */ #ifndef LINUX_POWERPC_PERF_REQ_GEN_PERF_H_ #define LINUX_POWERPC_PERF_REQ_GEN_PERF_H_ #include <linux/perf_event.h> #include <linux/stringify.h> #ifndef REQUEST_FILE #error "REQUEST_FILE must be defined before including" #endif #ifndef NAME_LOWER #error "NAME_LOWER must be defined before including" #endif #ifndef NAME_UPPER #error "NAME_UPPER must be defined before including" #endif #define BE_TYPE_b1 __u8 #define BE_TYPE_b2 __be16 #define BE_TYPE_b4 __be32 #define BE_TYPE_b8 __be64 #define BYTES_TO_BE_TYPE(bytes) \ BE_TYPE_b##bytes #define CAT2_(a, b) a ## b #define CAT2(a, b) CAT2_(a, b) #define CAT3_(a, b, c) a ## b ## c #define CAT3(a, b, c) CAT3_(a, b, c) /* * enumerate the request values as * <NAME_UPPER>_<request name> = <request value> */ #define REQUEST_VALUE__(name_upper, r_name) name_upper ## _ ## r_name #define REQUEST_VALUE_(name_upper, r_name) REQUEST_VALUE__(name_upper, r_name) #define REQUEST_VALUE(r_name) REQUEST_VALUE_(NAME_UPPER, r_name) #include "_clear.h" #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ REQUEST_VALUE(r_name) = r_value, enum CAT2(NAME_LOWER, _requests) { #include REQUEST_FILE }; /* * For each request: * struct <NAME_LOWER>_<request name> { * r_fields * }; */ #include "_clear.h" #define STRUCT_NAME__(name_lower, r_name) name_lower ## _ ## r_name #define STRUCT_NAME_(name_lower, r_name) STRUCT_NAME__(name_lower, r_name) #define STRUCT_NAME(r_name) STRUCT_NAME_(NAME_LOWER, r_name) #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ struct STRUCT_NAME(r_name) { \ r_fields \ }; #define __field_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) \ BYTES_TO_BE_TYPE(f_bytes) f_name; #define __count_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) \ __field_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) #define __array_(r_name, r_value, r_idx_1, a_offset, a_bytes, a_name) \ __u8 a_name[a_bytes]; #include REQUEST_FILE /* * Generate a check of the field offsets * <NAME_LOWER>_assert_offsets_correct() */ #include "_clear.h" #define REQUEST_(r_name, r_value, index, r_fields) \ r_fields #define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name) \ BUILD_BUG_ON(offsetof(struct STRUCT_NAME(r_name), f_name) != f_offset); #define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) \ __field_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) #define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) \ __field_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) static inline void CAT2(NAME_LOWER, _assert_offsets_correct)(void) { #include REQUEST_FILE } /* * Generate event attributes: * PMU_EVENT_ATTR_STRING(<request name>_<field name>, * <NAME_LOWER>_event_attr_<request name>_<field name>, * "request=<request value>" * "starting_index=<starting index type>" * "counter_info_version=CURRENT_COUNTER_INFO_VERSION" * "length=<f_size>" * "offset=<f_offset>") * * TODO: counter_info_version may need to vary, we should interperate the * value to some extent */ #define EVENT_ATTR_NAME__(name, r_name, c_name) \ name ## _event_attr_ ## r_name ## _ ## c_name #define EVENT_ATTR_NAME_(name, r_name, c_name) \ EVENT_ATTR_NAME__(name, r_name, c_name) #define EVENT_ATTR_NAME(r_name, c_name) \ EVENT_ATTR_NAME_(NAME_LOWER, r_name, c_name) #include "_clear.h" #define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name) #define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) #define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) \ PMU_EVENT_ATTR_STRING( \ CAT3(r_name, _, c_name), \ EVENT_ATTR_NAME(r_name, c_name), \ "request=" __stringify(r_value) "," \ r_idx_1 "," \ "counter_info_version=" \ __stringify(COUNTER_INFO_VERSION_CURRENT) "," \ "length=" #c_size "," \ "offset=" #c_offset) #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ r_fields #include REQUEST_FILE /* * Define event attribute array * static struct attribute *hv_gpci_event_attrs[] = { * &<NAME_LOWER>_event_attr_<request name>_<field name>.attr, * }; */ #include "_clear.h" #define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name) #define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) \ &EVENT_ATTR_NAME(r_name, c_name).attr.attr, #define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ r_fields /* Generate event list for platforms with counter_info_version 0x6 or below */ static __maybe_unused struct attribute *hv_gpci_event_attrs_v6[] = { #include REQUEST_FILE NULL }; /* * Based on getPerfCountInfo v1.018 documentation, some of the hv-gpci * events were deprecated for platform firmware that supports * counter_info_version 0x8 or above. * Those deprecated events are still part of platform firmware that * support counter_info_version 0x6 and below. As per the getPerfCountInfo * v1.018 documentation there is no counter_info_version 0x7. * Undefining macro ENABLE_EVENTS_COUNTERINFO_V6, to disable the addition of * deprecated events in "hv_gpci_event_attrs" attribute group, for platforms * that supports counter_info_version 0x8 or above. */ #undef ENABLE_EVENTS_COUNTERINFO_V6 /* Generate event list for platforms with counter_info_version 0x8 or above*/ static __maybe_unused struct attribute *hv_gpci_event_attrs[] = { #include REQUEST_FILE NULL }; /* cleanup */ #include "_clear.h" #undef EVENT_ATTR_NAME #undef EVENT_ATTR_NAME_ #undef BIT_NAME #undef BIT_NAME_ #undef STRUCT_NAME #undef REQUEST_VALUE #undef REQUEST_VALUE_ #endif