xref: /openbmc/linux/arch/powerpc/perf/req-gen/perf.h (revision d40d48e1)
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 static __maybe_unused struct attribute *hv_gpci_event_attrs[] = {
143 #include REQUEST_FILE
144 	NULL
145 };
146 
147 /* cleanup */
148 #include "_clear.h"
149 #undef EVENT_ATTR_NAME
150 #undef EVENT_ATTR_NAME_
151 #undef BIT_NAME
152 #undef BIT_NAME_
153 #undef STRUCT_NAME
154 #undef REQUEST_VALUE
155 #undef REQUEST_VALUE_
156 
157 #endif
158