|
@@ -0,0 +1,155 @@
|
|
|
+#ifndef LINUX_POWERPC_PERF_REQ_GEN_PERF_H_
|
|
|
+#define LINUX_POWERPC_PERF_REQ_GEN_PERF_H_
|
|
|
+
|
|
|
+#include <linux/perf_event.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
|
|
|
+
|
|
|
+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
|