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 reserve_bp_slot(struct perf_event *bp); 79 extern void release_bp_slot(struct perf_event *bp); 80 81 extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk); 82 83 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 84 { 85 return &bp->hw.info; 86 } 87 88 #else /* !CONFIG_HAVE_HW_BREAKPOINT */ 89 90 static inline struct perf_event * 91 register_user_hw_breakpoint(struct perf_event_attr *attr, 92 perf_overflow_handler_t triggered, 93 struct task_struct *tsk) { return NULL; } 94 static inline int 95 modify_user_hw_breakpoint(struct perf_event *bp, 96 struct perf_event_attr *attr) { return -ENOSYS; } 97 static inline struct perf_event * 98 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, 99 perf_overflow_handler_t triggered, 100 int cpu) { return NULL; } 101 static inline struct perf_event ** 102 register_wide_hw_breakpoint(struct perf_event_attr *attr, 103 perf_overflow_handler_t triggered) { return NULL; } 104 static inline int 105 register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } 106 static inline int 107 __register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } 108 static inline void unregister_hw_breakpoint(struct perf_event *bp) { } 109 static inline void 110 unregister_wide_hw_breakpoint(struct perf_event **cpu_events) { } 111 static inline int 112 reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; } 113 static inline void release_bp_slot(struct perf_event *bp) { } 114 115 static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { } 116 117 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) 118 { 119 return NULL; 120 } 121 122 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 123 #endif /* __KERNEL__ */ 124 125 #endif /* _LINUX_HW_BREAKPOINT_H */ 126