diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-11-23 09:42:34 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-23 12:18:31 -0500 |
commit | f5ffe02e5046003ae7e2ce70d3d1c2a73331268b (patch) | |
tree | ed300505d80941e2ea95746f65a1b9eacfd4562f /kernel/perf_event.c | |
parent | fdf6bc95229821e3d9405eba28925b76e92b74d0 (diff) |
perf: Add kernel side syscall events support for breakpoints
Add the remaining necessary bits to support breakpoints created
through perf syscall.
We don't use the software counter interface as:
- We don't need to check against recursion, this is already done
in hardware breakpoints arch level.
- We already know the perf event we are dealing with when the
event is to be committed.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Prasad <prasad@linux.vnet.ibm.com>
LKML-Reference: <1258987355-8751-3-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 0aafe85362fd..9425c9600c89 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -3831,6 +3831,20 @@ static int perf_swevent_is_counting(struct perf_event *event) | |||
3831 | static int perf_tp_event_match(struct perf_event *event, | 3831 | static int perf_tp_event_match(struct perf_event *event, |
3832 | struct perf_sample_data *data); | 3832 | struct perf_sample_data *data); |
3833 | 3833 | ||
3834 | static int perf_exclude_event(struct perf_event *event, | ||
3835 | struct pt_regs *regs) | ||
3836 | { | ||
3837 | if (regs) { | ||
3838 | if (event->attr.exclude_user && user_mode(regs)) | ||
3839 | return 1; | ||
3840 | |||
3841 | if (event->attr.exclude_kernel && !user_mode(regs)) | ||
3842 | return 1; | ||
3843 | } | ||
3844 | |||
3845 | return 0; | ||
3846 | } | ||
3847 | |||
3834 | static int perf_swevent_match(struct perf_event *event, | 3848 | static int perf_swevent_match(struct perf_event *event, |
3835 | enum perf_type_id type, | 3849 | enum perf_type_id type, |
3836 | u32 event_id, | 3850 | u32 event_id, |
@@ -3842,16 +3856,12 @@ static int perf_swevent_match(struct perf_event *event, | |||
3842 | 3856 | ||
3843 | if (event->attr.type != type) | 3857 | if (event->attr.type != type) |
3844 | return 0; | 3858 | return 0; |
3859 | |||
3845 | if (event->attr.config != event_id) | 3860 | if (event->attr.config != event_id) |
3846 | return 0; | 3861 | return 0; |
3847 | 3862 | ||
3848 | if (regs) { | 3863 | if (perf_exclude_event(event, regs)) |
3849 | if (event->attr.exclude_user && user_mode(regs)) | 3864 | return 0; |
3850 | return 0; | ||
3851 | |||
3852 | if (event->attr.exclude_kernel && !user_mode(regs)) | ||
3853 | return 0; | ||
3854 | } | ||
3855 | 3865 | ||
3856 | if (event->attr.type == PERF_TYPE_TRACEPOINT && | 3866 | if (event->attr.type == PERF_TYPE_TRACEPOINT && |
3857 | !perf_tp_event_match(event, data)) | 3867 | !perf_tp_event_match(event, data)) |
@@ -4282,9 +4292,15 @@ static const struct pmu *bp_perf_event_init(struct perf_event *bp) | |||
4282 | return &perf_ops_bp; | 4292 | return &perf_ops_bp; |
4283 | } | 4293 | } |
4284 | 4294 | ||
4285 | void perf_bp_event(struct perf_event *bp, void *regs) | 4295 | void perf_bp_event(struct perf_event *bp, void *data) |
4286 | { | 4296 | { |
4287 | /* TODO */ | 4297 | struct perf_sample_data sample; |
4298 | struct pt_regs *regs = data; | ||
4299 | |||
4300 | sample.addr = bp->attr.bp_addr; | ||
4301 | |||
4302 | if (!perf_exclude_event(bp, regs)) | ||
4303 | perf_swevent_add(bp, 1, 1, &sample, regs); | ||
4288 | } | 4304 | } |
4289 | #else | 4305 | #else |
4290 | static void bp_perf_event_destroy(struct perf_event *event) | 4306 | static void bp_perf_event_destroy(struct perf_event *event) |