b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 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 |