blob: 7e8899093098c36acff83943ca7fc5565b4e4056 [file] [log] [blame]
Frederic Weisbecker2da3e162009-11-05 23:06:50 +01001#ifndef _LINUX_HW_BREAKPOINT_H
2#define _LINUX_HW_BREAKPOINT_H
K.Prasadb3328282009-06-01 23:43:10 +05303
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +02004enum {
5 HW_BREAKPOINT_LEN_1 = 1,
6 HW_BREAKPOINT_LEN_2 = 2,
7 HW_BREAKPOINT_LEN_4 = 4,
8 HW_BREAKPOINT_LEN_8 = 8,
K.Prasadb3328282009-06-01 23:43:10 +05309};
10
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020011enum {
Frederic Weisbecker01027522010-04-11 18:55:56 +020012 HW_BREAKPOINT_EMPTY = 0,
13 HW_BREAKPOINT_R = 1,
14 HW_BREAKPOINT_W = 2,
15 HW_BREAKPOINT_RW = HW_BREAKPOINT_R | HW_BREAKPOINT_W,
16 HW_BREAKPOINT_X = 4,
17 HW_BREAKPOINT_INVALID = HW_BREAKPOINT_RW | HW_BREAKPOINT_X,
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020018};
K.Prasadb3328282009-06-01 23:43:10 +053019
Frederic Weisbecker5093eba2009-11-22 05:21:35 +010020#ifdef __KERNEL__
Ingo Molnar688bcaf2009-11-14 01:12:47 +010021
Frederic Weisbeckere6db4872009-11-23 15:42:32 +010022#include <linux/perf_event.h>
23
Frederic Weisbeckerfa7c27e2009-11-23 22:30:12 +010024#ifdef CONFIG_HAVE_HW_BREAKPOINT
25
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +010026static inline void hw_breakpoint_init(struct perf_event_attr *attr)
27{
Frederic Weisbeckered872d02009-12-07 03:14:17 +010028 memset(attr, 0, sizeof(*attr));
29
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +010030 attr->type = PERF_TYPE_BREAKPOINT;
31 attr->size = sizeof(*attr);
Frederic Weisbeckerb326e952009-12-05 09:44:31 +010032 /*
33 * As it's for in-kernel or ptrace use, we want it to be pinned
34 * and to call its callback every hits.
35 */
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +010036 attr->pinned = 1;
Frederic Weisbeckerb326e952009-12-05 09:44:31 +010037 attr->sample_period = 1;
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +010038}
39
Frederic Weisbecker73266fc2010-04-22 05:05:45 +020040static inline void ptrace_breakpoint_init(struct perf_event_attr *attr)
41{
42 hw_breakpoint_init(attr);
43 attr->exclude_kernel = 1;
44}
45
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020046static inline unsigned long hw_breakpoint_addr(struct perf_event *bp)
47{
48 return bp->attr.bp_addr;
49}
50
51static inline int hw_breakpoint_type(struct perf_event *bp)
52{
53 return bp->attr.bp_type;
54}
55
Mahesh Salgaonkarcd757642010-01-30 10:25:18 +053056static inline unsigned long hw_breakpoint_len(struct perf_event *bp)
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020057{
58 return bp->attr.bp_len;
59}
60
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020061extern struct perf_event *
Frederic Weisbecker5fa10b22009-11-27 04:55:53 +010062register_user_hw_breakpoint(struct perf_event_attr *attr,
Frederic Weisbeckerb326e952009-12-05 09:44:31 +010063 perf_overflow_handler_t triggered,
Frederic Weisbecker5fa10b22009-11-27 04:55:53 +010064 struct task_struct *tsk);
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020065
66/* FIXME: only change from the attr, and don't unregister */
Frederic Weisbecker44234ad2009-12-09 09:25:48 +010067extern int
Frederic Weisbecker2f0993e2009-12-05 07:06:10 +010068modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr);
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020069
K.Prasadb3328282009-06-01 23:43:10 +053070/*
71 * Kernel breakpoints are not associated with any particular thread.
72 */
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020073extern struct perf_event *
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +010074register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
Frederic Weisbeckerb326e952009-12-05 09:44:31 +010075 perf_overflow_handler_t triggered,
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +010076 int cpu);
K.Prasadb3328282009-06-01 23:43:10 +053077
Tejun Heo44ee6352010-02-17 10:50:50 +090078extern struct perf_event * __percpu *
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +010079register_wide_hw_breakpoint(struct perf_event_attr *attr,
Frederic Weisbeckerb326e952009-12-05 09:44:31 +010080 perf_overflow_handler_t triggered);
K.Prasadb3328282009-06-01 23:43:10 +053081
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020082extern int register_perf_hw_breakpoint(struct perf_event *bp);
83extern int __register_perf_hw_breakpoint(struct perf_event *bp);
84extern void unregister_hw_breakpoint(struct perf_event *bp);
Tejun Heo44ee6352010-02-17 10:50:50 +090085extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020086
Jason Wessel5352ae62010-01-28 17:04:43 -060087extern int dbg_reserve_bp_slot(struct perf_event *bp);
88extern int dbg_release_bp_slot(struct perf_event *bp);
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020089extern int reserve_bp_slot(struct perf_event *bp);
90extern void release_bp_slot(struct perf_event *bp);
91
92extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
93
Frederic Weisbecker687b16f2009-11-13 13:16:15 +010094static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
95{
96 return &bp->hw.info;
97}
98
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +020099#else /* !CONFIG_HAVE_HW_BREAKPOINT */
100
101static inline struct perf_event *
Frederic Weisbecker5fa10b22009-11-27 04:55:53 +0100102register_user_hw_breakpoint(struct perf_event_attr *attr,
Frederic Weisbeckerb326e952009-12-05 09:44:31 +0100103 perf_overflow_handler_t triggered,
Frederic Weisbecker5fa10b22009-11-27 04:55:53 +0100104 struct task_struct *tsk) { return NULL; }
Frederic Weisbecker44234ad2009-12-09 09:25:48 +0100105static inline int
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +0200106modify_user_hw_breakpoint(struct perf_event *bp,
Frederic Weisbecker99ac64c2009-12-11 11:58:42 +0100107 struct perf_event_attr *attr) { return -ENOSYS; }
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +0200108static inline struct perf_event *
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +0100109register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
Frederic Weisbeckerb326e952009-12-05 09:44:31 +0100110 perf_overflow_handler_t triggered,
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +0100111 int cpu) { return NULL; }
Tejun Heo44ee6352010-02-17 10:50:50 +0900112static inline struct perf_event * __percpu *
Frederic Weisbeckerdd1853c2009-11-27 04:55:54 +0100113register_wide_hw_breakpoint(struct perf_event_attr *attr,
Frederic Weisbeckerb326e952009-12-05 09:44:31 +0100114 perf_overflow_handler_t triggered) { return NULL; }
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +0200115static inline int
116register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
117static inline int
118__register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
119static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
120static inline void
Tejun Heo44ee6352010-02-17 10:50:50 +0900121unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) { }
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +0200122static inline int
123reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
124static inline void release_bp_slot(struct perf_event *bp) { }
125
126static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { }
127
Frederic Weisbecker687b16f2009-11-13 13:16:15 +0100128static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
129{
130 return NULL;
131}
132
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +0200133#endif /* CONFIG_HAVE_HW_BREAKPOINT */
Frederic Weisbecker5093eba2009-11-22 05:21:35 +0100134#endif /* __KERNEL__ */
Frederic Weisbecker24f1e32c2009-09-09 19:22:48 +0200135
136#endif /* _LINUX_HW_BREAKPOINT_H */