1 #ifndef _LINUX_HW_BREAKPOINT_H 2 #define _LINUX_HW_BREAKPOINT_H 3 4 enum { 5 HW_BREAKPOINT_LEN_1 = 1, 6 HW_BREAKPOINT_LEN_2 = 2, 7 HW_BREAKPOINT_LEN_4 = 4, 8 HW_BREAKPOINT_LEN_8 = 8, 9 }; 10 11 enum { 12 HW_BREAKPOINT_R = 1, 13 HW_BREAKPOINT_W = 2, 14 HW_BREAKPOINT_X = 4, 15 }; 16 17 #ifdef __KERNEL__ 18 19 #include <linux/perf_event.h> 20 21 #ifdef CONFIG_HAVE_HW_BREAKPOINT 22 23 static inline void hw_breakpoint_init(struct perf_event_attr *attr) 24 { 25 memset(attr, 0, sizeof(*attr)); 26 27 attr->type = PERF_TYPE_BREAKPOINT; 28 attr->size = sizeof(*attr); 29 /* 30 * As it's for in-kernel or ptrace use, we want it to be pinned 31 * and to call its callback every hits. 32 */ 33 attr->pinned = 1; 34 attr->sample_period = 1; 35 } 36 37 static inline unsigned long hw_breakpoint_addr(struct perf_event *bp) 38 { 39 return bp->attr.bp_addr; 40 } 41 42 static inline int hw_breakpoint_type(struct perf_event *bp) 43 { 44 return bp->attr.bp_type; 45 } 46 47 static inline int hw_breakpoint_len(struct perf_event *bp) 48 { 49 return bp->attr.bp_len; 50 } 51 52 extern struct perf_event * 53 register_user_hw_breakpoint(struct perf_event_attr *attr, 54 perf_overflow_handler_t triggered, 55 struct task_struct *tsk); 56 57 /* FIXME: only change from the attr, and don't unregister */ 58 extern int 59 modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr); 60 61 /* 62 * Kernel breakpoints are not associated with any particular thread. 63 */ 64 extern struct perf_event * 65 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, 66 perf_overflow_handler_t triggered, 67 int cpu); 68 69 extern struct perf_event ** 70 register_wide_hw_breakpoint(struct perf_event_attr *attr, 71 perf_overflow_handler_t triggered); 72 73 extern int register_perf_hw_breakpoint(struct perf_event *bp); 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 **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 83 extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk); 84 85 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 86 { 87 return &bp->hw.info; 88 } 89 90 #else /* !CONFIG_HAVE_HW_BREAKPOINT */ 91 92 static inline struct perf_event * 93 register_user_hw_breakpoint(struct perf_event_attr *attr, 94 perf_overflow_handler_t triggered, 95 struct task_struct *tsk) { return NULL; } 96 static inline int 97 modify_user_hw_breakpoint(struct perf_event *bp, 98 struct perf_event_attr *attr) { return -ENOSYS; } 99 static inline struct perf_event * 100 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, 101 perf_overflow_handler_t triggered, 102 int cpu) { return NULL; } 103 static inline struct perf_event ** 104 register_wide_hw_breakpoint(struct perf_event_attr *attr, 105 perf_overflow_handler_t triggered) { return NULL; } 106 static inline int 107 register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } 108 static inline int 109 __register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } 110 static inline void unregister_hw_breakpoint(struct perf_event *bp) { } 111 static inline void 112 unregister_wide_hw_breakpoint(struct perf_event **cpu_events) { } 113 static inline int 114 reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; } 115 static inline void release_bp_slot(struct perf_event *bp) { } 116 117 static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { } 118 119 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 120 { 121 return NULL; 122 } 123 124 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 125 #endif /* __KERNEL__ */ 126 127 #endif /* _LINUX_HW_BREAKPOINT_H */ 128