hw_breakpoint.h 4.2 KB

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