Skip to content

Commit 1efb790

Browse files
perf/core: adding PMU driver specific configuration
It is entirely possible that some PMUs need specific configuration that is currently not found in the perf options before a session can be setup. It is the case for the CoreSight PMU where a sink needs to be provided. That sink doesn't fall in any of the current perf options. As such this patch adds the capability to receive driver specific configuration using the existing ioctl() mechanism. Once the configuration has been pushed down the kernel PMU callbacks are used to deal with the information sent from user space. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
1 parent 65ad7b1 commit 1efb790

3 files changed

Lines changed: 29 additions & 0 deletions

File tree

include/linux/perf_event.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,14 @@ struct pmu {
391391
* Filter events for PMU-specific reasons.
392392
*/
393393
int (*filter_match) (struct perf_event *event); /* optional */
394+
395+
/*
396+
* Initial, PMU driver specific configuration.
397+
*/
398+
int (*get_drv_configs) (struct perf_event *event,
399+
void __user *arg); /* optional */
400+
void (*free_drv_configs) (struct perf_event *event);
401+
/* optional */
394402
};
395403

396404
/**
@@ -558,6 +566,7 @@ struct perf_event {
558566
struct irq_work pending;
559567

560568
atomic_t event_limit;
569+
struct list_head drv_configs;
561570

562571
void (*destroy)(struct perf_event *);
563572
struct rcu_head rcu_head;

include/uapi/linux/perf_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ struct perf_event_attr {
395395
#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
396396
#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
397397
#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
398+
#define PERF_EVENT_IOC_SET_DRV_CONFIGS _IOW('$', 10, char *)
398399

399400
enum perf_event_ioc_flags {
400401
PERF_IOC_FLAG_GROUP = 1U << 0,

kernel/events/core.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3729,6 +3729,9 @@ static void __free_event(struct perf_event *event)
37293729
if (event->destroy)
37303730
event->destroy(event);
37313731

3732+
if (event->pmu->free_drv_configs)
3733+
event->pmu->free_drv_configs(event);
3734+
37323735
if (event->ctx)
37333736
put_ctx(event->ctx);
37343737

@@ -4281,6 +4284,8 @@ static int perf_event_set_output(struct perf_event *event,
42814284
struct perf_event *output_event);
42824285
static int perf_event_set_filter(struct perf_event *event, void __user *arg);
42834286
static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd);
4287+
static int perf_event_drv_configs(struct perf_event *event,
4288+
void __user *arg);
42844289

42854290
static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
42864291
{
@@ -4337,6 +4342,9 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
43374342
case PERF_EVENT_IOC_SET_BPF:
43384343
return perf_event_set_bpf_prog(event, arg);
43394344

4345+
case PERF_EVENT_IOC_SET_DRV_CONFIGS:
4346+
return perf_event_drv_configs(event, (void __user *)arg);
4347+
43404348
default:
43414349
return -ENOTTY;
43424350
}
@@ -4369,6 +4377,7 @@ static long perf_compat_ioctl(struct file *file, unsigned int cmd,
43694377
switch (_IOC_NR(cmd)) {
43704378
case _IOC_NR(PERF_EVENT_IOC_SET_FILTER):
43714379
case _IOC_NR(PERF_EVENT_IOC_ID):
4380+
case _IOC_NR(PERF_EVENT_IOC_SET_DRV_CONFIGS):
43724381
/* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */
43734382
if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
43744383
cmd &= ~IOCSIZE_MASK;
@@ -7268,6 +7277,15 @@ void perf_bp_event(struct perf_event *bp, void *data)
72687277
}
72697278
#endif
72707279

7280+
static int perf_event_drv_configs(struct perf_event *event,
7281+
void __user *arg)
7282+
{
7283+
if (!event->pmu->get_drv_configs)
7284+
return -EINVAL;
7285+
7286+
return event->pmu->get_drv_configs(event, arg);
7287+
}
7288+
72717289
/*
72727290
* hrtimer based swevent callback
72737291
*/
@@ -8004,6 +8022,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
80048022
INIT_LIST_HEAD(&event->sibling_list);
80058023
INIT_LIST_HEAD(&event->rb_entry);
80068024
INIT_LIST_HEAD(&event->active_entry);
8025+
INIT_LIST_HEAD(&event->drv_configs);
80078026
INIT_HLIST_NODE(&event->hlist_entry);
80088027

80098028

0 commit comments

Comments
 (0)