/* 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 #include #include #include #include #include #include #include #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, arm_cspmu_sysfs_format_show, (char *)_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; 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); /* Default function to show format attribute in sysfs. */ ssize_t arm_cspmu_sysfs_format_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__ */