aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-11-21 08:07:23 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-21 08:07:23 -0500
commit96200591a34f8ecb98481c626125df43a2463b55 (patch)
tree314c376b01f254d04f9aaf449b1f9147ad177fa6 /include
parent7031281e02bf951a2259849217193fb9d75a9762 (diff)
parent68efa37df779b3e04280598e8b5b3a1919b65fee (diff)
Merge branch 'tracing/hw-breakpoints' into perf/core
Conflicts: arch/x86/kernel/kprobes.c kernel/trace/Makefile Merge reason: hw-breakpoints perf integration is looking good in testing and in reviews, plus conflicts are mounting up - so merge & resolve. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r--include/linux/hw_breakpoint.h137
-rw-r--r--include/linux/perf_event.h37
2 files changed, 173 insertions, 1 deletions
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
new file mode 100644
index 000000000000..0b98cbf76da7
--- /dev/null
+++ b/include/linux/hw_breakpoint.h
@@ -0,0 +1,137 @@
1#ifndef _LINUX_HW_BREAKPOINT_H
2#define _LINUX_HW_BREAKPOINT_H
3
4#include <linux/perf_event.h>
5
6enum {
7 HW_BREAKPOINT_LEN_1 = 1,
8 HW_BREAKPOINT_LEN_2 = 2,
9 HW_BREAKPOINT_LEN_4 = 4,
10 HW_BREAKPOINT_LEN_8 = 8,
11};
12
13enum {
14 HW_BREAKPOINT_R = 1,
15 HW_BREAKPOINT_W = 2,
16 HW_BREAKPOINT_X = 4,
17};
18
19#ifdef CONFIG_HAVE_HW_BREAKPOINT
20
21static inline unsigned long hw_breakpoint_addr(struct perf_event *bp)
22{
23 return bp->attr.bp_addr;
24}
25
26static inline int hw_breakpoint_type(struct perf_event *bp)
27{
28 return bp->attr.bp_type;
29}
30
31static inline int hw_breakpoint_len(struct perf_event *bp)
32{
33 return bp->attr.bp_len;
34}
35
36extern struct perf_event *
37register_user_hw_breakpoint(unsigned long addr,
38 int len,
39 int type,
40 perf_callback_t triggered,
41 struct task_struct *tsk,
42 bool active);
43
44/* FIXME: only change from the attr, and don't unregister */
45extern struct perf_event *
46modify_user_hw_breakpoint(struct perf_event *bp,
47 unsigned long addr,
48 int len,
49 int type,
50 perf_callback_t triggered,
51 struct task_struct *tsk,
52 bool active);
53
54/*
55 * Kernel breakpoints are not associated with any particular thread.
56 */
57extern struct perf_event *
58register_wide_hw_breakpoint_cpu(unsigned long addr,
59 int len,
60 int type,
61 perf_callback_t triggered,
62 int cpu,
63 bool active);
64
65extern struct perf_event **
66register_wide_hw_breakpoint(unsigned long addr,
67 int len,
68 int type,
69 perf_callback_t triggered,
70 bool active);
71
72extern int register_perf_hw_breakpoint(struct perf_event *bp);
73extern int __register_perf_hw_breakpoint(struct perf_event *bp);
74extern void unregister_hw_breakpoint(struct perf_event *bp);
75extern void unregister_wide_hw_breakpoint(struct perf_event **cpu_events);
76
77extern int reserve_bp_slot(struct perf_event *bp);
78extern void release_bp_slot(struct perf_event *bp);
79
80extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
81
82static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
83{
84 return &bp->hw.info;
85}
86
87#else /* !CONFIG_HAVE_HW_BREAKPOINT */
88
89static inline struct perf_event *
90register_user_hw_breakpoint(unsigned long addr,
91 int len,
92 int type,
93 perf_callback_t triggered,
94 struct task_struct *tsk,
95 bool active) { return NULL; }
96static inline struct perf_event *
97modify_user_hw_breakpoint(struct perf_event *bp,
98 unsigned long addr,
99 int len,
100 int type,
101 perf_callback_t triggered,
102 struct task_struct *tsk,
103 bool active) { return NULL; }
104static inline struct perf_event *
105register_wide_hw_breakpoint_cpu(unsigned long addr,
106 int len,
107 int type,
108 perf_callback_t triggered,
109 int cpu,
110 bool active) { return NULL; }
111static inline struct perf_event **
112register_wide_hw_breakpoint(unsigned long addr,
113 int len,
114 int type,
115 perf_callback_t triggered,
116 bool active) { return NULL; }
117static inline int
118register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
119static inline int
120__register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
121static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
122static inline void
123unregister_wide_hw_breakpoint(struct perf_event **cpu_events) { }
124static inline int
125reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
126static inline void release_bp_slot(struct perf_event *bp) { }
127
128static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { }
129
130static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
131{
132 return NULL;
133}
134
135#endif /* CONFIG_HAVE_HW_BREAKPOINT */
136
137#endif /* _LINUX_HW_BREAKPOINT_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7f87563c8485..b5cdac0de370 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -18,6 +18,10 @@
18#include <linux/ioctl.h> 18#include <linux/ioctl.h>
19#include <asm/byteorder.h> 19#include <asm/byteorder.h>
20 20
21#ifdef CONFIG_HAVE_HW_BREAKPOINT
22#include <asm/hw_breakpoint.h>
23#endif
24
21/* 25/*
22 * User-space ABI bits: 26 * User-space ABI bits:
23 */ 27 */
@@ -31,6 +35,7 @@ enum perf_type_id {
31 PERF_TYPE_TRACEPOINT = 2, 35 PERF_TYPE_TRACEPOINT = 2,
32 PERF_TYPE_HW_CACHE = 3, 36 PERF_TYPE_HW_CACHE = 3,
33 PERF_TYPE_RAW = 4, 37 PERF_TYPE_RAW = 4,
38 PERF_TYPE_BREAKPOINT = 5,
34 39
35 PERF_TYPE_MAX, /* non-ABI */ 40 PERF_TYPE_MAX, /* non-ABI */
36}; 41};
@@ -209,6 +214,15 @@ struct perf_event_attr {
209 __u32 wakeup_events; /* wakeup every n events */ 214 __u32 wakeup_events; /* wakeup every n events */
210 __u32 wakeup_watermark; /* bytes before wakeup */ 215 __u32 wakeup_watermark; /* bytes before wakeup */
211 }; 216 };
217
218 union {
219 struct { /* Hardware breakpoint info */
220 __u64 bp_addr;
221 __u32 bp_type;
222 __u32 bp_len;
223 };
224 };
225
212 __u32 __reserved_2; 226 __u32 __reserved_2;
213 227
214 __u64 __reserved_3; 228 __u64 __reserved_3;
@@ -478,6 +492,11 @@ struct hw_perf_event {
478 s64 remaining; 492 s64 remaining;
479 struct hrtimer hrtimer; 493 struct hrtimer hrtimer;
480 }; 494 };
495#ifdef CONFIG_HAVE_HW_BREAKPOINT
496 union { /* breakpoint */
497 struct arch_hw_breakpoint info;
498 };
499#endif
481 }; 500 };
482 atomic64_t prev_count; 501 atomic64_t prev_count;
483 u64 sample_period; 502 u64 sample_period;
@@ -546,6 +565,8 @@ struct perf_pending_entry {
546 void (*func)(struct perf_pending_entry *); 565 void (*func)(struct perf_pending_entry *);
547}; 566};
548 567
568typedef void (*perf_callback_t)(struct perf_event *, void *);
569
549/** 570/**
550 * struct perf_event - performance event kernel representation: 571 * struct perf_event - performance event kernel representation:
551 */ 572 */
@@ -588,7 +609,7 @@ struct perf_event {
588 u64 tstamp_running; 609 u64 tstamp_running;
589 u64 tstamp_stopped; 610 u64 tstamp_stopped;
590 611
591 struct perf_event_attr attr; 612 struct perf_event_attr attr;
592 struct hw_perf_event hw; 613 struct hw_perf_event hw;
593 614
594 struct perf_event_context *ctx; 615 struct perf_event_context *ctx;
@@ -641,6 +662,10 @@ struct perf_event {
641 struct event_filter *filter; 662 struct event_filter *filter;
642#endif 663#endif
643 664
665 perf_callback_t callback;
666
667 perf_callback_t event_callback;
668
644#endif /* CONFIG_PERF_EVENTS */ 669#endif /* CONFIG_PERF_EVENTS */
645}; 670};
646 671
@@ -745,6 +770,13 @@ extern int hw_perf_group_sched_in(struct perf_event *group_leader,
745 struct perf_cpu_context *cpuctx, 770 struct perf_cpu_context *cpuctx,
746 struct perf_event_context *ctx, int cpu); 771 struct perf_event_context *ctx, int cpu);
747extern void perf_event_update_userpage(struct perf_event *event); 772extern void perf_event_update_userpage(struct perf_event *event);
773extern int perf_event_release_kernel(struct perf_event *event);
774extern struct perf_event *
775perf_event_create_kernel_counter(struct perf_event_attr *attr,
776 int cpu,
777 pid_t pid,
778 perf_callback_t callback);
779extern u64 perf_event_read_value(struct perf_event *event);
748 780
749struct perf_sample_data { 781struct perf_sample_data {
750 u64 type; 782 u64 type;
@@ -821,6 +853,7 @@ extern int sysctl_perf_event_sample_rate;
821extern void perf_event_init(void); 853extern void perf_event_init(void);
822extern void perf_tp_event(int event_id, u64 addr, u64 count, 854extern void perf_tp_event(int event_id, u64 addr, u64 count,
823 void *record, int entry_size); 855 void *record, int entry_size);
856extern void perf_bp_event(struct perf_event *event, void *data);
824 857
825#ifndef perf_misc_flags 858#ifndef perf_misc_flags
826#define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \ 859#define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \
@@ -855,6 +888,8 @@ static inline int perf_event_task_enable(void) { return -EINVAL; }
855static inline void 888static inline void
856perf_sw_event(u32 event_id, u64 nr, int nmi, 889perf_sw_event(u32 event_id, u64 nr, int nmi,
857 struct pt_regs *regs, u64 addr) { } 890 struct pt_regs *regs, u64 addr) { }
891static inline void
892perf_bp_event(struct perf_event *event, void *data) { }
858 893
859static inline void perf_event_mmap(struct vm_area_struct *vma) { } 894static inline void perf_event_mmap(struct vm_area_struct *vma) { }
860static inline void perf_event_comm(struct task_struct *tsk) { } 895static inline void perf_event_comm(struct task_struct *tsk) { }