summaryrefslogtreecommitdiff
path: root/drivers/perf/arm_cspmu/arm_cspmu.h
blob: 2621f31111483b2a6519649e5f8a8c76c2f38352 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* SPDX-License-Identifier: GPL-2.0
 *
 * ARM CoreSight Architecture PMU driver.
 * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 *
 */

#ifndef __ARM_CSPMU_H__
#define __ARM_CSPMU_H__

#include <linux/bitfield.h>
#include <linux/cpumask.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/perf_event.h>
#include <linux/platform_device.h>
#include <linux/types.h>

#define to_arm_cspmu(p) (container_of(p, struct arm_cspmu, pmu))

#define ARM_CSPMU_EXT_ATTR(_name, _func, _config)			\
	(&((struct dev_ext_attribute[]){				\
		{							\
			.attr = __ATTR(_name, 0444, _func, NULL),	\
			.var = (void *)_config				\
		}							\
	})[0].attr.attr)

#define ARM_CSPMU_FORMAT_ATTR(_name, _config)				\
	ARM_CSPMU_EXT_ATTR(_name, device_show_string, _config)

#define ARM_CSPMU_EVENT_ATTR(_name, _config)				\
	PMU_EVENT_ATTR_ID(_name, arm_cspmu_sysfs_event_show, _config)


/* Default event id mask */
#define ARM_CSPMU_EVENT_MASK	GENMASK_ULL(63, 0)

/* Default filter value mask */
#define ARM_CSPMU_FILTER_MASK	GENMASK_ULL(63, 0)

/* Default event format */
#define ARM_CSPMU_FORMAT_EVENT_ATTR	\
	ARM_CSPMU_FORMAT_ATTR(event, "config:0-32")

/* Default filter format */
#define ARM_CSPMU_FORMAT_FILTER_ATTR	\
	ARM_CSPMU_FORMAT_ATTR(filter, "config1:0-31")

/*
 * This is the default event number for cycle count, if supported, since the
 * ARM Coresight PMU specification does not define a standard event code
 * for cycle count.
 */
#define ARM_CSPMU_EVT_CYCLES_DEFAULT	(0x1ULL << 32)

/*
 * The ARM Coresight PMU supports up to 256 event counters.
 * If the counters are larger-than 32-bits, then the PMU includes at
 * most 128 counters.
 */
#define ARM_CSPMU_MAX_HW_CNTRS		256

/* The cycle counter, if implemented, is located at counter[31]. */
#define ARM_CSPMU_CYCLE_CNTR_IDX	31

/* PMIIDR register field */
#define ARM_CSPMU_PMIIDR_IMPLEMENTER	GENMASK(11, 0)
#define ARM_CSPMU_PMIIDR_PRODUCTID	GENMASK(31, 20)

/* JEDEC-assigned JEP106 identification code */
#define ARM_CSPMU_IMPL_ID_NVIDIA	0x36B
#define ARM_CSPMU_IMPL_ID_AMPERE	0xA16

struct arm_cspmu;

/* This tracks the events assigned to each counter in the PMU. */
struct arm_cspmu_hw_events {
	/* The events that are active on the PMU for a given logical index. */
	struct perf_event **events;

	/*
	 * Each bit indicates a logical counter is being used (or not) for an
	 * event. If cycle counter is supported and there is a gap between
	 * regular and cycle counter, the last logical counter is mapped to
	 * cycle counter. Otherwise, logical and physical have 1-to-1 mapping.
	 */
	DECLARE_BITMAP(used_ctrs, ARM_CSPMU_MAX_HW_CNTRS);
};

/* Contains ops to query vendor/implementer specific attribute. */
struct arm_cspmu_impl_ops {
	/* Get event attributes */
	struct attribute **(*get_event_attrs)(const struct arm_cspmu *cspmu);
	/* Get format attributes */
	struct attribute **(*get_format_attrs)(const struct arm_cspmu *cspmu);
	/* Get string identifier */
	const char *(*get_identifier)(const struct arm_cspmu *cspmu);
	/* Get PMU name to register to core perf */
	const char *(*get_name)(const struct arm_cspmu *cspmu);
	/* Check if the event corresponds to cycle count event */
	bool (*is_cycle_counter_event)(const struct perf_event *event);
	/* Decode event type/id from configs */
	u32 (*event_type)(const struct perf_event *event);
	/* Decode filter value from configs */
	u32 (*event_filter)(const struct perf_event *event);
	/* Set event filter */
	void (*set_ev_filter)(struct arm_cspmu *cspmu,
			      struct hw_perf_event *hwc, u32 filter);
	/* Implementation specific event validation */
	int (*validate_event)(struct arm_cspmu *cspmu,
			      struct perf_event *event);
	/* Hide/show unsupported events */
	umode_t (*event_attr_is_visible)(struct kobject *kobj,
					 struct attribute *attr, int unused);
};

/* Vendor/implementer registration parameter. */
struct arm_cspmu_impl_match {
	/* Backend module. */
	struct module *module;
	const char *module_name;
	/* PMIIDR value/mask. */
	u32 pmiidr_val;
	u32 pmiidr_mask;
	/* Callback to vendor backend to init arm_cspmu_impl::ops. */
	int (*impl_init_ops)(struct arm_cspmu *cspmu);
};

/* Vendor/implementer descriptor. */
struct arm_cspmu_impl {
	u32 pmiidr;
	struct module *module;
	struct arm_cspmu_impl_match *match;
	struct arm_cspmu_impl_ops ops;
	void *ctx;
};

/* Coresight PMU descriptor. */
struct arm_cspmu {
	struct pmu pmu;
	struct device *dev;
	const char *name;
	const char *identifier;
	void __iomem *base0;
	void __iomem *base1;
	cpumask_t associated_cpus;
	cpumask_t active_cpu;
	struct hlist_node cpuhp_node;
	int irq;

	bool has_atomic_dword;
	u32 pmcfgr;
	u32 num_logical_ctrs;
	u32 num_set_clr_reg;
	int cycle_counter_logical_idx;

	struct arm_cspmu_hw_events hw_events;
	const struct attribute_group *attr_groups[5];

	struct arm_cspmu_impl impl;
};

/* Default function to show event attribute in sysfs. */
ssize_t arm_cspmu_sysfs_event_show(struct device *dev,
				   struct device_attribute *attr,
				   char *buf);

/* Register vendor backend. */
int arm_cspmu_impl_register(const struct arm_cspmu_impl_match *impl_match);

/* Unregister vendor backend. */
void arm_cspmu_impl_unregister(const struct arm_cspmu_impl_match *impl_match);

#endif /* __ARM_CSPMU_H__ */