Home | History | Annotate | Download | only in added
      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_EMPTY	= 0,
     13 	HW_BREAKPOINT_R		= 1,
     14 	HW_BREAKPOINT_W		= 2,
     15 	HW_BREAKPOINT_RW	= HW_BREAKPOINT_R | HW_BREAKPOINT_W,
     16 	HW_BREAKPOINT_X		= 4,
     17 	HW_BREAKPOINT_INVALID   = HW_BREAKPOINT_RW | HW_BREAKPOINT_X,
     18 };
     19 
     20 enum bp_type_idx {
     21 	TYPE_INST 	= 0,
     22 #ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
     23 	TYPE_DATA	= 0,
     24 #else
     25 	TYPE_DATA	= 1,
     26 #endif
     27 	TYPE_MAX
     28 };
     29 
     30 #ifdef __KERNEL__
     31 
     32 #include <linux/perf_event.h>
     33 
     34 #ifdef CONFIG_HAVE_HW_BREAKPOINT
     35 
     36 extern int __init init_hw_breakpoint(void);
     37 
     38 static inline void hw_breakpoint_init(struct perf_event_attr *attr)
     39 {
     40 	memset(attr, 0, sizeof(*attr));
     41 
     42 	attr->type = PERF_TYPE_BREAKPOINT;
     43 	attr->size = sizeof(*attr);
     44 	/*
     45 	 * As it's for in-kernel or ptrace use, we want it to be pinned
     46 	 * and to call its callback every hits.
     47 	 */
     48 	attr->pinned = 1;
     49 	attr->sample_period = 1;
     50 }
     51 
     52 static inline void ptrace_breakpoint_init(struct perf_event_attr *attr)
     53 {
     54 	hw_breakpoint_init(attr);
     55 	attr->exclude_kernel = 1;
     56 }
     57 
     58 static inline unsigned long hw_breakpoint_addr(struct perf_event *bp)
     59 {
     60 	return bp->attr.bp_addr;
     61 }
     62 
     63 static inline int hw_breakpoint_type(struct perf_event *bp)
     64 {
     65 	return bp->attr.bp_type;
     66 }
     67 
     68 static inline unsigned long hw_breakpoint_len(struct perf_event *bp)
     69 {
     70 	return bp->attr.bp_len;
     71 }
     72 
     73 extern struct perf_event *
     74 register_user_hw_breakpoint(struct perf_event_attr *attr,
     75 			    perf_overflow_handler_t triggered,
     76 			    struct task_struct *tsk);
     77 
     78 /* FIXME: only change from the attr, and don't unregister */
     79 extern int
     80 modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr);
     81 
     82 /*
     83  * Kernel breakpoints are not associated with any particular thread.
     84  */
     85 extern struct perf_event *
     86 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
     87 				perf_overflow_handler_t	triggered,
     88 				int cpu);
     89 
     90 extern struct perf_event * __percpu *
     91 register_wide_hw_breakpoint(struct perf_event_attr *attr,
     92 			    perf_overflow_handler_t triggered);
     93 
     94 extern int register_perf_hw_breakpoint(struct perf_event *bp);
     95 extern int __register_perf_hw_breakpoint(struct perf_event *bp);
     96 extern void unregister_hw_breakpoint(struct perf_event *bp);
     97 extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);
     98 
     99 extern int dbg_reserve_bp_slot(struct perf_event *bp);
    100 extern int dbg_release_bp_slot(struct perf_event *bp);
    101 extern int reserve_bp_slot(struct perf_event *bp);
    102 extern void release_bp_slot(struct perf_event *bp);
    103 
    104 extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
    105 
    106 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
    107 {
    108 	return &bp->hw.info;
    109 }
    110 
    111 #else /* !CONFIG_HAVE_HW_BREAKPOINT */
    112 
    113 static inline int __init init_hw_breakpoint(void) { return 0; }
    114 
    115 static inline struct perf_event *
    116 register_user_hw_breakpoint(struct perf_event_attr *attr,
    117 			    perf_overflow_handler_t triggered,
    118 			    struct task_struct *tsk)	{ return NULL; }
    119 static inline int
    120 modify_user_hw_breakpoint(struct perf_event *bp,
    121 			  struct perf_event_attr *attr)	{ return -ENOSYS; }
    122 static inline struct perf_event *
    123 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
    124 				perf_overflow_handler_t	 triggered,
    125 				int cpu)		{ return NULL; }
    126 static inline struct perf_event * __percpu *
    127 register_wide_hw_breakpoint(struct perf_event_attr *attr,
    128 			    perf_overflow_handler_t triggered)	{ return NULL; }
    129 static inline int
    130 register_perf_hw_breakpoint(struct perf_event *bp)	{ return -ENOSYS; }
    131 static inline int
    132 __register_perf_hw_breakpoint(struct perf_event *bp) 	{ return -ENOSYS; }
    133 static inline void unregister_hw_breakpoint(struct perf_event *bp)	{ }
    134 static inline void
    135 unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)	{ }
    136 static inline int
    137 reserve_bp_slot(struct perf_event *bp)			{return -ENOSYS; }
    138 static inline void release_bp_slot(struct perf_event *bp) 		{ }
    139 
    140 static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk)	{ }
    141 
    142 static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
    143 {
    144 	return NULL;
    145 }
    146 
    147 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
    148 #endif /* __KERNEL__ */
    149 
    150 #endif /* _LINUX_HW_BREAKPOINT_H */
    151