aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-03-27 04:46:19 -0400
committerIngo Molnar <mingo@kernel.org>2015-03-27 04:46:19 -0400
commit936c663aed930972f7e185485fd6c2da69e33819 (patch)
tree41bb069f66e109fc63c4114a4390de44d3068356 /kernel/events
parent072e5a1cfabca7276744d24726e094d85721df5c (diff)
parent50f16a8bf9d7a92c437ed1867d0f7e1dc6a9aca9 (diff)
Merge branch 'perf/x86' into perf/core, because it's ready
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
-rw-r--r--kernel/events/core.c73
-rw-r--r--kernel/events/hw_breakpoint.c8
2 files changed, 29 insertions, 52 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 9a5f339a0e2d..b01dfb602db1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -34,11 +34,11 @@
34#include <linux/syscalls.h> 34#include <linux/syscalls.h>
35#include <linux/anon_inodes.h> 35#include <linux/anon_inodes.h>
36#include <linux/kernel_stat.h> 36#include <linux/kernel_stat.h>
37#include <linux/cgroup.h>
37#include <linux/perf_event.h> 38#include <linux/perf_event.h>
38#include <linux/ftrace_event.h> 39#include <linux/ftrace_event.h>
39#include <linux/hw_breakpoint.h> 40#include <linux/hw_breakpoint.h>
40#include <linux/mm_types.h> 41#include <linux/mm_types.h>
41#include <linux/cgroup.h>
42#include <linux/module.h> 42#include <linux/module.h>
43#include <linux/mman.h> 43#include <linux/mman.h>
44#include <linux/compat.h> 44#include <linux/compat.h>
@@ -351,32 +351,6 @@ static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
351 351
352#ifdef CONFIG_CGROUP_PERF 352#ifdef CONFIG_CGROUP_PERF
353 353
354/*
355 * perf_cgroup_info keeps track of time_enabled for a cgroup.
356 * This is a per-cpu dynamically allocated data structure.
357 */
358struct perf_cgroup_info {
359 u64 time;
360 u64 timestamp;
361};
362
363struct perf_cgroup {
364 struct cgroup_subsys_state css;
365 struct perf_cgroup_info __percpu *info;
366};
367
368/*
369 * Must ensure cgroup is pinned (css_get) before calling
370 * this function. In other words, we cannot call this function
371 * if there is no cgroup event for the current CPU context.
372 */
373static inline struct perf_cgroup *
374perf_cgroup_from_task(struct task_struct *task)
375{
376 return container_of(task_css(task, perf_event_cgrp_id),
377 struct perf_cgroup, css);
378}
379
380static inline bool 354static inline bool
381perf_cgroup_match(struct perf_event *event) 355perf_cgroup_match(struct perf_event *event)
382{ 356{
@@ -3220,7 +3194,10 @@ static void __perf_event_read(void *info)
3220 3194
3221static inline u64 perf_event_count(struct perf_event *event) 3195static inline u64 perf_event_count(struct perf_event *event)
3222{ 3196{
3223 return local64_read(&event->count) + atomic64_read(&event->child_count); 3197 if (event->pmu->count)
3198 return event->pmu->count(event);
3199
3200 return __perf_event_count(event);
3224} 3201}
3225 3202
3226static u64 perf_event_read(struct perf_event *event) 3203static u64 perf_event_read(struct perf_event *event)
@@ -7149,7 +7126,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
7149 struct perf_event *group_leader, 7126 struct perf_event *group_leader,
7150 struct perf_event *parent_event, 7127 struct perf_event *parent_event,
7151 perf_overflow_handler_t overflow_handler, 7128 perf_overflow_handler_t overflow_handler,
7152 void *context) 7129 void *context, int cgroup_fd)
7153{ 7130{
7154 struct pmu *pmu; 7131 struct pmu *pmu;
7155 struct perf_event *event; 7132 struct perf_event *event;
@@ -7204,16 +7181,12 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
7204 7181
7205 if (task) { 7182 if (task) {
7206 event->attach_state = PERF_ATTACH_TASK; 7183 event->attach_state = PERF_ATTACH_TASK;
7207
7208 if (attr->type == PERF_TYPE_TRACEPOINT)
7209 event->hw.tp_target = task;
7210#ifdef CONFIG_HAVE_HW_BREAKPOINT
7211 /* 7184 /*
7212 * hw_breakpoint is a bit difficult here.. 7185 * XXX pmu::event_init needs to know what task to account to
7186 * and we cannot use the ctx information because we need the
7187 * pmu before we get a ctx.
7213 */ 7188 */
7214 else if (attr->type == PERF_TYPE_BREAKPOINT) 7189 event->hw.target = task;
7215 event->hw.bp_target = task;
7216#endif
7217 } 7190 }
7218 7191
7219 if (!overflow_handler && parent_event) { 7192 if (!overflow_handler && parent_event) {
@@ -7245,6 +7218,12 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
7245 if (!has_branch_stack(event)) 7218 if (!has_branch_stack(event))
7246 event->attr.branch_sample_type = 0; 7219 event->attr.branch_sample_type = 0;
7247 7220
7221 if (cgroup_fd != -1) {
7222 err = perf_cgroup_connect(cgroup_fd, event, attr, group_leader);
7223 if (err)
7224 goto err_ns;
7225 }
7226
7248 pmu = perf_init_event(event); 7227 pmu = perf_init_event(event);
7249 if (!pmu) 7228 if (!pmu)
7250 goto err_ns; 7229 goto err_ns;
@@ -7268,6 +7247,8 @@ err_pmu:
7268 event->destroy(event); 7247 event->destroy(event);
7269 module_put(pmu->module); 7248 module_put(pmu->module);
7270err_ns: 7249err_ns:
7250 if (is_cgroup_event(event))
7251 perf_detach_cgroup(event);
7271 if (event->ns) 7252 if (event->ns)
7272 put_pid_ns(event->ns); 7253 put_pid_ns(event->ns);
7273 kfree(event); 7254 kfree(event);
@@ -7486,6 +7467,7 @@ SYSCALL_DEFINE5(perf_event_open,
7486 int move_group = 0; 7467 int move_group = 0;
7487 int err; 7468 int err;
7488 int f_flags = O_RDWR; 7469 int f_flags = O_RDWR;
7470 int cgroup_fd = -1;
7489 7471
7490 /* for future expandability... */ 7472 /* for future expandability... */
7491 if (flags & ~PERF_FLAG_ALL) 7473 if (flags & ~PERF_FLAG_ALL)
@@ -7551,21 +7533,16 @@ SYSCALL_DEFINE5(perf_event_open,
7551 7533
7552 get_online_cpus(); 7534 get_online_cpus();
7553 7535
7536 if (flags & PERF_FLAG_PID_CGROUP)
7537 cgroup_fd = pid;
7538
7554 event = perf_event_alloc(&attr, cpu, task, group_leader, NULL, 7539 event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
7555 NULL, NULL); 7540 NULL, NULL, cgroup_fd);
7556 if (IS_ERR(event)) { 7541 if (IS_ERR(event)) {
7557 err = PTR_ERR(event); 7542 err = PTR_ERR(event);
7558 goto err_cpus; 7543 goto err_cpus;
7559 } 7544 }
7560 7545
7561 if (flags & PERF_FLAG_PID_CGROUP) {
7562 err = perf_cgroup_connect(pid, event, &attr, group_leader);
7563 if (err) {
7564 __free_event(event);
7565 goto err_cpus;
7566 }
7567 }
7568
7569 if (is_sampling_event(event)) { 7546 if (is_sampling_event(event)) {
7570 if (event->pmu->capabilities & PERF_PMU_CAP_NO_INTERRUPT) { 7547 if (event->pmu->capabilities & PERF_PMU_CAP_NO_INTERRUPT) {
7571 err = -ENOTSUPP; 7548 err = -ENOTSUPP;
@@ -7802,7 +7779,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
7802 */ 7779 */
7803 7780
7804 event = perf_event_alloc(attr, cpu, task, NULL, NULL, 7781 event = perf_event_alloc(attr, cpu, task, NULL, NULL,
7805 overflow_handler, context); 7782 overflow_handler, context, -1);
7806 if (IS_ERR(event)) { 7783 if (IS_ERR(event)) {
7807 err = PTR_ERR(event); 7784 err = PTR_ERR(event);
7808 goto err; 7785 goto err;
@@ -8163,7 +8140,7 @@ inherit_event(struct perf_event *parent_event,
8163 parent_event->cpu, 8140 parent_event->cpu,
8164 child, 8141 child,
8165 group_leader, parent_event, 8142 group_leader, parent_event,
8166 NULL, NULL); 8143 NULL, NULL, -1);
8167 if (IS_ERR(child_event)) 8144 if (IS_ERR(child_event))
8168 return child_event; 8145 return child_event;
8169 8146
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 9803a6600d49..92ce5f4ccc26 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -116,12 +116,12 @@ static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type)
116 */ 116 */
117static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type) 117static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type)
118{ 118{
119 struct task_struct *tsk = bp->hw.bp_target; 119 struct task_struct *tsk = bp->hw.target;
120 struct perf_event *iter; 120 struct perf_event *iter;
121 int count = 0; 121 int count = 0;
122 122
123 list_for_each_entry(iter, &bp_task_head, hw.bp_list) { 123 list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
124 if (iter->hw.bp_target == tsk && 124 if (iter->hw.target == tsk &&
125 find_slot_idx(iter) == type && 125 find_slot_idx(iter) == type &&
126 (iter->cpu < 0 || cpu == iter->cpu)) 126 (iter->cpu < 0 || cpu == iter->cpu))
127 count += hw_breakpoint_weight(iter); 127 count += hw_breakpoint_weight(iter);
@@ -153,7 +153,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
153 int nr; 153 int nr;
154 154
155 nr = info->cpu_pinned; 155 nr = info->cpu_pinned;
156 if (!bp->hw.bp_target) 156 if (!bp->hw.target)
157 nr += max_task_bp_pinned(cpu, type); 157 nr += max_task_bp_pinned(cpu, type);
158 else 158 else
159 nr += task_bp_pinned(cpu, bp, type); 159 nr += task_bp_pinned(cpu, bp, type);
@@ -210,7 +210,7 @@ toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type,
210 weight = -weight; 210 weight = -weight;
211 211
212 /* Pinned counter cpu profiling */ 212 /* Pinned counter cpu profiling */
213 if (!bp->hw.bp_target) { 213 if (!bp->hw.target) {
214 get_bp_info(bp->cpu, type)->cpu_pinned += weight; 214 get_bp_info(bp->cpu, type)->cpu_pinned += weight;
215 return; 215 return;
216 } 216 }