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