hw_breakpoint.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. void *context,
  63. struct task_struct *tsk);
  64. /* FIXME: only change from the attr, and don't unregister */
  65. extern int
  66. modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr);
  67. /*
  68. * Kernel breakpoints are not associated with any particular thread.
  69. */
  70. extern struct perf_event *
  71. register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
  72. perf_overflow_handler_t triggered,
  73. void *context,
  74. int cpu);
  75. extern struct perf_event * __percpu *
  76. register_wide_hw_breakpoint(struct perf_event_attr *attr,
  77. perf_overflow_handler_t triggered,
  78. void *context);
  79. extern int register_perf_hw_breakpoint(struct perf_event *bp);
  80. extern int __register_perf_hw_breakpoint(struct perf_event *bp);
  81. extern void unregister_hw_breakpoint(struct perf_event *bp);
  82. extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);
  83. extern int dbg_reserve_bp_slot(struct perf_event *bp);
  84. extern int dbg_release_bp_slot(struct perf_event *bp);
  85. extern int reserve_bp_slot(struct perf_event *bp);
  86. extern void release_bp_slot(struct perf_event *bp);
  87. extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
  88. static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
  89. {
  90. return &bp->hw.info;
  91. }
  92. #else /* !CONFIG_HAVE_HW_BREAKPOINT */
  93. static inline int __init init_hw_breakpoint(void) { return 0; }
  94. static inline struct perf_event *
  95. register_user_hw_breakpoint(struct perf_event_attr *attr,
  96. perf_overflow_handler_t triggered,
  97. void *context,
  98. struct task_struct *tsk) { return NULL; }
  99. static inline int
  100. modify_user_hw_breakpoint(struct perf_event *bp,
  101. struct perf_event_attr *attr) { return -ENOSYS; }
  102. static inline struct perf_event *
  103. register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
  104. perf_overflow_handler_t triggered,
  105. void *context,
  106. int cpu) { return NULL; }
  107. static inline struct perf_event * __percpu *
  108. register_wide_hw_breakpoint(struct perf_event_attr *attr,
  109. perf_overflow_handler_t triggered,
  110. void *context) { return NULL; }
  111. static inline int
  112. register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
  113. static inline int
  114. __register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
  115. static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
  116. static inline void
  117. unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) { }
  118. static inline int
  119. reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
  120. static inline void release_bp_slot(struct perf_event *bp) { }
  121. static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { }
  122. static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
  123. {
  124. return NULL;
  125. }
  126. #endif /* CONFIG_HAVE_HW_BREAKPOINT */
  127. #endif /* __KERNEL__ */
  128. #endif /* _LINUX_HW_BREAKPOINT_H */