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 void unregister_hw_breakpoint(struct perf_event *bp); 76 extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events); 77 extern bool hw_breakpoint_is_used(void); 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 int arch_reserve_bp_slot(struct perf_event *bp); 84 void arch_release_bp_slot(struct perf_event *bp); 85 void arch_unregister_hw_breakpoint(struct perf_event *bp); 86 87 extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk); 88 89 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 90 { 91 return &bp->hw.info; 92 } 93 94 #else /* !CONFIG_HAVE_HW_BREAKPOINT */ 95 96 static inline int __init init_hw_breakpoint(void) { return 0; } 97 98 static inline struct perf_event * 99 register_user_hw_breakpoint(struct perf_event_attr *attr, 100 perf_overflow_handler_t triggered, 101 void *context, 102 struct task_struct *tsk) { return NULL; } 103 static inline int 104 modify_user_hw_breakpoint(struct perf_event *bp, 105 struct perf_event_attr *attr) { return -ENOSYS; } 106 static inline int 107 modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr, 108 bool check) { return -ENOSYS; } 109 110 static inline struct perf_event * 111 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, 112 perf_overflow_handler_t triggered, 113 void *context, 114 int cpu) { return NULL; } 115 static inline struct perf_event * __percpu * 116 register_wide_hw_breakpoint(struct perf_event_attr *attr, 117 perf_overflow_handler_t triggered, 118 void *context) { return NULL; } 119 static inline int 120 register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } 121 static inline void unregister_hw_breakpoint(struct perf_event *bp) { } 122 static inline void 123 unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) { } 124 static inline bool hw_breakpoint_is_used(void) { return false; } 125 126 static inline int 127 reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; } 128 static inline void release_bp_slot(struct perf_event *bp) { } 129 130 static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { } 131 132 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 133 { 134 return NULL; 135 } 136 137 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 138 #endif /* _LINUX_HW_BREAKPOINT_H */ 139