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