1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef LINUX_POWERPC_PERF_REQ_GEN_PERF_H_ 3 #define LINUX_POWERPC_PERF_REQ_GEN_PERF_H_ 4 5 #include <linux/perf_event.h> 6 #include <linux/stringify.h> 7 8 #ifndef REQUEST_FILE 9 #error "REQUEST_FILE must be defined before including" 10 #endif 11 12 #ifndef NAME_LOWER 13 #error "NAME_LOWER must be defined before including" 14 #endif 15 16 #ifndef NAME_UPPER 17 #error "NAME_UPPER must be defined before including" 18 #endif 19 20 #define BE_TYPE_b1 __u8 21 #define BE_TYPE_b2 __be16 22 #define BE_TYPE_b4 __be32 23 #define BE_TYPE_b8 __be64 24 25 #define BYTES_TO_BE_TYPE(bytes) \ 26 BE_TYPE_b##bytes 27 28 #define CAT2_(a, b) a ## b 29 #define CAT2(a, b) CAT2_(a, b) 30 #define CAT3_(a, b, c) a ## b ## c 31 #define CAT3(a, b, c) CAT3_(a, b, c) 32 33 /* 34 * enumerate the request values as 35 * <NAME_UPPER>_<request name> = <request value> 36 */ 37 #define REQUEST_VALUE__(name_upper, r_name) name_upper ## _ ## r_name 38 #define REQUEST_VALUE_(name_upper, r_name) REQUEST_VALUE__(name_upper, r_name) 39 #define REQUEST_VALUE(r_name) REQUEST_VALUE_(NAME_UPPER, r_name) 40 41 #include "_clear.h" 42 #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ 43 REQUEST_VALUE(r_name) = r_value, 44 enum CAT2(NAME_LOWER, _requests) { 45 #include REQUEST_FILE 46 }; 47 48 /* 49 * For each request: 50 * struct <NAME_LOWER>_<request name> { 51 * r_fields 52 * }; 53 */ 54 #include "_clear.h" 55 #define STRUCT_NAME__(name_lower, r_name) name_lower ## _ ## r_name 56 #define STRUCT_NAME_(name_lower, r_name) STRUCT_NAME__(name_lower, r_name) 57 #define STRUCT_NAME(r_name) STRUCT_NAME_(NAME_LOWER, r_name) 58 #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ 59 struct STRUCT_NAME(r_name) { \ 60 r_fields \ 61 }; 62 #define __field_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) \ 63 BYTES_TO_BE_TYPE(f_bytes) f_name; 64 #define __count_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) \ 65 __field_(r_name, r_value, r_idx_1, f_offset, f_bytes, f_name) 66 #define __array_(r_name, r_value, r_idx_1, a_offset, a_bytes, a_name) \ 67 __u8 a_name[a_bytes]; 68 69 #include REQUEST_FILE 70 71 /* 72 * Generate a check of the field offsets 73 * <NAME_LOWER>_assert_offsets_correct() 74 */ 75 #include "_clear.h" 76 #define REQUEST_(r_name, r_value, index, r_fields) \ 77 r_fields 78 #define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name) \ 79 BUILD_BUG_ON(offsetof(struct STRUCT_NAME(r_name), f_name) != f_offset); 80 #define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) \ 81 __field_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) 82 #define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) \ 83 __field_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) 84 85 static inline void CAT2(NAME_LOWER, _assert_offsets_correct)(void) 86 { 87 #include REQUEST_FILE 88 } 89 90 /* 91 * Generate event attributes: 92 * PMU_EVENT_ATTR_STRING(<request name>_<field name>, 93 * <NAME_LOWER>_event_attr_<request name>_<field name>, 94 * "request=<request value>" 95 * "starting_index=<starting index type>" 96 * "counter_info_version=CURRENT_COUNTER_INFO_VERSION" 97 * "length=<f_size>" 98 * "offset=<f_offset>") 99 * 100 * TODO: counter_info_version may need to vary, we should interperate the 101 * value to some extent 102 */ 103 #define EVENT_ATTR_NAME__(name, r_name, c_name) \ 104 name ## _event_attr_ ## r_name ## _ ## c_name 105 #define EVENT_ATTR_NAME_(name, r_name, c_name) \ 106 EVENT_ATTR_NAME__(name, r_name, c_name) 107 #define EVENT_ATTR_NAME(r_name, c_name) \ 108 EVENT_ATTR_NAME_(NAME_LOWER, r_name, c_name) 109 110 #include "_clear.h" 111 #define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name) 112 #define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) 113 #define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) \ 114 PMU_EVENT_ATTR_STRING( \ 115 CAT3(r_name, _, c_name), \ 116 EVENT_ATTR_NAME(r_name, c_name), \ 117 "request=" __stringify(r_value) "," \ 118 r_idx_1 "," \ 119 "counter_info_version=" \ 120 __stringify(COUNTER_INFO_VERSION_CURRENT) "," \ 121 "length=" #c_size "," \ 122 "offset=" #c_offset) 123 #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ 124 r_fields 125 126 #include REQUEST_FILE 127 128 /* 129 * Define event attribute array 130 * static struct attribute *hv_gpci_event_attrs[] = { 131 * &<NAME_LOWER>_event_attr_<request name>_<field name>.attr, 132 * }; 133 */ 134 #include "_clear.h" 135 #define __field_(r_name, r_value, r_idx_1, f_offset, f_size, f_name) 136 #define __count_(r_name, r_value, r_idx_1, c_offset, c_size, c_name) \ 137 &EVENT_ATTR_NAME(r_name, c_name).attr.attr, 138 #define __array_(r_name, r_value, r_idx_1, a_offset, a_size, a_name) 139 #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ 140 r_fields 141 142 /* Generate event list for platforms with counter_info_version 0x6 or below */ 143 static __maybe_unused struct attribute *hv_gpci_event_attrs_v6[] = { 144 #include REQUEST_FILE 145 NULL 146 }; 147 148 /* 149 * Based on getPerfCountInfo v1.018 documentation, some of the hv-gpci 150 * events were deprecated for platform firmware that supports 151 * counter_info_version 0x8 or above. 152 * Those deprecated events are still part of platform firmware that 153 * support counter_info_version 0x6 and below. As per the getPerfCountInfo 154 * v1.018 documentation there is no counter_info_version 0x7. 155 * Undefining macro ENABLE_EVENTS_COUNTERINFO_V6, to disable the addition of 156 * deprecated events in "hv_gpci_event_attrs" attribute group, for platforms 157 * that supports counter_info_version 0x8 or above. 158 */ 159 #undef ENABLE_EVENTS_COUNTERINFO_V6 160 161 /* Generate event list for platforms with counter_info_version 0x8 or above*/ 162 static __maybe_unused struct attribute *hv_gpci_event_attrs[] = { 163 #include REQUEST_FILE 164 NULL 165 }; 166 167 /* cleanup */ 168 #include "_clear.h" 169 #undef EVENT_ATTR_NAME 170 #undef EVENT_ATTR_NAME_ 171 #undef BIT_NAME 172 #undef BIT_NAME_ 173 #undef STRUCT_NAME 174 #undef REQUEST_VALUE 175 #undef REQUEST_VALUE_ 176 177 #endif 178