1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Perf support for the Statistical Profiling Extension, introduced as
4*4882a593Smuzhiyun * part of ARMv8.2.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2016 ARM Limited
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Author: Will Deacon <will.deacon@arm.com>
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define PMUNAME "arm_spe"
12*4882a593Smuzhiyun #define DRVNAME PMUNAME "_pmu"
13*4882a593Smuzhiyun #define pr_fmt(fmt) DRVNAME ": " fmt
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/bitops.h>
16*4882a593Smuzhiyun #include <linux/bug.h>
17*4882a593Smuzhiyun #include <linux/capability.h>
18*4882a593Smuzhiyun #include <linux/cpuhotplug.h>
19*4882a593Smuzhiyun #include <linux/cpumask.h>
20*4882a593Smuzhiyun #include <linux/device.h>
21*4882a593Smuzhiyun #include <linux/errno.h>
22*4882a593Smuzhiyun #include <linux/interrupt.h>
23*4882a593Smuzhiyun #include <linux/irq.h>
24*4882a593Smuzhiyun #include <linux/kernel.h>
25*4882a593Smuzhiyun #include <linux/list.h>
26*4882a593Smuzhiyun #include <linux/module.h>
27*4882a593Smuzhiyun #include <linux/of_address.h>
28*4882a593Smuzhiyun #include <linux/of_device.h>
29*4882a593Smuzhiyun #include <linux/perf_event.h>
30*4882a593Smuzhiyun #include <linux/perf/arm_pmu.h>
31*4882a593Smuzhiyun #include <linux/platform_device.h>
32*4882a593Smuzhiyun #include <linux/printk.h>
33*4882a593Smuzhiyun #include <linux/slab.h>
34*4882a593Smuzhiyun #include <linux/smp.h>
35*4882a593Smuzhiyun #include <linux/vmalloc.h>
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #include <asm/barrier.h>
38*4882a593Smuzhiyun #include <asm/cpufeature.h>
39*4882a593Smuzhiyun #include <asm/mmu.h>
40*4882a593Smuzhiyun #include <asm/sysreg.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun * Cache if the event is allowed to trace Context information.
44*4882a593Smuzhiyun * This allows us to perform the check, i.e, perfmon_capable(),
45*4882a593Smuzhiyun * in the context of the event owner, once, during the event_init().
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun #define SPE_PMU_HW_FLAGS_CX BIT(0)
48*4882a593Smuzhiyun
set_spe_event_has_cx(struct perf_event * event)49*4882a593Smuzhiyun static void set_spe_event_has_cx(struct perf_event *event)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable())
52*4882a593Smuzhiyun event->hw.flags |= SPE_PMU_HW_FLAGS_CX;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
get_spe_event_has_cx(struct perf_event * event)55*4882a593Smuzhiyun static bool get_spe_event_has_cx(struct perf_event *event)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun return !!(event->hw.flags & SPE_PMU_HW_FLAGS_CX);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #define ARM_SPE_BUF_PAD_BYTE 0
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun struct arm_spe_pmu_buf {
63*4882a593Smuzhiyun int nr_pages;
64*4882a593Smuzhiyun bool snapshot;
65*4882a593Smuzhiyun void *base;
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun struct arm_spe_pmu {
69*4882a593Smuzhiyun struct pmu pmu;
70*4882a593Smuzhiyun struct platform_device *pdev;
71*4882a593Smuzhiyun cpumask_t supported_cpus;
72*4882a593Smuzhiyun struct hlist_node hotplug_node;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun int irq; /* PPI */
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun u16 min_period;
77*4882a593Smuzhiyun u16 counter_sz;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #define SPE_PMU_FEAT_FILT_EVT (1UL << 0)
80*4882a593Smuzhiyun #define SPE_PMU_FEAT_FILT_TYP (1UL << 1)
81*4882a593Smuzhiyun #define SPE_PMU_FEAT_FILT_LAT (1UL << 2)
82*4882a593Smuzhiyun #define SPE_PMU_FEAT_ARCH_INST (1UL << 3)
83*4882a593Smuzhiyun #define SPE_PMU_FEAT_LDS (1UL << 4)
84*4882a593Smuzhiyun #define SPE_PMU_FEAT_ERND (1UL << 5)
85*4882a593Smuzhiyun #define SPE_PMU_FEAT_DEV_PROBED (1UL << 63)
86*4882a593Smuzhiyun u64 features;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun u16 max_record_sz;
89*4882a593Smuzhiyun u16 align;
90*4882a593Smuzhiyun struct perf_output_handle __percpu *handle;
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun #define to_spe_pmu(p) (container_of(p, struct arm_spe_pmu, pmu))
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* Convert a free-running index from perf into an SPE buffer offset */
96*4882a593Smuzhiyun #define PERF_IDX2OFF(idx, buf) ((idx) % ((buf)->nr_pages << PAGE_SHIFT))
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* Keep track of our dynamic hotplug state */
99*4882a593Smuzhiyun static enum cpuhp_state arm_spe_pmu_online;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun enum arm_spe_pmu_buf_fault_action {
102*4882a593Smuzhiyun SPE_PMU_BUF_FAULT_ACT_SPURIOUS,
103*4882a593Smuzhiyun SPE_PMU_BUF_FAULT_ACT_FATAL,
104*4882a593Smuzhiyun SPE_PMU_BUF_FAULT_ACT_OK,
105*4882a593Smuzhiyun };
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* This sysfs gunk was really good fun to write. */
108*4882a593Smuzhiyun enum arm_spe_pmu_capabilities {
109*4882a593Smuzhiyun SPE_PMU_CAP_ARCH_INST = 0,
110*4882a593Smuzhiyun SPE_PMU_CAP_ERND,
111*4882a593Smuzhiyun SPE_PMU_CAP_FEAT_MAX,
112*4882a593Smuzhiyun SPE_PMU_CAP_CNT_SZ = SPE_PMU_CAP_FEAT_MAX,
113*4882a593Smuzhiyun SPE_PMU_CAP_MIN_IVAL,
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun static int arm_spe_pmu_feat_caps[SPE_PMU_CAP_FEAT_MAX] = {
117*4882a593Smuzhiyun [SPE_PMU_CAP_ARCH_INST] = SPE_PMU_FEAT_ARCH_INST,
118*4882a593Smuzhiyun [SPE_PMU_CAP_ERND] = SPE_PMU_FEAT_ERND,
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun
arm_spe_pmu_cap_get(struct arm_spe_pmu * spe_pmu,int cap)121*4882a593Smuzhiyun static u32 arm_spe_pmu_cap_get(struct arm_spe_pmu *spe_pmu, int cap)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun if (cap < SPE_PMU_CAP_FEAT_MAX)
124*4882a593Smuzhiyun return !!(spe_pmu->features & arm_spe_pmu_feat_caps[cap]);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun switch (cap) {
127*4882a593Smuzhiyun case SPE_PMU_CAP_CNT_SZ:
128*4882a593Smuzhiyun return spe_pmu->counter_sz;
129*4882a593Smuzhiyun case SPE_PMU_CAP_MIN_IVAL:
130*4882a593Smuzhiyun return spe_pmu->min_period;
131*4882a593Smuzhiyun default:
132*4882a593Smuzhiyun WARN(1, "unknown cap %d\n", cap);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun return 0;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
arm_spe_pmu_cap_show(struct device * dev,struct device_attribute * attr,char * buf)138*4882a593Smuzhiyun static ssize_t arm_spe_pmu_cap_show(struct device *dev,
139*4882a593Smuzhiyun struct device_attribute *attr,
140*4882a593Smuzhiyun char *buf)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
143*4882a593Smuzhiyun struct dev_ext_attribute *ea =
144*4882a593Smuzhiyun container_of(attr, struct dev_ext_attribute, attr);
145*4882a593Smuzhiyun int cap = (long)ea->var;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "%u\n",
148*4882a593Smuzhiyun arm_spe_pmu_cap_get(spe_pmu, cap));
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun #define SPE_EXT_ATTR_ENTRY(_name, _func, _var) \
152*4882a593Smuzhiyun &((struct dev_ext_attribute[]) { \
153*4882a593Smuzhiyun { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_var } \
154*4882a593Smuzhiyun })[0].attr.attr
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun #define SPE_CAP_EXT_ATTR_ENTRY(_name, _var) \
157*4882a593Smuzhiyun SPE_EXT_ATTR_ENTRY(_name, arm_spe_pmu_cap_show, _var)
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun static struct attribute *arm_spe_pmu_cap_attr[] = {
160*4882a593Smuzhiyun SPE_CAP_EXT_ATTR_ENTRY(arch_inst, SPE_PMU_CAP_ARCH_INST),
161*4882a593Smuzhiyun SPE_CAP_EXT_ATTR_ENTRY(ernd, SPE_PMU_CAP_ERND),
162*4882a593Smuzhiyun SPE_CAP_EXT_ATTR_ENTRY(count_size, SPE_PMU_CAP_CNT_SZ),
163*4882a593Smuzhiyun SPE_CAP_EXT_ATTR_ENTRY(min_interval, SPE_PMU_CAP_MIN_IVAL),
164*4882a593Smuzhiyun NULL,
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun static struct attribute_group arm_spe_pmu_cap_group = {
168*4882a593Smuzhiyun .name = "caps",
169*4882a593Smuzhiyun .attrs = arm_spe_pmu_cap_attr,
170*4882a593Smuzhiyun };
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun /* User ABI */
173*4882a593Smuzhiyun #define ATTR_CFG_FLD_ts_enable_CFG config /* PMSCR_EL1.TS */
174*4882a593Smuzhiyun #define ATTR_CFG_FLD_ts_enable_LO 0
175*4882a593Smuzhiyun #define ATTR_CFG_FLD_ts_enable_HI 0
176*4882a593Smuzhiyun #define ATTR_CFG_FLD_pa_enable_CFG config /* PMSCR_EL1.PA */
177*4882a593Smuzhiyun #define ATTR_CFG_FLD_pa_enable_LO 1
178*4882a593Smuzhiyun #define ATTR_CFG_FLD_pa_enable_HI 1
179*4882a593Smuzhiyun #define ATTR_CFG_FLD_pct_enable_CFG config /* PMSCR_EL1.PCT */
180*4882a593Smuzhiyun #define ATTR_CFG_FLD_pct_enable_LO 2
181*4882a593Smuzhiyun #define ATTR_CFG_FLD_pct_enable_HI 2
182*4882a593Smuzhiyun #define ATTR_CFG_FLD_jitter_CFG config /* PMSIRR_EL1.RND */
183*4882a593Smuzhiyun #define ATTR_CFG_FLD_jitter_LO 16
184*4882a593Smuzhiyun #define ATTR_CFG_FLD_jitter_HI 16
185*4882a593Smuzhiyun #define ATTR_CFG_FLD_branch_filter_CFG config /* PMSFCR_EL1.B */
186*4882a593Smuzhiyun #define ATTR_CFG_FLD_branch_filter_LO 32
187*4882a593Smuzhiyun #define ATTR_CFG_FLD_branch_filter_HI 32
188*4882a593Smuzhiyun #define ATTR_CFG_FLD_load_filter_CFG config /* PMSFCR_EL1.LD */
189*4882a593Smuzhiyun #define ATTR_CFG_FLD_load_filter_LO 33
190*4882a593Smuzhiyun #define ATTR_CFG_FLD_load_filter_HI 33
191*4882a593Smuzhiyun #define ATTR_CFG_FLD_store_filter_CFG config /* PMSFCR_EL1.ST */
192*4882a593Smuzhiyun #define ATTR_CFG_FLD_store_filter_LO 34
193*4882a593Smuzhiyun #define ATTR_CFG_FLD_store_filter_HI 34
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun #define ATTR_CFG_FLD_event_filter_CFG config1 /* PMSEVFR_EL1 */
196*4882a593Smuzhiyun #define ATTR_CFG_FLD_event_filter_LO 0
197*4882a593Smuzhiyun #define ATTR_CFG_FLD_event_filter_HI 63
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #define ATTR_CFG_FLD_min_latency_CFG config2 /* PMSLATFR_EL1.MINLAT */
200*4882a593Smuzhiyun #define ATTR_CFG_FLD_min_latency_LO 0
201*4882a593Smuzhiyun #define ATTR_CFG_FLD_min_latency_HI 11
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /* Why does everything I do descend into this? */
204*4882a593Smuzhiyun #define __GEN_PMU_FORMAT_ATTR(cfg, lo, hi) \
205*4882a593Smuzhiyun (lo) == (hi) ? #cfg ":" #lo "\n" : #cfg ":" #lo "-" #hi
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun #define _GEN_PMU_FORMAT_ATTR(cfg, lo, hi) \
208*4882a593Smuzhiyun __GEN_PMU_FORMAT_ATTR(cfg, lo, hi)
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun #define GEN_PMU_FORMAT_ATTR(name) \
211*4882a593Smuzhiyun PMU_FORMAT_ATTR(name, \
212*4882a593Smuzhiyun _GEN_PMU_FORMAT_ATTR(ATTR_CFG_FLD_##name##_CFG, \
213*4882a593Smuzhiyun ATTR_CFG_FLD_##name##_LO, \
214*4882a593Smuzhiyun ATTR_CFG_FLD_##name##_HI))
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun #define _ATTR_CFG_GET_FLD(attr, cfg, lo, hi) \
217*4882a593Smuzhiyun ((((attr)->cfg) >> lo) & GENMASK(hi - lo, 0))
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun #define ATTR_CFG_GET_FLD(attr, name) \
220*4882a593Smuzhiyun _ATTR_CFG_GET_FLD(attr, \
221*4882a593Smuzhiyun ATTR_CFG_FLD_##name##_CFG, \
222*4882a593Smuzhiyun ATTR_CFG_FLD_##name##_LO, \
223*4882a593Smuzhiyun ATTR_CFG_FLD_##name##_HI)
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(ts_enable);
226*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(pa_enable);
227*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(pct_enable);
228*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(jitter);
229*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(branch_filter);
230*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(load_filter);
231*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(store_filter);
232*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(event_filter);
233*4882a593Smuzhiyun GEN_PMU_FORMAT_ATTR(min_latency);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun static struct attribute *arm_spe_pmu_formats_attr[] = {
236*4882a593Smuzhiyun &format_attr_ts_enable.attr,
237*4882a593Smuzhiyun &format_attr_pa_enable.attr,
238*4882a593Smuzhiyun &format_attr_pct_enable.attr,
239*4882a593Smuzhiyun &format_attr_jitter.attr,
240*4882a593Smuzhiyun &format_attr_branch_filter.attr,
241*4882a593Smuzhiyun &format_attr_load_filter.attr,
242*4882a593Smuzhiyun &format_attr_store_filter.attr,
243*4882a593Smuzhiyun &format_attr_event_filter.attr,
244*4882a593Smuzhiyun &format_attr_min_latency.attr,
245*4882a593Smuzhiyun NULL,
246*4882a593Smuzhiyun };
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun static struct attribute_group arm_spe_pmu_format_group = {
249*4882a593Smuzhiyun .name = "format",
250*4882a593Smuzhiyun .attrs = arm_spe_pmu_formats_attr,
251*4882a593Smuzhiyun };
252*4882a593Smuzhiyun
arm_spe_pmu_get_attr_cpumask(struct device * dev,struct device_attribute * attr,char * buf)253*4882a593Smuzhiyun static ssize_t arm_spe_pmu_get_attr_cpumask(struct device *dev,
254*4882a593Smuzhiyun struct device_attribute *attr,
255*4882a593Smuzhiyun char *buf)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun return cpumap_print_to_pagebuf(true, buf, &spe_pmu->supported_cpus);
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun static DEVICE_ATTR(cpumask, S_IRUGO, arm_spe_pmu_get_attr_cpumask, NULL);
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun static struct attribute *arm_spe_pmu_attrs[] = {
264*4882a593Smuzhiyun &dev_attr_cpumask.attr,
265*4882a593Smuzhiyun NULL,
266*4882a593Smuzhiyun };
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun static struct attribute_group arm_spe_pmu_group = {
269*4882a593Smuzhiyun .attrs = arm_spe_pmu_attrs,
270*4882a593Smuzhiyun };
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun static const struct attribute_group *arm_spe_pmu_attr_groups[] = {
273*4882a593Smuzhiyun &arm_spe_pmu_group,
274*4882a593Smuzhiyun &arm_spe_pmu_cap_group,
275*4882a593Smuzhiyun &arm_spe_pmu_format_group,
276*4882a593Smuzhiyun NULL,
277*4882a593Smuzhiyun };
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* Convert between user ABI and register values */
arm_spe_event_to_pmscr(struct perf_event * event)280*4882a593Smuzhiyun static u64 arm_spe_event_to_pmscr(struct perf_event *event)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun struct perf_event_attr *attr = &event->attr;
283*4882a593Smuzhiyun u64 reg = 0;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun reg |= ATTR_CFG_GET_FLD(attr, ts_enable) << SYS_PMSCR_EL1_TS_SHIFT;
286*4882a593Smuzhiyun reg |= ATTR_CFG_GET_FLD(attr, pa_enable) << SYS_PMSCR_EL1_PA_SHIFT;
287*4882a593Smuzhiyun reg |= ATTR_CFG_GET_FLD(attr, pct_enable) << SYS_PMSCR_EL1_PCT_SHIFT;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun if (!attr->exclude_user)
290*4882a593Smuzhiyun reg |= BIT(SYS_PMSCR_EL1_E0SPE_SHIFT);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun if (!attr->exclude_kernel)
293*4882a593Smuzhiyun reg |= BIT(SYS_PMSCR_EL1_E1SPE_SHIFT);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun if (get_spe_event_has_cx(event))
296*4882a593Smuzhiyun reg |= BIT(SYS_PMSCR_EL1_CX_SHIFT);
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun return reg;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
arm_spe_event_sanitise_period(struct perf_event * event)301*4882a593Smuzhiyun static void arm_spe_event_sanitise_period(struct perf_event *event)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(event->pmu);
304*4882a593Smuzhiyun u64 period = event->hw.sample_period;
305*4882a593Smuzhiyun u64 max_period = SYS_PMSIRR_EL1_INTERVAL_MASK
306*4882a593Smuzhiyun << SYS_PMSIRR_EL1_INTERVAL_SHIFT;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun if (period < spe_pmu->min_period)
309*4882a593Smuzhiyun period = spe_pmu->min_period;
310*4882a593Smuzhiyun else if (period > max_period)
311*4882a593Smuzhiyun period = max_period;
312*4882a593Smuzhiyun else
313*4882a593Smuzhiyun period &= max_period;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun event->hw.sample_period = period;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
arm_spe_event_to_pmsirr(struct perf_event * event)318*4882a593Smuzhiyun static u64 arm_spe_event_to_pmsirr(struct perf_event *event)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun struct perf_event_attr *attr = &event->attr;
321*4882a593Smuzhiyun u64 reg = 0;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun arm_spe_event_sanitise_period(event);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun reg |= ATTR_CFG_GET_FLD(attr, jitter) << SYS_PMSIRR_EL1_RND_SHIFT;
326*4882a593Smuzhiyun reg |= event->hw.sample_period;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun return reg;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
arm_spe_event_to_pmsfcr(struct perf_event * event)331*4882a593Smuzhiyun static u64 arm_spe_event_to_pmsfcr(struct perf_event *event)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun struct perf_event_attr *attr = &event->attr;
334*4882a593Smuzhiyun u64 reg = 0;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun reg |= ATTR_CFG_GET_FLD(attr, load_filter) << SYS_PMSFCR_EL1_LD_SHIFT;
337*4882a593Smuzhiyun reg |= ATTR_CFG_GET_FLD(attr, store_filter) << SYS_PMSFCR_EL1_ST_SHIFT;
338*4882a593Smuzhiyun reg |= ATTR_CFG_GET_FLD(attr, branch_filter) << SYS_PMSFCR_EL1_B_SHIFT;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun if (reg)
341*4882a593Smuzhiyun reg |= BIT(SYS_PMSFCR_EL1_FT_SHIFT);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun if (ATTR_CFG_GET_FLD(attr, event_filter))
344*4882a593Smuzhiyun reg |= BIT(SYS_PMSFCR_EL1_FE_SHIFT);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (ATTR_CFG_GET_FLD(attr, min_latency))
347*4882a593Smuzhiyun reg |= BIT(SYS_PMSFCR_EL1_FL_SHIFT);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun return reg;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
arm_spe_event_to_pmsevfr(struct perf_event * event)352*4882a593Smuzhiyun static u64 arm_spe_event_to_pmsevfr(struct perf_event *event)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun struct perf_event_attr *attr = &event->attr;
355*4882a593Smuzhiyun return ATTR_CFG_GET_FLD(attr, event_filter);
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
arm_spe_event_to_pmslatfr(struct perf_event * event)358*4882a593Smuzhiyun static u64 arm_spe_event_to_pmslatfr(struct perf_event *event)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun struct perf_event_attr *attr = &event->attr;
361*4882a593Smuzhiyun return ATTR_CFG_GET_FLD(attr, min_latency)
362*4882a593Smuzhiyun << SYS_PMSLATFR_EL1_MINLAT_SHIFT;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
arm_spe_pmu_pad_buf(struct perf_output_handle * handle,int len)365*4882a593Smuzhiyun static void arm_spe_pmu_pad_buf(struct perf_output_handle *handle, int len)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf = perf_get_aux(handle);
368*4882a593Smuzhiyun u64 head = PERF_IDX2OFF(handle->head, buf);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun memset(buf->base + head, ARM_SPE_BUF_PAD_BYTE, len);
371*4882a593Smuzhiyun if (!buf->snapshot)
372*4882a593Smuzhiyun perf_aux_output_skip(handle, len);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
arm_spe_pmu_next_snapshot_off(struct perf_output_handle * handle)375*4882a593Smuzhiyun static u64 arm_spe_pmu_next_snapshot_off(struct perf_output_handle *handle)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf = perf_get_aux(handle);
378*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(handle->event->pmu);
379*4882a593Smuzhiyun u64 head = PERF_IDX2OFF(handle->head, buf);
380*4882a593Smuzhiyun u64 limit = buf->nr_pages * PAGE_SIZE;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /*
383*4882a593Smuzhiyun * The trace format isn't parseable in reverse, so clamp
384*4882a593Smuzhiyun * the limit to half of the buffer size in snapshot mode
385*4882a593Smuzhiyun * so that the worst case is half a buffer of records, as
386*4882a593Smuzhiyun * opposed to a single record.
387*4882a593Smuzhiyun */
388*4882a593Smuzhiyun if (head < limit >> 1)
389*4882a593Smuzhiyun limit >>= 1;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /*
392*4882a593Smuzhiyun * If we're within max_record_sz of the limit, we must
393*4882a593Smuzhiyun * pad, move the head index and recompute the limit.
394*4882a593Smuzhiyun */
395*4882a593Smuzhiyun if (limit - head < spe_pmu->max_record_sz) {
396*4882a593Smuzhiyun arm_spe_pmu_pad_buf(handle, limit - head);
397*4882a593Smuzhiyun handle->head = PERF_IDX2OFF(limit, buf);
398*4882a593Smuzhiyun limit = ((buf->nr_pages * PAGE_SIZE) >> 1) + handle->head;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun return limit;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
__arm_spe_pmu_next_off(struct perf_output_handle * handle)404*4882a593Smuzhiyun static u64 __arm_spe_pmu_next_off(struct perf_output_handle *handle)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(handle->event->pmu);
407*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf = perf_get_aux(handle);
408*4882a593Smuzhiyun const u64 bufsize = buf->nr_pages * PAGE_SIZE;
409*4882a593Smuzhiyun u64 limit = bufsize;
410*4882a593Smuzhiyun u64 head, tail, wakeup;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /*
413*4882a593Smuzhiyun * The head can be misaligned for two reasons:
414*4882a593Smuzhiyun *
415*4882a593Smuzhiyun * 1. The hardware left PMBPTR pointing to the first byte after
416*4882a593Smuzhiyun * a record when generating a buffer management event.
417*4882a593Smuzhiyun *
418*4882a593Smuzhiyun * 2. We used perf_aux_output_skip to consume handle->size bytes
419*4882a593Smuzhiyun * and CIRC_SPACE was used to compute the size, which always
420*4882a593Smuzhiyun * leaves one entry free.
421*4882a593Smuzhiyun *
422*4882a593Smuzhiyun * Deal with this by padding to the next alignment boundary and
423*4882a593Smuzhiyun * moving the head index. If we run out of buffer space, we'll
424*4882a593Smuzhiyun * reduce handle->size to zero and end up reporting truncation.
425*4882a593Smuzhiyun */
426*4882a593Smuzhiyun head = PERF_IDX2OFF(handle->head, buf);
427*4882a593Smuzhiyun if (!IS_ALIGNED(head, spe_pmu->align)) {
428*4882a593Smuzhiyun unsigned long delta = roundup(head, spe_pmu->align) - head;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun delta = min(delta, handle->size);
431*4882a593Smuzhiyun arm_spe_pmu_pad_buf(handle, delta);
432*4882a593Smuzhiyun head = PERF_IDX2OFF(handle->head, buf);
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun /* If we've run out of free space, then nothing more to do */
436*4882a593Smuzhiyun if (!handle->size)
437*4882a593Smuzhiyun goto no_space;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /* Compute the tail and wakeup indices now that we've aligned head */
440*4882a593Smuzhiyun tail = PERF_IDX2OFF(handle->head + handle->size, buf);
441*4882a593Smuzhiyun wakeup = PERF_IDX2OFF(handle->wakeup, buf);
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun /*
444*4882a593Smuzhiyun * Avoid clobbering unconsumed data. We know we have space, so
445*4882a593Smuzhiyun * if we see head == tail we know that the buffer is empty. If
446*4882a593Smuzhiyun * head > tail, then there's nothing to clobber prior to
447*4882a593Smuzhiyun * wrapping.
448*4882a593Smuzhiyun */
449*4882a593Smuzhiyun if (head < tail)
450*4882a593Smuzhiyun limit = round_down(tail, PAGE_SIZE);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun /*
453*4882a593Smuzhiyun * Wakeup may be arbitrarily far into the future. If it's not in
454*4882a593Smuzhiyun * the current generation, either we'll wrap before hitting it,
455*4882a593Smuzhiyun * or it's in the past and has been handled already.
456*4882a593Smuzhiyun *
457*4882a593Smuzhiyun * If there's a wakeup before we wrap, arrange to be woken up by
458*4882a593Smuzhiyun * the page boundary following it. Keep the tail boundary if
459*4882a593Smuzhiyun * that's lower.
460*4882a593Smuzhiyun */
461*4882a593Smuzhiyun if (handle->wakeup < (handle->head + handle->size) && head <= wakeup)
462*4882a593Smuzhiyun limit = min(limit, round_up(wakeup, PAGE_SIZE));
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun if (limit > head)
465*4882a593Smuzhiyun return limit;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun arm_spe_pmu_pad_buf(handle, handle->size);
468*4882a593Smuzhiyun no_space:
469*4882a593Smuzhiyun perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
470*4882a593Smuzhiyun perf_aux_output_end(handle, 0);
471*4882a593Smuzhiyun return 0;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
arm_spe_pmu_next_off(struct perf_output_handle * handle)474*4882a593Smuzhiyun static u64 arm_spe_pmu_next_off(struct perf_output_handle *handle)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf = perf_get_aux(handle);
477*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(handle->event->pmu);
478*4882a593Smuzhiyun u64 limit = __arm_spe_pmu_next_off(handle);
479*4882a593Smuzhiyun u64 head = PERF_IDX2OFF(handle->head, buf);
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun /*
482*4882a593Smuzhiyun * If the head has come too close to the end of the buffer,
483*4882a593Smuzhiyun * then pad to the end and recompute the limit.
484*4882a593Smuzhiyun */
485*4882a593Smuzhiyun if (limit && (limit - head < spe_pmu->max_record_sz)) {
486*4882a593Smuzhiyun arm_spe_pmu_pad_buf(handle, limit - head);
487*4882a593Smuzhiyun limit = __arm_spe_pmu_next_off(handle);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun return limit;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
arm_spe_perf_aux_output_begin(struct perf_output_handle * handle,struct perf_event * event)493*4882a593Smuzhiyun static void arm_spe_perf_aux_output_begin(struct perf_output_handle *handle,
494*4882a593Smuzhiyun struct perf_event *event)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun u64 base, limit;
497*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* Start a new aux session */
500*4882a593Smuzhiyun buf = perf_aux_output_begin(handle, event);
501*4882a593Smuzhiyun if (!buf) {
502*4882a593Smuzhiyun event->hw.state |= PERF_HES_STOPPED;
503*4882a593Smuzhiyun /*
504*4882a593Smuzhiyun * We still need to clear the limit pointer, since the
505*4882a593Smuzhiyun * profiler might only be disabled by virtue of a fault.
506*4882a593Smuzhiyun */
507*4882a593Smuzhiyun limit = 0;
508*4882a593Smuzhiyun goto out_write_limit;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun limit = buf->snapshot ? arm_spe_pmu_next_snapshot_off(handle)
512*4882a593Smuzhiyun : arm_spe_pmu_next_off(handle);
513*4882a593Smuzhiyun if (limit)
514*4882a593Smuzhiyun limit |= BIT(SYS_PMBLIMITR_EL1_E_SHIFT);
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun limit += (u64)buf->base;
517*4882a593Smuzhiyun base = (u64)buf->base + PERF_IDX2OFF(handle->head, buf);
518*4882a593Smuzhiyun write_sysreg_s(base, SYS_PMBPTR_EL1);
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun out_write_limit:
521*4882a593Smuzhiyun write_sysreg_s(limit, SYS_PMBLIMITR_EL1);
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
arm_spe_perf_aux_output_end(struct perf_output_handle * handle)524*4882a593Smuzhiyun static void arm_spe_perf_aux_output_end(struct perf_output_handle *handle)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf = perf_get_aux(handle);
527*4882a593Smuzhiyun u64 offset, size;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun offset = read_sysreg_s(SYS_PMBPTR_EL1) - (u64)buf->base;
530*4882a593Smuzhiyun size = offset - PERF_IDX2OFF(handle->head, buf);
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun if (buf->snapshot)
533*4882a593Smuzhiyun handle->head = offset;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun perf_aux_output_end(handle, size);
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
arm_spe_pmu_disable_and_drain_local(void)538*4882a593Smuzhiyun static void arm_spe_pmu_disable_and_drain_local(void)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun /* Disable profiling at EL0 and EL1 */
541*4882a593Smuzhiyun write_sysreg_s(0, SYS_PMSCR_EL1);
542*4882a593Smuzhiyun isb();
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun /* Drain any buffered data */
545*4882a593Smuzhiyun psb_csync();
546*4882a593Smuzhiyun dsb(nsh);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun /* Disable the profiling buffer */
549*4882a593Smuzhiyun write_sysreg_s(0, SYS_PMBLIMITR_EL1);
550*4882a593Smuzhiyun isb();
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun /* IRQ handling */
554*4882a593Smuzhiyun static enum arm_spe_pmu_buf_fault_action
arm_spe_pmu_buf_get_fault_act(struct perf_output_handle * handle)555*4882a593Smuzhiyun arm_spe_pmu_buf_get_fault_act(struct perf_output_handle *handle)
556*4882a593Smuzhiyun {
557*4882a593Smuzhiyun const char *err_str;
558*4882a593Smuzhiyun u64 pmbsr;
559*4882a593Smuzhiyun enum arm_spe_pmu_buf_fault_action ret;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun /*
562*4882a593Smuzhiyun * Ensure new profiling data is visible to the CPU and any external
563*4882a593Smuzhiyun * aborts have been resolved.
564*4882a593Smuzhiyun */
565*4882a593Smuzhiyun psb_csync();
566*4882a593Smuzhiyun dsb(nsh);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun /* Ensure hardware updates to PMBPTR_EL1 are visible */
569*4882a593Smuzhiyun isb();
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /* Service required? */
572*4882a593Smuzhiyun pmbsr = read_sysreg_s(SYS_PMBSR_EL1);
573*4882a593Smuzhiyun if (!(pmbsr & BIT(SYS_PMBSR_EL1_S_SHIFT)))
574*4882a593Smuzhiyun return SPE_PMU_BUF_FAULT_ACT_SPURIOUS;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun /*
577*4882a593Smuzhiyun * If we've lost data, disable profiling and also set the PARTIAL
578*4882a593Smuzhiyun * flag to indicate that the last record is corrupted.
579*4882a593Smuzhiyun */
580*4882a593Smuzhiyun if (pmbsr & BIT(SYS_PMBSR_EL1_DL_SHIFT))
581*4882a593Smuzhiyun perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED |
582*4882a593Smuzhiyun PERF_AUX_FLAG_PARTIAL);
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun /* Report collisions to userspace so that it can up the period */
585*4882a593Smuzhiyun if (pmbsr & BIT(SYS_PMBSR_EL1_COLL_SHIFT))
586*4882a593Smuzhiyun perf_aux_output_flag(handle, PERF_AUX_FLAG_COLLISION);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun /* We only expect buffer management events */
589*4882a593Smuzhiyun switch (pmbsr & (SYS_PMBSR_EL1_EC_MASK << SYS_PMBSR_EL1_EC_SHIFT)) {
590*4882a593Smuzhiyun case SYS_PMBSR_EL1_EC_BUF:
591*4882a593Smuzhiyun /* Handled below */
592*4882a593Smuzhiyun break;
593*4882a593Smuzhiyun case SYS_PMBSR_EL1_EC_FAULT_S1:
594*4882a593Smuzhiyun case SYS_PMBSR_EL1_EC_FAULT_S2:
595*4882a593Smuzhiyun err_str = "Unexpected buffer fault";
596*4882a593Smuzhiyun goto out_err;
597*4882a593Smuzhiyun default:
598*4882a593Smuzhiyun err_str = "Unknown error code";
599*4882a593Smuzhiyun goto out_err;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun /* Buffer management event */
603*4882a593Smuzhiyun switch (pmbsr &
604*4882a593Smuzhiyun (SYS_PMBSR_EL1_BUF_BSC_MASK << SYS_PMBSR_EL1_BUF_BSC_SHIFT)) {
605*4882a593Smuzhiyun case SYS_PMBSR_EL1_BUF_BSC_FULL:
606*4882a593Smuzhiyun ret = SPE_PMU_BUF_FAULT_ACT_OK;
607*4882a593Smuzhiyun goto out_stop;
608*4882a593Smuzhiyun default:
609*4882a593Smuzhiyun err_str = "Unknown buffer status code";
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun out_err:
613*4882a593Smuzhiyun pr_err_ratelimited("%s on CPU %d [PMBSR=0x%016llx, PMBPTR=0x%016llx, PMBLIMITR=0x%016llx]\n",
614*4882a593Smuzhiyun err_str, smp_processor_id(), pmbsr,
615*4882a593Smuzhiyun read_sysreg_s(SYS_PMBPTR_EL1),
616*4882a593Smuzhiyun read_sysreg_s(SYS_PMBLIMITR_EL1));
617*4882a593Smuzhiyun ret = SPE_PMU_BUF_FAULT_ACT_FATAL;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun out_stop:
620*4882a593Smuzhiyun arm_spe_perf_aux_output_end(handle);
621*4882a593Smuzhiyun return ret;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
arm_spe_pmu_irq_handler(int irq,void * dev)624*4882a593Smuzhiyun static irqreturn_t arm_spe_pmu_irq_handler(int irq, void *dev)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun struct perf_output_handle *handle = dev;
627*4882a593Smuzhiyun struct perf_event *event = handle->event;
628*4882a593Smuzhiyun enum arm_spe_pmu_buf_fault_action act;
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun if (!perf_get_aux(handle))
631*4882a593Smuzhiyun return IRQ_NONE;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun act = arm_spe_pmu_buf_get_fault_act(handle);
634*4882a593Smuzhiyun if (act == SPE_PMU_BUF_FAULT_ACT_SPURIOUS)
635*4882a593Smuzhiyun return IRQ_NONE;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun /*
638*4882a593Smuzhiyun * Ensure perf callbacks have completed, which may disable the
639*4882a593Smuzhiyun * profiling buffer in response to a TRUNCATION flag.
640*4882a593Smuzhiyun */
641*4882a593Smuzhiyun irq_work_run();
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun switch (act) {
644*4882a593Smuzhiyun case SPE_PMU_BUF_FAULT_ACT_FATAL:
645*4882a593Smuzhiyun /*
646*4882a593Smuzhiyun * If a fatal exception occurred then leaving the profiling
647*4882a593Smuzhiyun * buffer enabled is a recipe waiting to happen. Since
648*4882a593Smuzhiyun * fatal faults don't always imply truncation, make sure
649*4882a593Smuzhiyun * that the profiling buffer is disabled explicitly before
650*4882a593Smuzhiyun * clearing the syndrome register.
651*4882a593Smuzhiyun */
652*4882a593Smuzhiyun arm_spe_pmu_disable_and_drain_local();
653*4882a593Smuzhiyun break;
654*4882a593Smuzhiyun case SPE_PMU_BUF_FAULT_ACT_OK:
655*4882a593Smuzhiyun /*
656*4882a593Smuzhiyun * We handled the fault (the buffer was full), so resume
657*4882a593Smuzhiyun * profiling as long as we didn't detect truncation.
658*4882a593Smuzhiyun * PMBPTR might be misaligned, but we'll burn that bridge
659*4882a593Smuzhiyun * when we get to it.
660*4882a593Smuzhiyun */
661*4882a593Smuzhiyun if (!(handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)) {
662*4882a593Smuzhiyun arm_spe_perf_aux_output_begin(handle, event);
663*4882a593Smuzhiyun isb();
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun break;
666*4882a593Smuzhiyun case SPE_PMU_BUF_FAULT_ACT_SPURIOUS:
667*4882a593Smuzhiyun /* We've seen you before, but GCC has the memory of a sieve. */
668*4882a593Smuzhiyun break;
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun /* The buffer pointers are now sane, so resume profiling. */
672*4882a593Smuzhiyun write_sysreg_s(0, SYS_PMBSR_EL1);
673*4882a593Smuzhiyun return IRQ_HANDLED;
674*4882a593Smuzhiyun }
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun /* Perf callbacks */
arm_spe_pmu_event_init(struct perf_event * event)677*4882a593Smuzhiyun static int arm_spe_pmu_event_init(struct perf_event *event)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun u64 reg;
680*4882a593Smuzhiyun struct perf_event_attr *attr = &event->attr;
681*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(event->pmu);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun /* This is, of course, deeply driver-specific */
684*4882a593Smuzhiyun if (attr->type != event->pmu->type)
685*4882a593Smuzhiyun return -ENOENT;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun if (event->cpu >= 0 &&
688*4882a593Smuzhiyun !cpumask_test_cpu(event->cpu, &spe_pmu->supported_cpus))
689*4882a593Smuzhiyun return -ENOENT;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun if (arm_spe_event_to_pmsevfr(event) & SYS_PMSEVFR_EL1_RES0)
692*4882a593Smuzhiyun return -EOPNOTSUPP;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun if (attr->exclude_idle)
695*4882a593Smuzhiyun return -EOPNOTSUPP;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun /*
698*4882a593Smuzhiyun * Feedback-directed frequency throttling doesn't work when we
699*4882a593Smuzhiyun * have a buffer of samples. We'd need to manually count the
700*4882a593Smuzhiyun * samples in the buffer when it fills up and adjust the event
701*4882a593Smuzhiyun * count to reflect that. Instead, just force the user to specify
702*4882a593Smuzhiyun * a sample period.
703*4882a593Smuzhiyun */
704*4882a593Smuzhiyun if (attr->freq)
705*4882a593Smuzhiyun return -EINVAL;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun reg = arm_spe_event_to_pmsfcr(event);
708*4882a593Smuzhiyun if ((reg & BIT(SYS_PMSFCR_EL1_FE_SHIFT)) &&
709*4882a593Smuzhiyun !(spe_pmu->features & SPE_PMU_FEAT_FILT_EVT))
710*4882a593Smuzhiyun return -EOPNOTSUPP;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun if ((reg & BIT(SYS_PMSFCR_EL1_FT_SHIFT)) &&
713*4882a593Smuzhiyun !(spe_pmu->features & SPE_PMU_FEAT_FILT_TYP))
714*4882a593Smuzhiyun return -EOPNOTSUPP;
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun if ((reg & BIT(SYS_PMSFCR_EL1_FL_SHIFT)) &&
717*4882a593Smuzhiyun !(spe_pmu->features & SPE_PMU_FEAT_FILT_LAT))
718*4882a593Smuzhiyun return -EOPNOTSUPP;
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun set_spe_event_has_cx(event);
721*4882a593Smuzhiyun reg = arm_spe_event_to_pmscr(event);
722*4882a593Smuzhiyun if (!perfmon_capable() &&
723*4882a593Smuzhiyun (reg & (BIT(SYS_PMSCR_EL1_PA_SHIFT) |
724*4882a593Smuzhiyun BIT(SYS_PMSCR_EL1_PCT_SHIFT))))
725*4882a593Smuzhiyun return -EACCES;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun return 0;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun
arm_spe_pmu_start(struct perf_event * event,int flags)730*4882a593Smuzhiyun static void arm_spe_pmu_start(struct perf_event *event, int flags)
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun u64 reg;
733*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(event->pmu);
734*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
735*4882a593Smuzhiyun struct perf_output_handle *handle = this_cpu_ptr(spe_pmu->handle);
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun hwc->state = 0;
738*4882a593Smuzhiyun arm_spe_perf_aux_output_begin(handle, event);
739*4882a593Smuzhiyun if (hwc->state)
740*4882a593Smuzhiyun return;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun reg = arm_spe_event_to_pmsfcr(event);
743*4882a593Smuzhiyun write_sysreg_s(reg, SYS_PMSFCR_EL1);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun reg = arm_spe_event_to_pmsevfr(event);
746*4882a593Smuzhiyun write_sysreg_s(reg, SYS_PMSEVFR_EL1);
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun reg = arm_spe_event_to_pmslatfr(event);
749*4882a593Smuzhiyun write_sysreg_s(reg, SYS_PMSLATFR_EL1);
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun if (flags & PERF_EF_RELOAD) {
752*4882a593Smuzhiyun reg = arm_spe_event_to_pmsirr(event);
753*4882a593Smuzhiyun write_sysreg_s(reg, SYS_PMSIRR_EL1);
754*4882a593Smuzhiyun isb();
755*4882a593Smuzhiyun reg = local64_read(&hwc->period_left);
756*4882a593Smuzhiyun write_sysreg_s(reg, SYS_PMSICR_EL1);
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun reg = arm_spe_event_to_pmscr(event);
760*4882a593Smuzhiyun isb();
761*4882a593Smuzhiyun write_sysreg_s(reg, SYS_PMSCR_EL1);
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
arm_spe_pmu_stop(struct perf_event * event,int flags)764*4882a593Smuzhiyun static void arm_spe_pmu_stop(struct perf_event *event, int flags)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(event->pmu);
767*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
768*4882a593Smuzhiyun struct perf_output_handle *handle = this_cpu_ptr(spe_pmu->handle);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun /* If we're already stopped, then nothing to do */
771*4882a593Smuzhiyun if (hwc->state & PERF_HES_STOPPED)
772*4882a593Smuzhiyun return;
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun /* Stop all trace generation */
775*4882a593Smuzhiyun arm_spe_pmu_disable_and_drain_local();
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun if (flags & PERF_EF_UPDATE) {
778*4882a593Smuzhiyun /*
779*4882a593Smuzhiyun * If there's a fault pending then ensure we contain it
780*4882a593Smuzhiyun * to this buffer, since we might be on the context-switch
781*4882a593Smuzhiyun * path.
782*4882a593Smuzhiyun */
783*4882a593Smuzhiyun if (perf_get_aux(handle)) {
784*4882a593Smuzhiyun enum arm_spe_pmu_buf_fault_action act;
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun act = arm_spe_pmu_buf_get_fault_act(handle);
787*4882a593Smuzhiyun if (act == SPE_PMU_BUF_FAULT_ACT_SPURIOUS)
788*4882a593Smuzhiyun arm_spe_perf_aux_output_end(handle);
789*4882a593Smuzhiyun else
790*4882a593Smuzhiyun write_sysreg_s(0, SYS_PMBSR_EL1);
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun /*
794*4882a593Smuzhiyun * This may also contain ECOUNT, but nobody else should
795*4882a593Smuzhiyun * be looking at period_left, since we forbid frequency
796*4882a593Smuzhiyun * based sampling.
797*4882a593Smuzhiyun */
798*4882a593Smuzhiyun local64_set(&hwc->period_left, read_sysreg_s(SYS_PMSICR_EL1));
799*4882a593Smuzhiyun hwc->state |= PERF_HES_UPTODATE;
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun hwc->state |= PERF_HES_STOPPED;
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun
arm_spe_pmu_add(struct perf_event * event,int flags)805*4882a593Smuzhiyun static int arm_spe_pmu_add(struct perf_event *event, int flags)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun int ret = 0;
808*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = to_spe_pmu(event->pmu);
809*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
810*4882a593Smuzhiyun int cpu = event->cpu == -1 ? smp_processor_id() : event->cpu;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (!cpumask_test_cpu(cpu, &spe_pmu->supported_cpus))
813*4882a593Smuzhiyun return -ENOENT;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun if (flags & PERF_EF_START) {
818*4882a593Smuzhiyun arm_spe_pmu_start(event, PERF_EF_RELOAD);
819*4882a593Smuzhiyun if (hwc->state & PERF_HES_STOPPED)
820*4882a593Smuzhiyun ret = -EINVAL;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun return ret;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun
arm_spe_pmu_del(struct perf_event * event,int flags)826*4882a593Smuzhiyun static void arm_spe_pmu_del(struct perf_event *event, int flags)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun arm_spe_pmu_stop(event, PERF_EF_UPDATE);
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun
arm_spe_pmu_read(struct perf_event * event)831*4882a593Smuzhiyun static void arm_spe_pmu_read(struct perf_event *event)
832*4882a593Smuzhiyun {
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun
arm_spe_pmu_setup_aux(struct perf_event * event,void ** pages,int nr_pages,bool snapshot)835*4882a593Smuzhiyun static void *arm_spe_pmu_setup_aux(struct perf_event *event, void **pages,
836*4882a593Smuzhiyun int nr_pages, bool snapshot)
837*4882a593Smuzhiyun {
838*4882a593Smuzhiyun int i, cpu = event->cpu;
839*4882a593Smuzhiyun struct page **pglist;
840*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf;
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun /* We need at least two pages for this to work. */
843*4882a593Smuzhiyun if (nr_pages < 2)
844*4882a593Smuzhiyun return NULL;
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun /*
847*4882a593Smuzhiyun * We require an even number of pages for snapshot mode, so that
848*4882a593Smuzhiyun * we can effectively treat the buffer as consisting of two equal
849*4882a593Smuzhiyun * parts and give userspace a fighting chance of getting some
850*4882a593Smuzhiyun * useful data out of it.
851*4882a593Smuzhiyun */
852*4882a593Smuzhiyun if (snapshot && (nr_pages & 1))
853*4882a593Smuzhiyun return NULL;
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun if (cpu == -1)
856*4882a593Smuzhiyun cpu = raw_smp_processor_id();
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun buf = kzalloc_node(sizeof(*buf), GFP_KERNEL, cpu_to_node(cpu));
859*4882a593Smuzhiyun if (!buf)
860*4882a593Smuzhiyun return NULL;
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun pglist = kcalloc(nr_pages, sizeof(*pglist), GFP_KERNEL);
863*4882a593Smuzhiyun if (!pglist)
864*4882a593Smuzhiyun goto out_free_buf;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun for (i = 0; i < nr_pages; ++i)
867*4882a593Smuzhiyun pglist[i] = virt_to_page(pages[i]);
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun buf->base = vmap(pglist, nr_pages, VM_MAP, PAGE_KERNEL);
870*4882a593Smuzhiyun if (!buf->base)
871*4882a593Smuzhiyun goto out_free_pglist;
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun buf->nr_pages = nr_pages;
874*4882a593Smuzhiyun buf->snapshot = snapshot;
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun kfree(pglist);
877*4882a593Smuzhiyun return buf;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun out_free_pglist:
880*4882a593Smuzhiyun kfree(pglist);
881*4882a593Smuzhiyun out_free_buf:
882*4882a593Smuzhiyun kfree(buf);
883*4882a593Smuzhiyun return NULL;
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun
arm_spe_pmu_free_aux(void * aux)886*4882a593Smuzhiyun static void arm_spe_pmu_free_aux(void *aux)
887*4882a593Smuzhiyun {
888*4882a593Smuzhiyun struct arm_spe_pmu_buf *buf = aux;
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun vunmap(buf->base);
891*4882a593Smuzhiyun kfree(buf);
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun /* Initialisation and teardown functions */
arm_spe_pmu_perf_init(struct arm_spe_pmu * spe_pmu)895*4882a593Smuzhiyun static int arm_spe_pmu_perf_init(struct arm_spe_pmu *spe_pmu)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun static atomic_t pmu_idx = ATOMIC_INIT(-1);
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun int idx;
900*4882a593Smuzhiyun char *name;
901*4882a593Smuzhiyun struct device *dev = &spe_pmu->pdev->dev;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun spe_pmu->pmu = (struct pmu) {
904*4882a593Smuzhiyun .module = THIS_MODULE,
905*4882a593Smuzhiyun .capabilities = PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE,
906*4882a593Smuzhiyun .attr_groups = arm_spe_pmu_attr_groups,
907*4882a593Smuzhiyun /*
908*4882a593Smuzhiyun * We hitch a ride on the software context here, so that
909*4882a593Smuzhiyun * we can support per-task profiling (which is not possible
910*4882a593Smuzhiyun * with the invalid context as it doesn't get sched callbacks).
911*4882a593Smuzhiyun * This requires that userspace either uses a dummy event for
912*4882a593Smuzhiyun * perf_event_open, since the aux buffer is not setup until
913*4882a593Smuzhiyun * a subsequent mmap, or creates the profiling event in a
914*4882a593Smuzhiyun * disabled state and explicitly PERF_EVENT_IOC_ENABLEs it
915*4882a593Smuzhiyun * once the buffer has been created.
916*4882a593Smuzhiyun */
917*4882a593Smuzhiyun .task_ctx_nr = perf_sw_context,
918*4882a593Smuzhiyun .event_init = arm_spe_pmu_event_init,
919*4882a593Smuzhiyun .add = arm_spe_pmu_add,
920*4882a593Smuzhiyun .del = arm_spe_pmu_del,
921*4882a593Smuzhiyun .start = arm_spe_pmu_start,
922*4882a593Smuzhiyun .stop = arm_spe_pmu_stop,
923*4882a593Smuzhiyun .read = arm_spe_pmu_read,
924*4882a593Smuzhiyun .setup_aux = arm_spe_pmu_setup_aux,
925*4882a593Smuzhiyun .free_aux = arm_spe_pmu_free_aux,
926*4882a593Smuzhiyun };
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun idx = atomic_inc_return(&pmu_idx);
929*4882a593Smuzhiyun name = devm_kasprintf(dev, GFP_KERNEL, "%s_%d", PMUNAME, idx);
930*4882a593Smuzhiyun if (!name) {
931*4882a593Smuzhiyun dev_err(dev, "failed to allocate name for pmu %d\n", idx);
932*4882a593Smuzhiyun return -ENOMEM;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun return perf_pmu_register(&spe_pmu->pmu, name, -1);
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun
arm_spe_pmu_perf_destroy(struct arm_spe_pmu * spe_pmu)938*4882a593Smuzhiyun static void arm_spe_pmu_perf_destroy(struct arm_spe_pmu *spe_pmu)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun perf_pmu_unregister(&spe_pmu->pmu);
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun
__arm_spe_pmu_dev_probe(void * info)943*4882a593Smuzhiyun static void __arm_spe_pmu_dev_probe(void *info)
944*4882a593Smuzhiyun {
945*4882a593Smuzhiyun int fld;
946*4882a593Smuzhiyun u64 reg;
947*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = info;
948*4882a593Smuzhiyun struct device *dev = &spe_pmu->pdev->dev;
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun fld = cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64DFR0_EL1),
951*4882a593Smuzhiyun ID_AA64DFR0_PMSVER_SHIFT);
952*4882a593Smuzhiyun if (!fld) {
953*4882a593Smuzhiyun dev_err(dev,
954*4882a593Smuzhiyun "unsupported ID_AA64DFR0_EL1.PMSVer [%d] on CPU %d\n",
955*4882a593Smuzhiyun fld, smp_processor_id());
956*4882a593Smuzhiyun return;
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun /* Read PMBIDR first to determine whether or not we have access */
960*4882a593Smuzhiyun reg = read_sysreg_s(SYS_PMBIDR_EL1);
961*4882a593Smuzhiyun if (reg & BIT(SYS_PMBIDR_EL1_P_SHIFT)) {
962*4882a593Smuzhiyun dev_err(dev,
963*4882a593Smuzhiyun "profiling buffer owned by higher exception level\n");
964*4882a593Smuzhiyun return;
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun /* Minimum alignment. If it's out-of-range, then fail the probe */
968*4882a593Smuzhiyun fld = reg >> SYS_PMBIDR_EL1_ALIGN_SHIFT & SYS_PMBIDR_EL1_ALIGN_MASK;
969*4882a593Smuzhiyun spe_pmu->align = 1 << fld;
970*4882a593Smuzhiyun if (spe_pmu->align > SZ_2K) {
971*4882a593Smuzhiyun dev_err(dev, "unsupported PMBIDR.Align [%d] on CPU %d\n",
972*4882a593Smuzhiyun fld, smp_processor_id());
973*4882a593Smuzhiyun return;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun /* It's now safe to read PMSIDR and figure out what we've got */
977*4882a593Smuzhiyun reg = read_sysreg_s(SYS_PMSIDR_EL1);
978*4882a593Smuzhiyun if (reg & BIT(SYS_PMSIDR_EL1_FE_SHIFT))
979*4882a593Smuzhiyun spe_pmu->features |= SPE_PMU_FEAT_FILT_EVT;
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun if (reg & BIT(SYS_PMSIDR_EL1_FT_SHIFT))
982*4882a593Smuzhiyun spe_pmu->features |= SPE_PMU_FEAT_FILT_TYP;
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun if (reg & BIT(SYS_PMSIDR_EL1_FL_SHIFT))
985*4882a593Smuzhiyun spe_pmu->features |= SPE_PMU_FEAT_FILT_LAT;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun if (reg & BIT(SYS_PMSIDR_EL1_ARCHINST_SHIFT))
988*4882a593Smuzhiyun spe_pmu->features |= SPE_PMU_FEAT_ARCH_INST;
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun if (reg & BIT(SYS_PMSIDR_EL1_LDS_SHIFT))
991*4882a593Smuzhiyun spe_pmu->features |= SPE_PMU_FEAT_LDS;
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun if (reg & BIT(SYS_PMSIDR_EL1_ERND_SHIFT))
994*4882a593Smuzhiyun spe_pmu->features |= SPE_PMU_FEAT_ERND;
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun /* This field has a spaced out encoding, so just use a look-up */
997*4882a593Smuzhiyun fld = reg >> SYS_PMSIDR_EL1_INTERVAL_SHIFT & SYS_PMSIDR_EL1_INTERVAL_MASK;
998*4882a593Smuzhiyun switch (fld) {
999*4882a593Smuzhiyun case 0:
1000*4882a593Smuzhiyun spe_pmu->min_period = 256;
1001*4882a593Smuzhiyun break;
1002*4882a593Smuzhiyun case 2:
1003*4882a593Smuzhiyun spe_pmu->min_period = 512;
1004*4882a593Smuzhiyun break;
1005*4882a593Smuzhiyun case 3:
1006*4882a593Smuzhiyun spe_pmu->min_period = 768;
1007*4882a593Smuzhiyun break;
1008*4882a593Smuzhiyun case 4:
1009*4882a593Smuzhiyun spe_pmu->min_period = 1024;
1010*4882a593Smuzhiyun break;
1011*4882a593Smuzhiyun case 5:
1012*4882a593Smuzhiyun spe_pmu->min_period = 1536;
1013*4882a593Smuzhiyun break;
1014*4882a593Smuzhiyun case 6:
1015*4882a593Smuzhiyun spe_pmu->min_period = 2048;
1016*4882a593Smuzhiyun break;
1017*4882a593Smuzhiyun case 7:
1018*4882a593Smuzhiyun spe_pmu->min_period = 3072;
1019*4882a593Smuzhiyun break;
1020*4882a593Smuzhiyun default:
1021*4882a593Smuzhiyun dev_warn(dev, "unknown PMSIDR_EL1.Interval [%d]; assuming 8\n",
1022*4882a593Smuzhiyun fld);
1023*4882a593Smuzhiyun fallthrough;
1024*4882a593Smuzhiyun case 8:
1025*4882a593Smuzhiyun spe_pmu->min_period = 4096;
1026*4882a593Smuzhiyun }
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun /* Maximum record size. If it's out-of-range, then fail the probe */
1029*4882a593Smuzhiyun fld = reg >> SYS_PMSIDR_EL1_MAXSIZE_SHIFT & SYS_PMSIDR_EL1_MAXSIZE_MASK;
1030*4882a593Smuzhiyun spe_pmu->max_record_sz = 1 << fld;
1031*4882a593Smuzhiyun if (spe_pmu->max_record_sz > SZ_2K || spe_pmu->max_record_sz < 16) {
1032*4882a593Smuzhiyun dev_err(dev, "unsupported PMSIDR_EL1.MaxSize [%d] on CPU %d\n",
1033*4882a593Smuzhiyun fld, smp_processor_id());
1034*4882a593Smuzhiyun return;
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun fld = reg >> SYS_PMSIDR_EL1_COUNTSIZE_SHIFT & SYS_PMSIDR_EL1_COUNTSIZE_MASK;
1038*4882a593Smuzhiyun switch (fld) {
1039*4882a593Smuzhiyun default:
1040*4882a593Smuzhiyun dev_warn(dev, "unknown PMSIDR_EL1.CountSize [%d]; assuming 2\n",
1041*4882a593Smuzhiyun fld);
1042*4882a593Smuzhiyun fallthrough;
1043*4882a593Smuzhiyun case 2:
1044*4882a593Smuzhiyun spe_pmu->counter_sz = 12;
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun dev_info(dev,
1048*4882a593Smuzhiyun "probed for CPUs %*pbl [max_record_sz %u, align %u, features 0x%llx]\n",
1049*4882a593Smuzhiyun cpumask_pr_args(&spe_pmu->supported_cpus),
1050*4882a593Smuzhiyun spe_pmu->max_record_sz, spe_pmu->align, spe_pmu->features);
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun spe_pmu->features |= SPE_PMU_FEAT_DEV_PROBED;
1053*4882a593Smuzhiyun return;
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun
__arm_spe_pmu_reset_local(void)1056*4882a593Smuzhiyun static void __arm_spe_pmu_reset_local(void)
1057*4882a593Smuzhiyun {
1058*4882a593Smuzhiyun /*
1059*4882a593Smuzhiyun * This is probably overkill, as we have no idea where we're
1060*4882a593Smuzhiyun * draining any buffered data to...
1061*4882a593Smuzhiyun */
1062*4882a593Smuzhiyun arm_spe_pmu_disable_and_drain_local();
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun /* Reset the buffer base pointer */
1065*4882a593Smuzhiyun write_sysreg_s(0, SYS_PMBPTR_EL1);
1066*4882a593Smuzhiyun isb();
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun /* Clear any pending management interrupts */
1069*4882a593Smuzhiyun write_sysreg_s(0, SYS_PMBSR_EL1);
1070*4882a593Smuzhiyun isb();
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun
__arm_spe_pmu_setup_one(void * info)1073*4882a593Smuzhiyun static void __arm_spe_pmu_setup_one(void *info)
1074*4882a593Smuzhiyun {
1075*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = info;
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun __arm_spe_pmu_reset_local();
1078*4882a593Smuzhiyun enable_percpu_irq(spe_pmu->irq, IRQ_TYPE_NONE);
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun
__arm_spe_pmu_stop_one(void * info)1081*4882a593Smuzhiyun static void __arm_spe_pmu_stop_one(void *info)
1082*4882a593Smuzhiyun {
1083*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = info;
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun disable_percpu_irq(spe_pmu->irq);
1086*4882a593Smuzhiyun __arm_spe_pmu_reset_local();
1087*4882a593Smuzhiyun }
1088*4882a593Smuzhiyun
arm_spe_pmu_cpu_startup(unsigned int cpu,struct hlist_node * node)1089*4882a593Smuzhiyun static int arm_spe_pmu_cpu_startup(unsigned int cpu, struct hlist_node *node)
1090*4882a593Smuzhiyun {
1091*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu;
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun spe_pmu = hlist_entry_safe(node, struct arm_spe_pmu, hotplug_node);
1094*4882a593Smuzhiyun if (!cpumask_test_cpu(cpu, &spe_pmu->supported_cpus))
1095*4882a593Smuzhiyun return 0;
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun __arm_spe_pmu_setup_one(spe_pmu);
1098*4882a593Smuzhiyun return 0;
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun
arm_spe_pmu_cpu_teardown(unsigned int cpu,struct hlist_node * node)1101*4882a593Smuzhiyun static int arm_spe_pmu_cpu_teardown(unsigned int cpu, struct hlist_node *node)
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu;
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun spe_pmu = hlist_entry_safe(node, struct arm_spe_pmu, hotplug_node);
1106*4882a593Smuzhiyun if (!cpumask_test_cpu(cpu, &spe_pmu->supported_cpus))
1107*4882a593Smuzhiyun return 0;
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun __arm_spe_pmu_stop_one(spe_pmu);
1110*4882a593Smuzhiyun return 0;
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun
arm_spe_pmu_dev_init(struct arm_spe_pmu * spe_pmu)1113*4882a593Smuzhiyun static int arm_spe_pmu_dev_init(struct arm_spe_pmu *spe_pmu)
1114*4882a593Smuzhiyun {
1115*4882a593Smuzhiyun int ret;
1116*4882a593Smuzhiyun cpumask_t *mask = &spe_pmu->supported_cpus;
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun /* Make sure we probe the hardware on a relevant CPU */
1119*4882a593Smuzhiyun ret = smp_call_function_any(mask, __arm_spe_pmu_dev_probe, spe_pmu, 1);
1120*4882a593Smuzhiyun if (ret || !(spe_pmu->features & SPE_PMU_FEAT_DEV_PROBED))
1121*4882a593Smuzhiyun return -ENXIO;
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun /* Request our PPIs (note that the IRQ is still disabled) */
1124*4882a593Smuzhiyun ret = request_percpu_irq(spe_pmu->irq, arm_spe_pmu_irq_handler, DRVNAME,
1125*4882a593Smuzhiyun spe_pmu->handle);
1126*4882a593Smuzhiyun if (ret)
1127*4882a593Smuzhiyun return ret;
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun /*
1130*4882a593Smuzhiyun * Register our hotplug notifier now so we don't miss any events.
1131*4882a593Smuzhiyun * This will enable the IRQ for any supported CPUs that are already
1132*4882a593Smuzhiyun * up.
1133*4882a593Smuzhiyun */
1134*4882a593Smuzhiyun ret = cpuhp_state_add_instance(arm_spe_pmu_online,
1135*4882a593Smuzhiyun &spe_pmu->hotplug_node);
1136*4882a593Smuzhiyun if (ret)
1137*4882a593Smuzhiyun free_percpu_irq(spe_pmu->irq, spe_pmu->handle);
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun return ret;
1140*4882a593Smuzhiyun }
1141*4882a593Smuzhiyun
arm_spe_pmu_dev_teardown(struct arm_spe_pmu * spe_pmu)1142*4882a593Smuzhiyun static void arm_spe_pmu_dev_teardown(struct arm_spe_pmu *spe_pmu)
1143*4882a593Smuzhiyun {
1144*4882a593Smuzhiyun cpuhp_state_remove_instance(arm_spe_pmu_online, &spe_pmu->hotplug_node);
1145*4882a593Smuzhiyun free_percpu_irq(spe_pmu->irq, spe_pmu->handle);
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun /* Driver and device probing */
arm_spe_pmu_irq_probe(struct arm_spe_pmu * spe_pmu)1149*4882a593Smuzhiyun static int arm_spe_pmu_irq_probe(struct arm_spe_pmu *spe_pmu)
1150*4882a593Smuzhiyun {
1151*4882a593Smuzhiyun struct platform_device *pdev = spe_pmu->pdev;
1152*4882a593Smuzhiyun int irq = platform_get_irq(pdev, 0);
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun if (irq < 0)
1155*4882a593Smuzhiyun return -ENXIO;
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun if (!irq_is_percpu(irq)) {
1158*4882a593Smuzhiyun dev_err(&pdev->dev, "expected PPI but got SPI (%d)\n", irq);
1159*4882a593Smuzhiyun return -EINVAL;
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun if (irq_get_percpu_devid_partition(irq, &spe_pmu->supported_cpus)) {
1163*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to get PPI partition (%d)\n", irq);
1164*4882a593Smuzhiyun return -EINVAL;
1165*4882a593Smuzhiyun }
1166*4882a593Smuzhiyun
1167*4882a593Smuzhiyun spe_pmu->irq = irq;
1168*4882a593Smuzhiyun return 0;
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun
1171*4882a593Smuzhiyun static const struct of_device_id arm_spe_pmu_of_match[] = {
1172*4882a593Smuzhiyun { .compatible = "arm,statistical-profiling-extension-v1", .data = (void *)1 },
1173*4882a593Smuzhiyun { /* Sentinel */ },
1174*4882a593Smuzhiyun };
1175*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, arm_spe_pmu_of_match);
1176*4882a593Smuzhiyun
1177*4882a593Smuzhiyun static const struct platform_device_id arm_spe_match[] = {
1178*4882a593Smuzhiyun { ARMV8_SPE_PDEV_NAME, 0},
1179*4882a593Smuzhiyun { }
1180*4882a593Smuzhiyun };
1181*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, arm_spe_match);
1182*4882a593Smuzhiyun
arm_spe_pmu_device_probe(struct platform_device * pdev)1183*4882a593Smuzhiyun static int arm_spe_pmu_device_probe(struct platform_device *pdev)
1184*4882a593Smuzhiyun {
1185*4882a593Smuzhiyun int ret;
1186*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu;
1187*4882a593Smuzhiyun struct device *dev = &pdev->dev;
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun /*
1190*4882a593Smuzhiyun * If kernelspace is unmapped when running at EL0, then the SPE
1191*4882a593Smuzhiyun * buffer will fault and prematurely terminate the AUX session.
1192*4882a593Smuzhiyun */
1193*4882a593Smuzhiyun if (arm64_kernel_unmapped_at_el0()) {
1194*4882a593Smuzhiyun dev_warn_once(dev, "profiling buffer inaccessible. Try passing \"kpti=off\" on the kernel command line\n");
1195*4882a593Smuzhiyun return -EPERM;
1196*4882a593Smuzhiyun }
1197*4882a593Smuzhiyun
1198*4882a593Smuzhiyun spe_pmu = devm_kzalloc(dev, sizeof(*spe_pmu), GFP_KERNEL);
1199*4882a593Smuzhiyun if (!spe_pmu) {
1200*4882a593Smuzhiyun dev_err(dev, "failed to allocate spe_pmu\n");
1201*4882a593Smuzhiyun return -ENOMEM;
1202*4882a593Smuzhiyun }
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun spe_pmu->handle = alloc_percpu(typeof(*spe_pmu->handle));
1205*4882a593Smuzhiyun if (!spe_pmu->handle)
1206*4882a593Smuzhiyun return -ENOMEM;
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun spe_pmu->pdev = pdev;
1209*4882a593Smuzhiyun platform_set_drvdata(pdev, spe_pmu);
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun ret = arm_spe_pmu_irq_probe(spe_pmu);
1212*4882a593Smuzhiyun if (ret)
1213*4882a593Smuzhiyun goto out_free_handle;
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun ret = arm_spe_pmu_dev_init(spe_pmu);
1216*4882a593Smuzhiyun if (ret)
1217*4882a593Smuzhiyun goto out_free_handle;
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun ret = arm_spe_pmu_perf_init(spe_pmu);
1220*4882a593Smuzhiyun if (ret)
1221*4882a593Smuzhiyun goto out_teardown_dev;
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun return 0;
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun out_teardown_dev:
1226*4882a593Smuzhiyun arm_spe_pmu_dev_teardown(spe_pmu);
1227*4882a593Smuzhiyun out_free_handle:
1228*4882a593Smuzhiyun free_percpu(spe_pmu->handle);
1229*4882a593Smuzhiyun return ret;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
arm_spe_pmu_device_remove(struct platform_device * pdev)1232*4882a593Smuzhiyun static int arm_spe_pmu_device_remove(struct platform_device *pdev)
1233*4882a593Smuzhiyun {
1234*4882a593Smuzhiyun struct arm_spe_pmu *spe_pmu = platform_get_drvdata(pdev);
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun arm_spe_pmu_perf_destroy(spe_pmu);
1237*4882a593Smuzhiyun arm_spe_pmu_dev_teardown(spe_pmu);
1238*4882a593Smuzhiyun free_percpu(spe_pmu->handle);
1239*4882a593Smuzhiyun return 0;
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun static struct platform_driver arm_spe_pmu_driver = {
1243*4882a593Smuzhiyun .id_table = arm_spe_match,
1244*4882a593Smuzhiyun .driver = {
1245*4882a593Smuzhiyun .name = DRVNAME,
1246*4882a593Smuzhiyun .of_match_table = of_match_ptr(arm_spe_pmu_of_match),
1247*4882a593Smuzhiyun .suppress_bind_attrs = true,
1248*4882a593Smuzhiyun },
1249*4882a593Smuzhiyun .probe = arm_spe_pmu_device_probe,
1250*4882a593Smuzhiyun .remove = arm_spe_pmu_device_remove,
1251*4882a593Smuzhiyun };
1252*4882a593Smuzhiyun
arm_spe_pmu_init(void)1253*4882a593Smuzhiyun static int __init arm_spe_pmu_init(void)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun int ret;
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, DRVNAME,
1258*4882a593Smuzhiyun arm_spe_pmu_cpu_startup,
1259*4882a593Smuzhiyun arm_spe_pmu_cpu_teardown);
1260*4882a593Smuzhiyun if (ret < 0)
1261*4882a593Smuzhiyun return ret;
1262*4882a593Smuzhiyun arm_spe_pmu_online = ret;
1263*4882a593Smuzhiyun
1264*4882a593Smuzhiyun ret = platform_driver_register(&arm_spe_pmu_driver);
1265*4882a593Smuzhiyun if (ret)
1266*4882a593Smuzhiyun cpuhp_remove_multi_state(arm_spe_pmu_online);
1267*4882a593Smuzhiyun
1268*4882a593Smuzhiyun return ret;
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun
arm_spe_pmu_exit(void)1271*4882a593Smuzhiyun static void __exit arm_spe_pmu_exit(void)
1272*4882a593Smuzhiyun {
1273*4882a593Smuzhiyun platform_driver_unregister(&arm_spe_pmu_driver);
1274*4882a593Smuzhiyun cpuhp_remove_multi_state(arm_spe_pmu_online);
1275*4882a593Smuzhiyun }
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun module_init(arm_spe_pmu_init);
1278*4882a593Smuzhiyun module_exit(arm_spe_pmu_exit);
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun MODULE_DESCRIPTION("Perf driver for the ARMv8.2 Statistical Profiling Extension");
1281*4882a593Smuzhiyun MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
1282*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1283