1/* SPDX-License-Identifier: GPL-2.0
2 *
3 * ARM CoreSight Architecture PMU driver.
4 * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 *
6 */
7
8#ifndef __ARM_CSPMU_H__
9#define __ARM_CSPMU_H__
10
11#include <linux/bitfield.h>
12#include <linux/cpumask.h>
13#include <linux/device.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/perf_event.h>
17#include <linux/platform_device.h>
18#include <linux/types.h>
19
20#define to_arm_cspmu(p) (container_of(p, struct arm_cspmu, pmu))
21
22#define ARM_CSPMU_EXT_ATTR(_name, _func, _config) \
23 (&((struct dev_ext_attribute[]){ \
24 { \
25 .attr = __ATTR(_name, 0444, _func, NULL), \
26 .var = (void *)_config \
27 } \
28 })[0].attr.attr)
29
30#define ARM_CSPMU_FORMAT_ATTR(_name, _config) \
31 ARM_CSPMU_EXT_ATTR(_name, arm_cspmu_sysfs_format_show, (char *)_config)
32
33#define ARM_CSPMU_EVENT_ATTR(_name, _config) \
34 PMU_EVENT_ATTR_ID(_name, arm_cspmu_sysfs_event_show, _config)
35
36
37/* Default event id mask */
38#define ARM_CSPMU_EVENT_MASK GENMASK_ULL(63, 0)
39
40/* Default filter value mask */
41#define ARM_CSPMU_FILTER_MASK GENMASK_ULL(63, 0)
42
43/* Default event format */
44#define ARM_CSPMU_FORMAT_EVENT_ATTR \
45 ARM_CSPMU_FORMAT_ATTR(event, "config:0-32")
46
47/* Default filter format */
48#define ARM_CSPMU_FORMAT_FILTER_ATTR \
49 ARM_CSPMU_FORMAT_ATTR(filter, "config1:0-31")
50
51/*
52 * This is the default event number for cycle count, if supported, since the
53 * ARM Coresight PMU specification does not define a standard event code
54 * for cycle count.
55 */
56#define ARM_CSPMU_EVT_CYCLES_DEFAULT (0x1ULL << 32)
57
58/*
59 * The ARM Coresight PMU supports up to 256 event counters.
60 * If the counters are larger-than 32-bits, then the PMU includes at
61 * most 128 counters.
62 */
63#define ARM_CSPMU_MAX_HW_CNTRS 256
64
65/* The cycle counter, if implemented, is located at counter[31]. */
66#define ARM_CSPMU_CYCLE_CNTR_IDX 31
67
68/* PMIIDR register field */
69#define ARM_CSPMU_PMIIDR_IMPLEMENTER GENMASK(11, 0)
70#define ARM_CSPMU_PMIIDR_PRODUCTID GENMASK(31, 20)
71
72/* JEDEC-assigned JEP106 identification code */
73#define ARM_CSPMU_IMPL_ID_NVIDIA 0x36B
74#define ARM_CSPMU_IMPL_ID_AMPERE 0xA16
75
76struct arm_cspmu;
77
78/* This tracks the events assigned to each counter in the PMU. */
79struct arm_cspmu_hw_events {
80 /* The events that are active on the PMU for a given logical index. */
81 struct perf_event **events;
82
83 /*
84 * Each bit indicates a logical counter is being used (or not) for an
85 * event. If cycle counter is supported and there is a gap between
86 * regular and cycle counter, the last logical counter is mapped to
87 * cycle counter. Otherwise, logical and physical have 1-to-1 mapping.
88 */
89 DECLARE_BITMAP(used_ctrs, ARM_CSPMU_MAX_HW_CNTRS);
90};
91
92/* Contains ops to query vendor/implementer specific attribute. */
93struct arm_cspmu_impl_ops {
94 /* Get event attributes */
95 struct attribute **(*get_event_attrs)(const struct arm_cspmu *cspmu);
96 /* Get format attributes */
97 struct attribute **(*get_format_attrs)(const struct arm_cspmu *cspmu);
98 /* Get string identifier */
99 const char *(*get_identifier)(const struct arm_cspmu *cspmu);
100 /* Get PMU name to register to core perf */
101 const char *(*get_name)(const struct arm_cspmu *cspmu);
102 /* Check if the event corresponds to cycle count event */
103 bool (*is_cycle_counter_event)(const struct perf_event *event);
104 /* Decode event type/id from configs */
105 u32 (*event_type)(const struct perf_event *event);
106 /* Decode filter value from configs */
107 u32 (*event_filter)(const struct perf_event *event);
108 /* Set event filter */
109 void (*set_ev_filter)(struct arm_cspmu *cspmu,
110 struct hw_perf_event *hwc, u32 filter);
111 /* Implementation specific event validation */
112 int (*validate_event)(struct arm_cspmu *cspmu,
113 struct perf_event *event);
114 /* Hide/show unsupported events */
115 umode_t (*event_attr_is_visible)(struct kobject *kobj,
116 struct attribute *attr, int unused);
117};
118
119/* Vendor/implementer registration parameter. */
120struct arm_cspmu_impl_match {
121 /* Backend module. */
122 struct module *module;
123 const char *module_name;
124 /* PMIIDR value/mask. */
125 u32 pmiidr_val;
126 u32 pmiidr_mask;
127 /* Callback to vendor backend to init arm_cspmu_impl::ops. */
128 int (*impl_init_ops)(struct arm_cspmu *cspmu);
129};
130
131/* Vendor/implementer descriptor. */
132struct arm_cspmu_impl {
133 u32 pmiidr;
134 struct module *module;
135 struct arm_cspmu_impl_match *match;
136 struct arm_cspmu_impl_ops ops;
137 void *ctx;
138};
139
140/* Coresight PMU descriptor. */
141struct arm_cspmu {
142 struct pmu pmu;
143 struct device *dev;
144 const char *name;
145 const char *identifier;
146 void __iomem *base0;
147 void __iomem *base1;
148 cpumask_t associated_cpus;
149 cpumask_t active_cpu;
150 struct hlist_node cpuhp_node;
151 int irq;
152
153 bool has_atomic_dword;
154 u32 pmcfgr;
155 u32 num_logical_ctrs;
156 u32 num_set_clr_reg;
157 int cycle_counter_logical_idx;
158
159 struct arm_cspmu_hw_events hw_events;
160 const struct attribute_group *attr_groups[5];
161
162 struct arm_cspmu_impl impl;
163};
164
165/* Default function to show event attribute in sysfs. */
166ssize_t arm_cspmu_sysfs_event_show(struct device *dev,
167 struct device_attribute *attr,
168 char *buf);
169
170/* Default function to show format attribute in sysfs. */
171ssize_t arm_cspmu_sysfs_format_show(struct device *dev,
172 struct device_attribute *attr,
173 char *buf);
174
175/* Register vendor backend. */
176int arm_cspmu_impl_register(const struct arm_cspmu_impl_match *impl_match);
177
178/* Unregister vendor backend. */
179void arm_cspmu_impl_unregister(const struct arm_cspmu_impl_match *impl_match);
180
181#endif /* __ARM_CSPMU_H__ */
182

source code of linux/drivers/perf/arm_cspmu/arm_cspmu.h