Branch data Line data Source code
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 : 0 : memset(attr, 0, sizeof(*attr)); 15 : : 16 : 0 : attr->type = PERF_TYPE_BREAKPOINT; 17 : 0 : 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 : 0 : attr->pinned = 1; 23 : 0 : 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 : 0 : 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 : 0 : 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 */