aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/hw_breakpoint.h243
-rw-r--r--include/linux/perf_event.h26
2 files changed, 144 insertions, 125 deletions
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index 61ccc8f17eac..7eba9b92e5f3 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h
@@ -1,136 +1,131 @@
1#ifndef _LINUX_HW_BREAKPOINT_H 1#ifndef _LINUX_HW_BREAKPOINT_H
2#define _LINUX_HW_BREAKPOINT_H 2#define _LINUX_HW_BREAKPOINT_H
3 3
4#include <linux/perf_event.h>
4 5
5#ifdef __KERNEL__ 6enum {
6#include <linux/list.h> 7 HW_BREAKPOINT_LEN_1 = 1,
7#include <linux/types.h> 8 HW_BREAKPOINT_LEN_2 = 2,
8#include <linux/kallsyms.h> 9 HW_BREAKPOINT_LEN_4 = 4,
9 10 HW_BREAKPOINT_LEN_8 = 8,
10/**
11 * struct hw_breakpoint - unified kernel/user-space hardware breakpoint
12 * @triggered: callback invoked after target address access
13 * @info: arch-specific breakpoint info (address, length, and type)
14 *
15 * %hw_breakpoint structures are the kernel's way of representing
16 * hardware breakpoints. These are data breakpoints
17 * (also known as "watchpoints", triggered on data access), and the breakpoint's
18 * target address can be located in either kernel space or user space.
19 *
20 * The breakpoint's address, length, and type are highly
21 * architecture-specific. The values are encoded in the @info field; you
22 * specify them when registering the breakpoint. To examine the encoded
23 * values use hw_breakpoint_get_{kaddress,uaddress,len,type}(), declared
24 * below.
25 *
26 * The address is specified as a regular kernel pointer (for kernel-space
27 * breakponts) or as an %__user pointer (for user-space breakpoints).
28 * With register_user_hw_breakpoint(), the address must refer to a
29 * location in user space. The breakpoint will be active only while the
30 * requested task is running. Conversely with
31 * register_kernel_hw_breakpoint(), the address must refer to a location
32 * in kernel space, and the breakpoint will be active on all CPUs
33 * regardless of the current task.
34 *
35 * The length is the breakpoint's extent in bytes, which is subject to
36 * certain limitations. include/asm/hw_breakpoint.h contains macros
37 * defining the available lengths for a specific architecture. Note that
38 * the address's alignment must match the length. The breakpoint will
39 * catch accesses to any byte in the range from address to address +
40 * (length - 1).
41 *
42 * The breakpoint's type indicates the sort of access that will cause it
43 * to trigger. Possible values may include:
44 *
45 * %HW_BREAKPOINT_RW (triggered on read or write access),
46 * %HW_BREAKPOINT_WRITE (triggered on write access), and
47 * %HW_BREAKPOINT_READ (triggered on read access).
48 *
49 * Appropriate macros are defined in include/asm/hw_breakpoint.h; not all
50 * possibilities are available on all architectures. Execute breakpoints
51 * must have length equal to the special value %HW_BREAKPOINT_LEN_EXECUTE.
52 *
53 * When a breakpoint gets hit, the @triggered callback is
54 * invoked in_interrupt with a pointer to the %hw_breakpoint structure and the
55 * processor registers.
56 * Data breakpoints occur after the memory access has taken place.
57 * Breakpoints are disabled during execution @triggered, to avoid
58 * recursive traps and allow unhindered access to breakpointed memory.
59 *
60 * This sample code sets a breakpoint on pid_max and registers a callback
61 * function for writes to that variable. Note that it is not portable
62 * as written, because not all architectures support HW_BREAKPOINT_LEN_4.
63 *
64 * ----------------------------------------------------------------------
65 *
66 * #include <asm/hw_breakpoint.h>
67 *
68 * struct hw_breakpoint my_bp;
69 *
70 * static void my_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
71 * {
72 * printk(KERN_DEBUG "Inside triggered routine of breakpoint exception\n");
73 * dump_stack();
74 * .......<more debugging output>........
75 * }
76 *
77 * static struct hw_breakpoint my_bp;
78 *
79 * static int init_module(void)
80 * {
81 * ..........<do anything>............
82 * my_bp.info.type = HW_BREAKPOINT_WRITE;
83 * my_bp.info.len = HW_BREAKPOINT_LEN_4;
84 *
85 * my_bp.installed = (void *)my_bp_installed;
86 *
87 * rc = register_kernel_hw_breakpoint(&my_bp);
88 * ..........<do anything>............
89 * }
90 *
91 * static void cleanup_module(void)
92 * {
93 * ..........<do anything>............
94 * unregister_kernel_hw_breakpoint(&my_bp);
95 * ..........<do anything>............
96 * }
97 *
98 * ----------------------------------------------------------------------
99 */
100struct hw_breakpoint {
101 void (*triggered)(struct hw_breakpoint *, struct pt_regs *);
102 struct arch_hw_breakpoint info;
103}; 11};
104 12
105/* 13enum {
106 * len and type values are defined in include/asm/hw_breakpoint.h. 14 HW_BREAKPOINT_R = 1,
107 * Available values vary according to the architecture. On i386 the 15 HW_BREAKPOINT_W = 2,
108 * possibilities are: 16 HW_BREAKPOINT_X = 4,
109 * 17};
110 * HW_BREAKPOINT_LEN_1 18
111 * HW_BREAKPOINT_LEN_2 19static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
112 * HW_BREAKPOINT_LEN_4 20{
113 * HW_BREAKPOINT_RW 21 return &bp->hw.info;
114 * HW_BREAKPOINT_READ 22}
115 * 23
116 * On other architectures HW_BREAKPOINT_LEN_8 may be available, and the 24static inline unsigned long hw_breakpoint_addr(struct perf_event *bp)
117 * 1-, 2-, and 4-byte lengths may be unavailable. There also may be 25{
118 * HW_BREAKPOINT_WRITE. You can use #ifdef to check at compile time. 26 return bp->attr.bp_addr;
119 */ 27}
28
29static inline int hw_breakpoint_type(struct perf_event *bp)
30{
31 return bp->attr.bp_type;
32}
33
34static inline int hw_breakpoint_len(struct perf_event *bp)
35{
36 return bp->attr.bp_len;
37}
38
39#ifdef CONFIG_HAVE_HW_BREAKPOINT
40extern struct perf_event *
41register_user_hw_breakpoint(unsigned long addr,
42 int len,
43 int type,
44 perf_callback_t triggered,
45 struct task_struct *tsk,
46 bool active);
47
48/* FIXME: only change from the attr, and don't unregister */
49extern struct perf_event *
50modify_user_hw_breakpoint(struct perf_event *bp,
51 unsigned long addr,
52 int len,
53 int type,
54 perf_callback_t triggered,
55 struct task_struct *tsk,
56 bool active);
120 57
121extern int register_user_hw_breakpoint(struct task_struct *tsk,
122 struct hw_breakpoint *bp);
123extern int modify_user_hw_breakpoint(struct task_struct *tsk,
124 struct hw_breakpoint *bp);
125extern void unregister_user_hw_breakpoint(struct task_struct *tsk,
126 struct hw_breakpoint *bp);
127/* 58/*
128 * Kernel breakpoints are not associated with any particular thread. 59 * Kernel breakpoints are not associated with any particular thread.
129 */ 60 */
130extern int register_kernel_hw_breakpoint(struct hw_breakpoint *bp); 61extern struct perf_event *
131extern void unregister_kernel_hw_breakpoint(struct hw_breakpoint *bp); 62register_wide_hw_breakpoint_cpu(unsigned long addr,
63 int len,
64 int type,
65 perf_callback_t triggered,
66 int cpu,
67 bool active);
68
69extern struct perf_event **
70register_wide_hw_breakpoint(unsigned long addr,
71 int len,
72 int type,
73 perf_callback_t triggered,
74 bool active);
75
76extern int register_perf_hw_breakpoint(struct perf_event *bp);
77extern int __register_perf_hw_breakpoint(struct perf_event *bp);
78extern void unregister_hw_breakpoint(struct perf_event *bp);
79extern void unregister_wide_hw_breakpoint(struct perf_event **cpu_events);
80
81extern int reserve_bp_slot(struct perf_event *bp);
82extern void release_bp_slot(struct perf_event *bp);
83
84extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
85
86#else /* !CONFIG_HAVE_HW_BREAKPOINT */
87
88static inline struct perf_event *
89register_user_hw_breakpoint(unsigned long addr,
90 int len,
91 int type,
92 perf_callback_t triggered,
93 struct task_struct *tsk,
94 bool active) { return NULL; }
95static inline struct perf_event *
96modify_user_hw_breakpoint(struct perf_event *bp,
97 unsigned long addr,
98 int len,
99 int type,
100 perf_callback_t triggered,
101 struct task_struct *tsk,
102 bool active) { return NULL; }
103static inline struct perf_event *
104register_wide_hw_breakpoint_cpu(unsigned long addr,
105 int len,
106 int type,
107 perf_callback_t triggered,
108 int cpu,
109 bool active) { return NULL; }
110static inline struct perf_event **
111register_wide_hw_breakpoint(unsigned long addr,
112 int len,
113 int type,
114 perf_callback_t triggered,
115 bool active) { return NULL; }
116static inline int
117register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
118static inline int
119__register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
120static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
121static inline void
122unregister_wide_hw_breakpoint(struct perf_event **cpu_events) { }
123static inline int
124reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
125static inline void release_bp_slot(struct perf_event *bp) { }
126
127static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { }
132 128
133extern unsigned int hbp_kernel_pos; 129#endif /* CONFIG_HAVE_HW_BREAKPOINT */
134 130
135#endif /* __KERNEL__ */ 131#endif /* _LINUX_HW_BREAKPOINT_H */
136#endif /* _LINUX_HW_BREAKPOINT_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 8d54e6d25eeb..cead64ea6c15 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};
@@ -207,6 +212,15 @@ struct perf_event_attr {
207 __u32 wakeup_events; /* wakeup every n events */ 212 __u32 wakeup_events; /* wakeup every n events */
208 __u32 wakeup_watermark; /* bytes before wakeup */ 213 __u32 wakeup_watermark; /* bytes before wakeup */
209 }; 214 };
215
216 union {
217 struct { /* Hardware breakpoint info */
218 __u64 bp_addr;
219 __u32 bp_type;
220 __u32 bp_len;
221 };
222 };
223
210 __u32 __reserved_2; 224 __u32 __reserved_2;
211 225
212 __u64 __reserved_3; 226 __u64 __reserved_3;
@@ -476,6 +490,11 @@ struct hw_perf_event {
476 atomic64_t count; 490 atomic64_t count;
477 struct hrtimer hrtimer; 491 struct hrtimer hrtimer;
478 }; 492 };
493#ifdef CONFIG_HAVE_HW_BREAKPOINT
494 union { /* breakpoint */
495 struct arch_hw_breakpoint info;
496 };
497#endif
479 }; 498 };
480 atomic64_t prev_count; 499 atomic64_t prev_count;
481 u64 sample_period; 500 u64 sample_period;
@@ -588,7 +607,7 @@ struct perf_event {
588 u64 tstamp_running; 607 u64 tstamp_running;
589 u64 tstamp_stopped; 608 u64 tstamp_stopped;
590 609
591 struct perf_event_attr attr; 610 struct perf_event_attr attr;
592 struct hw_perf_event hw; 611 struct hw_perf_event hw;
593 612
594 struct perf_event_context *ctx; 613 struct perf_event_context *ctx;
@@ -643,6 +662,8 @@ struct perf_event {
643 662
644 perf_callback_t callback; 663 perf_callback_t callback;
645 664
665 perf_callback_t event_callback;
666
646#endif /* CONFIG_PERF_EVENTS */ 667#endif /* CONFIG_PERF_EVENTS */
647}; 668};
648 669
@@ -831,6 +852,7 @@ extern int sysctl_perf_event_sample_rate;
831extern void perf_event_init(void); 852extern void perf_event_init(void);
832extern void perf_tp_event(int event_id, u64 addr, u64 count, 853extern void perf_tp_event(int event_id, u64 addr, u64 count,
833 void *record, int entry_size); 854 void *record, int entry_size);
855extern void perf_bp_event(struct perf_event *event, void *data);
834 856
835#ifndef perf_misc_flags 857#ifndef perf_misc_flags
836#define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \ 858#define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \
@@ -865,6 +887,8 @@ static inline int perf_event_task_enable(void) { return -EINVAL; }
865static inline void 887static inline void
866perf_sw_event(u32 event_id, u64 nr, int nmi, 888perf_sw_event(u32 event_id, u64 nr, int nmi,
867 struct pt_regs *regs, u64 addr) { } 889 struct pt_regs *regs, u64 addr) { }
890static inline void
891perf_bp_event(struct perf_event *event, void *data) { }
868 892
869static inline void perf_event_mmap(struct vm_area_struct *vma) { } 893static inline void perf_event_mmap(struct vm_area_struct *vma) { }
870static inline void perf_event_comm(struct task_struct *tsk) { } 894static inline void perf_event_comm(struct task_struct *tsk) { }