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 0 : 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 0 : } 25 : 26 0 : static inline void ptrace_breakpoint_init(struct perf_event_attr *attr) 27 : { 28 0 : 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 : 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 : 78 : extern int dbg_reserve_bp_slot(struct perf_event *bp); 79 : extern int dbg_release_bp_slot(struct perf_event *bp); 80 : extern int reserve_bp_slot(struct perf_event *bp); 81 : extern void release_bp_slot(struct perf_event *bp); 82 : int hw_breakpoint_weight(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 0 : static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 90 : { 91 0 : 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 int 125 : reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; } 126 : static inline void release_bp_slot(struct perf_event *bp) { } 127 : 128 : static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { } 129 : 130 : static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 131 : { 132 : return NULL; 133 : } 134 : 135 : #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 136 : #endif /* _LINUX_HW_BREAKPOINT_H */