lkml.org 
[lkml]   [2015]   [Sep]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 2/4] perf: Add function to enable perf events in kernel with ring buffer
Date
perf_event_create_kernel_counter is used to enable perf events in kernel
without buffer for logging its events. This patch add new fucntion which
enable perf events with ring buffer. Intel PT logger uses this to enable
Intel PT and some associated events with its log buffer.

Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
---
include/linux/perf_event.h | 10 ++++++
kernel/events/core.c | 70 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 2027809..34ada8c 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -657,6 +657,16 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr,
struct task_struct *task,
perf_overflow_handler_t callback,
void *context);
+extern struct perf_event *
+perf_event_create_kernel_counter_with_buffer(struct perf_event_attr *attr,
+ int cpu,
+ struct task_struct *task,
+ perf_overflow_handler_t callback,
+ void *context,
+ int flags,
+ int nr_pages,
+ int nr_pages_aux,
+ struct perf_event *output_event);
extern void perf_pmu_migrate_context(struct pmu *pmu,
int src_cpu, int dst_cpu);
extern u64 perf_event_read_value(struct perf_event *event,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index ae16867..c9d8a59 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8356,21 +8356,33 @@ err_fd:
}

/**
- * perf_event_create_kernel_counter
+ * perf_event_create_kernel_counter_with_buffer
*
* @attr: attributes of the counter to create
* @cpu: cpu in which the counter is bound
* @task: task to profile (NULL for percpu)
+ * @overflow_handler: handler for overflow event
+ * @context: target context
+ * @flags: flags of ring buffer
+ * @nr_pages: size (number of pages) of buffer
+ * @nr_pages_aux: size (number of pages) of aux buffer
+ * @output_event: event to be attached
*/
struct perf_event *
-perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
- struct task_struct *task,
- perf_overflow_handler_t overflow_handler,
- void *context)
+perf_event_create_kernel_counter_with_buffer(struct perf_event_attr *attr,
+ int cpu,
+ struct task_struct *task,
+ perf_overflow_handler_t overflow_handler,
+ void *context,
+ int flags,
+ int nr_pages,
+ int nr_pages_aux,
+ struct perf_event *output_event)
{
struct perf_event_context *ctx;
struct perf_event *event;
int err;
+ struct ring_buffer *rb = NULL;

/*
* Get the target context (task or percpu):
@@ -8383,6 +8395,31 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
goto err;
}

+ if (output_event) {
+ err = perf_event_set_output(event, output_event);
+ if (err)
+ goto err_free;
+ } else if (nr_pages) {
+ rb = rb_alloc(nr_pages,
+ event->attr.watermark ? event->attr.wakeup_watermark : 0,
+ event->cpu, flags);
+
+ if (!rb) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
+ ring_buffer_attach(event, rb);
+
+ if (nr_pages_aux) {
+ err = rb_alloc_aux(rb, event, 0, nr_pages_aux,
+ event->attr.aux_watermark, flags);
+
+ if (err)
+ goto err_free;
+ }
+ }
+
/* Mark owner so we could distinguish it from user events. */
event->owner = EVENT_OWNER_KERNEL;

@@ -8411,10 +8448,33 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
return event;

err_free:
+ if (rb && rb->aux_pages)
+ rb_free_aux(rb);
+ if (rb)
+ rb_free(rb);
free_event(event);
err:
return ERR_PTR(err);
}
+EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter_with_buffer);
+
+/**
+ * perf_event_create_kernel_counter
+ *
+ * @attr: attributes of the counter to create
+ * @cpu: cpu in which the counter is bound
+ * @task: task to profile (NULL for percpu)
+ */
+struct perf_event *
+perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
+ struct task_struct *task,
+ perf_overflow_handler_t overflow_handler,
+ void *context)
+{
+ return perf_event_create_kernel_counter_with_buffer(attr, cpu, task,
+ overflow_handler,
+ context, 0, 0, 0, NULL);
+}
EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);

void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
--
1.7.1



\
 
 \ /
  Last update: 2015-09-08 08:01    [W:0.082 / U:0.032 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site