diff options
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 5087125e2a00..98dc56b2ebe4 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/kernel_stat.h> | 29 | #include <linux/kernel_stat.h> |
30 | #include <linux/perf_event.h> | 30 | #include <linux/perf_event.h> |
31 | #include <linux/ftrace_event.h> | 31 | #include <linux/ftrace_event.h> |
32 | #include <linux/hw_breakpoint.h> | ||
32 | 33 | ||
33 | #include <asm/irq_regs.h> | 34 | #include <asm/irq_regs.h> |
34 | 35 | ||
@@ -4229,6 +4230,51 @@ static void perf_event_free_filter(struct perf_event *event) | |||
4229 | 4230 | ||
4230 | #endif /* CONFIG_EVENT_PROFILE */ | 4231 | #endif /* CONFIG_EVENT_PROFILE */ |
4231 | 4232 | ||
4233 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
4234 | static void bp_perf_event_destroy(struct perf_event *event) | ||
4235 | { | ||
4236 | release_bp_slot(event); | ||
4237 | } | ||
4238 | |||
4239 | static const struct pmu *bp_perf_event_init(struct perf_event *bp) | ||
4240 | { | ||
4241 | int err; | ||
4242 | /* | ||
4243 | * The breakpoint is already filled if we haven't created the counter | ||
4244 | * through perf syscall | ||
4245 | * FIXME: manage to get trigerred to NULL if it comes from syscalls | ||
4246 | */ | ||
4247 | if (!bp->callback) | ||
4248 | err = register_perf_hw_breakpoint(bp); | ||
4249 | else | ||
4250 | err = __register_perf_hw_breakpoint(bp); | ||
4251 | if (err) | ||
4252 | return ERR_PTR(err); | ||
4253 | |||
4254 | bp->destroy = bp_perf_event_destroy; | ||
4255 | |||
4256 | return &perf_ops_bp; | ||
4257 | } | ||
4258 | |||
4259 | void perf_bp_event(struct perf_event *bp, void *regs) | ||
4260 | { | ||
4261 | /* TODO */ | ||
4262 | } | ||
4263 | #else | ||
4264 | static void bp_perf_event_destroy(struct perf_event *event) | ||
4265 | { | ||
4266 | } | ||
4267 | |||
4268 | static const struct pmu *bp_perf_event_init(struct perf_event *bp) | ||
4269 | { | ||
4270 | return NULL; | ||
4271 | } | ||
4272 | |||
4273 | void perf_bp_event(struct perf_event *bp, void *regs) | ||
4274 | { | ||
4275 | } | ||
4276 | #endif | ||
4277 | |||
4232 | atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; | 4278 | atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; |
4233 | 4279 | ||
4234 | static void sw_perf_event_destroy(struct perf_event *event) | 4280 | static void sw_perf_event_destroy(struct perf_event *event) |
@@ -4375,6 +4421,11 @@ perf_event_alloc(struct perf_event_attr *attr, | |||
4375 | pmu = tp_perf_event_init(event); | 4421 | pmu = tp_perf_event_init(event); |
4376 | break; | 4422 | break; |
4377 | 4423 | ||
4424 | case PERF_TYPE_BREAKPOINT: | ||
4425 | pmu = bp_perf_event_init(event); | ||
4426 | break; | ||
4427 | |||
4428 | |||
4378 | default: | 4429 | default: |
4379 | break; | 4430 | break; |
4380 | } | 4431 | } |
@@ -4686,7 +4737,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, | |||
4686 | 4737 | ||
4687 | ctx = find_get_context(pid, cpu); | 4738 | ctx = find_get_context(pid, cpu); |
4688 | if (IS_ERR(ctx)) | 4739 | if (IS_ERR(ctx)) |
4689 | return NULL ; | 4740 | return NULL; |
4690 | 4741 | ||
4691 | event = perf_event_alloc(attr, cpu, ctx, NULL, | 4742 | event = perf_event_alloc(attr, cpu, ctx, NULL, |
4692 | NULL, callback, GFP_KERNEL); | 4743 | NULL, callback, GFP_KERNEL); |