Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2da3e160 FW |
2 | #ifndef _LINUX_HW_BREAKPOINT_H |
3 | #define _LINUX_HW_BREAKPOINT_H | |
b332828c | 4 | |
e6db4876 | 5 | #include <linux/perf_event.h> |
d2709c7c | 6 | #include <uapi/linux/hw_breakpoint.h> |
e6db4876 | 7 | |
fa7c27ee FW |
8 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
9 | ||
3c502e7a JW |
10 | extern int __init init_hw_breakpoint(void); |
11 | ||
dd1853c3 FW |
12 | static inline void hw_breakpoint_init(struct perf_event_attr *attr) |
13 | { | |
ed872d09 FW |
14 | memset(attr, 0, sizeof(*attr)); |
15 | ||
dd1853c3 FW |
16 | attr->type = PERF_TYPE_BREAKPOINT; |
17 | attr->size = sizeof(*attr); | |
b326e956 FW |
18 | /* |
19 | * As it's for in-kernel or ptrace use, we want it to be pinned | |
20 | * and to call its callback every hits. | |
21 | */ | |
dd1853c3 | 22 | attr->pinned = 1; |
b326e956 | 23 | attr->sample_period = 1; |
73266fc1 FW |
24 | } |
25 | ||
26 | static inline void ptrace_breakpoint_init(struct perf_event_attr *attr) | |
27 | { | |
28 | hw_breakpoint_init(attr); | |
29 | attr->exclude_kernel = 1; | |
dd1853c3 FW |
30 | } |
31 | ||
24f1e32c FW |
32 | static inline unsigned long hw_breakpoint_addr(struct perf_event *bp) |
33 | { | |
34 | return bp->attr.bp_addr; | |
35 | } | |
36 | ||
37 | static inline int hw_breakpoint_type(struct perf_event *bp) | |
38 | { | |
39 | return bp->attr.bp_type; | |
40 | } | |
41 | ||
cd757645 | 42 | static inline unsigned long hw_breakpoint_len(struct perf_event *bp) |
24f1e32c FW |
43 | { |
44 | return bp->attr.bp_len; | |
45 | } | |
46 | ||
24f1e32c | 47 | extern struct perf_event * |
5fa10b28 | 48 | register_user_hw_breakpoint(struct perf_event_attr *attr, |
b326e956 | 49 | perf_overflow_handler_t triggered, |
4dc0da86 | 50 | void *context, |
5fa10b28 | 51 | struct task_struct *tsk); |
24f1e32c FW |
52 | |
53 | /* FIXME: only change from the attr, and don't unregister */ | |
44234adc | 54 | extern int |
2f0993e0 | 55 | modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr); |
b332828c | 56 | |
b332828c P |
57 | /* |
58 | * Kernel breakpoints are not associated with any particular thread. | |
59 | */ | |
24f1e32c | 60 | extern struct perf_event * |
dd1853c3 | 61 | register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, |
b326e956 | 62 | perf_overflow_handler_t triggered, |
4dc0da86 | 63 | void *context, |
dd1853c3 | 64 | int cpu); |
24f1e32c | 65 | |
44ee6358 | 66 | extern struct perf_event * __percpu * |
dd1853c3 | 67 | register_wide_hw_breakpoint(struct perf_event_attr *attr, |
4dc0da86 AK |
68 | perf_overflow_handler_t triggered, |
69 | void *context); | |
24f1e32c FW |
70 | |
71 | extern int register_perf_hw_breakpoint(struct perf_event *bp); | |
72 | extern int __register_perf_hw_breakpoint(struct perf_event *bp); | |
73 | extern void unregister_hw_breakpoint(struct perf_event *bp); | |
44ee6358 | 74 | extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events); |
24f1e32c | 75 | |
5352ae63 JW |
76 | extern int dbg_reserve_bp_slot(struct perf_event *bp); |
77 | extern int dbg_release_bp_slot(struct perf_event *bp); | |
24f1e32c FW |
78 | extern int reserve_bp_slot(struct perf_event *bp); |
79 | extern void release_bp_slot(struct perf_event *bp); | |
80 | ||
81 | extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk); | |
82 | ||
687b16fb FW |
83 | static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) |
84 | { | |
85 | return &bp->hw.info; | |
86 | } | |
87 | ||
24f1e32c FW |
88 | #else /* !CONFIG_HAVE_HW_BREAKPOINT */ |
89 | ||
3c502e7a JW |
90 | static inline int __init init_hw_breakpoint(void) { return 0; } |
91 | ||
24f1e32c | 92 | static inline struct perf_event * |
5fa10b28 | 93 | register_user_hw_breakpoint(struct perf_event_attr *attr, |
b326e956 | 94 | perf_overflow_handler_t triggered, |
4dc0da86 | 95 | void *context, |
5fa10b28 | 96 | struct task_struct *tsk) { return NULL; } |
44234adc | 97 | static inline int |
24f1e32c | 98 | modify_user_hw_breakpoint(struct perf_event *bp, |
99ac64c8 | 99 | struct perf_event_attr *attr) { return -ENOSYS; } |
24f1e32c | 100 | static inline struct perf_event * |
dd1853c3 | 101 | register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, |
b326e956 | 102 | perf_overflow_handler_t triggered, |
4dc0da86 | 103 | void *context, |
dd1853c3 | 104 | int cpu) { return NULL; } |
44ee6358 | 105 | static inline struct perf_event * __percpu * |
dd1853c3 | 106 | register_wide_hw_breakpoint(struct perf_event_attr *attr, |
4dc0da86 AK |
107 | perf_overflow_handler_t triggered, |
108 | void *context) { return NULL; } | |
24f1e32c FW |
109 | static inline int |
110 | register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } | |
111 | static inline int | |
112 | __register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } | |
113 | static inline void unregister_hw_breakpoint(struct perf_event *bp) { } | |
114 | static inline void | |
44ee6358 | 115 | unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) { } |
24f1e32c FW |
116 | static inline int |
117 | reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; } | |
118 | static inline void release_bp_slot(struct perf_event *bp) { } | |
119 | ||
120 | static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { } | |
b332828c | 121 | |
687b16fb FW |
122 | static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) |
123 | { | |
124 | return NULL; | |
125 | } | |
126 | ||
24f1e32c | 127 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ |
24f1e32c | 128 | #endif /* _LINUX_HW_BREAKPOINT_H */ |