blob: fa9bc804e67af1d3a31a9d3676457219a1c183b1 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LINUX_POWERPC_PERF_REQ_GEN_PERF_H_
#define LINUX_POWERPC_PERF_REQ_GEN_PERF_H_
#include <linux/perf_event.h>
#include <linux/stringify.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