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