1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_HW_BREAKPOINT_H 3 #define _LINUX_HW_BREAKPOINT_H 4 5 #include <linux/perf_event.h> 6 #include <uapi/linux/hw_breakpoint.h> 7 8 #ifdef CONFIG_HAVE_HW_BREAKPOINT 9 10 extern int __init init_hw_breakpoint(void); 11 12 static inline void hw_breakpoint_init(struct perf_event_attr *attr) 13 { 14 memset(attr, 0, sizeof(*attr)); 15 16 attr->type = PERF_TYPE_BREAKPOINT; 17 attr->size = sizeof(*attr); 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 */ 22 attr->pinned = 1; 23 attr->sample_period = 1; 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; 30 } 31 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 42 static inline unsigned long hw_breakpoint_len(struct perf_event *bp) 43 { 44 return bp->attr.bp_len; 45 } 46 47 extern struct perf_event * 48 register_user_hw_breakpoint(struct perf_event_attr *attr, 49 perf_overflow_handler_t triggered, 50 void *context, 51 struct task_struct *tsk); 52 53 /* FIXME: only change from the attr, and don't unregister */ 54 extern int 55 modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr); 56 extern int 57 modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr, 58 bool check); 59 60 /* 61 * Kernel breakpoints are not associated with any particular thread. 62 */ 63 extern struct perf_event * 64 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, 65 perf_overflow_handler_t triggered, 66 void *context, 67 int cpu); 68 69 extern struct perf_event * __percpu * 70 register_wide_hw_breakpoint(struct perf_event_attr *attr, 71 perf_overflow_handler_t triggered, 72 void *context); 73 74 extern int register_perf_hw_breakpoint(struct perf_event *bp); 75 extern int __register_perf_hw_breakpoint(struct perf_event *bp); 76 extern void unregister_hw_breakpoint(struct perf_event *bp); 77 extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events); 78 79 extern int dbg_reserve_bp_slot(struct perf_event *bp); 80 extern int dbg_release_bp_slot(struct perf_event *bp); 81 extern int reserve_bp_slot(struct perf_event *bp); 82 extern void release_bp_slot(struct perf_event *bp); 83 84 extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk); 85 86 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 87 { 88 return &bp->hw.info; 89 } 90 91 #else /* !CONFIG_HAVE_HW_BREAKPOINT */ 92 93 static inline int __init init_hw_breakpoint(void) { return 0; } 94 95 static inline struct perf_event * 96 register_user_hw_breakpoint(struct perf_event_attr *attr, 97 perf_overflow_handler_t triggered, 98 void *context, 99 struct task_struct *tsk) { return NULL; } 100 static inline int 101 modify_user_hw_breakpoint(struct perf_event *bp, 102 struct perf_event_attr *attr) { return -ENOSYS; } 103 static inline int 104 modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr, 105 bool check) { return -ENOSYS; } 106 107 static inline struct perf_event * 108 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, 109 perf_overflow_handler_t triggered, 110 void *context, 111 int cpu) { return NULL; } 112 static inline struct perf_event * __percpu * 113 register_wide_hw_breakpoint(struct perf_event_attr *attr, 114 perf_overflow_handler_t triggered, 115 void *context) { return NULL; } 116 static inline int 117 register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } 118 static inline int 119 __register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } 120 static inline void unregister_hw_breakpoint(struct perf_event *bp) { } 121 static inline void 122 unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) { } 123 static inline int 124 reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; } 125 static inline void release_bp_slot(struct perf_event *bp) { } 126 127 static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { } 128 129 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 130 { 131 return NULL; 132 } 133 134 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 135 #endif /* _LINUX_HW_BREAKPOINT_H */ 136