hw_breakpoint.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. static inline void hw_breakpoint_init(struct perf_event_attr *attr)
  30. {
  31. memset(attr, 0, sizeof(*attr));
  32. attr->type = PERF_TYPE_BREAKPOINT;
  33. attr->size = sizeof(*attr);
  34. /*
  35. * As it's for in-kernel or ptrace use, we want it to be pinned
  36. * and to call its callback every hits.
  37. */
  38. attr->pinned = 1;
  39. attr->sample_period = 1;
  40. }
  41. static inline void ptrace_breakpoint_init(struct perf_event_attr *attr)
  42. {
  43. hw_breakpoint_init(attr);
  44. attr->exclude_kernel = 1;
  45. }
  46. static inline unsigned long hw_breakpoint_addr(struct perf_event *bp)
  47. {
  48. return bp->attr.bp_addr;
  49. }
  50. static inline int hw_breakpoint_type(struct perf_event *bp)
  51. {
  52. return bp->attr.bp_type;
  53. }
  54. static inline unsigned long hw_breakpoint_len(struct perf_event *bp)
  55. {
  56. return bp->attr.bp_len;
  57. }
  58. extern struct perf_event *
  59. register_user_hw_breakpoint(struct perf_event_attr *attr,
  60. perf_overflow_handler_t triggered,
  61. struct task_struct *tsk);
  62. /* FIXME: only change from the attr, and don't unregister */
  63. extern int
  64. modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr);
  65. /*
  66. * Kernel breakpoints are not associated with any particular thread.
  67. */
  68. extern struct perf_event *
  69. register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
  70. perf_overflow_handler_t triggered,
  71. int cpu);
  72. extern struct perf_event * __percpu *
  73. register_wide_hw_breakpoint(struct perf_event_attr *attr,
  74. perf_overflow_handler_t triggered);
  75. extern int register_perf_hw_breakpoint(struct perf_event *bp);
  76. extern int __register_perf_hw_breakpoint(struct perf_event *bp);
  77. extern void unregister_hw_breakpoint(struct perf_event *bp);
  78. extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);
  79. extern int dbg_reserve_bp_slot(struct perf_event *bp);
  80. extern int dbg_release_bp_slot(struct perf_event *bp);
  81. extern int reserve_bp_slot(struct perf_event *bp);
  82. extern void release_bp_slot(struct perf_event *bp);
  83. extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
  84. static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
  85. {
  86. return &bp->hw.info;
  87. }
  88. #else /* !CONFIG_HAVE_HW_BREAKPOINT */
  89. static inline struct perf_event *
  90. register_user_hw_breakpoint(struct perf_event_attr *attr,
  91. perf_overflow_handler_t triggered,
  92. struct task_struct *tsk) { return NULL; }
  93. static inline int
  94. modify_user_hw_breakpoint(struct perf_event *bp,
  95. struct perf_event_attr *attr) { return -ENOSYS; }
  96. static inline struct perf_event *
  97. register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
  98. perf_overflow_handler_t triggered,
  99. int cpu) { return NULL; }
  100. static inline struct perf_event * __percpu *
  101. register_wide_hw_breakpoint(struct perf_event_attr *attr,
  102. perf_overflow_handler_t triggered) { return NULL; }
  103. static inline int
  104. register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
  105. static inline int
  106. __register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
  107. static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
  108. static inline void
  109. unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) { }
  110. static inline int
  111. reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
  112. static inline void release_bp_slot(struct perf_event *bp) { }
  113. static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { }
  114. static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
  115. {
  116. return NULL;
  117. }
  118. #endif /* CONFIG_HAVE_HW_BREAKPOINT */
  119. #endif /* __KERNEL__ */
  120. #endif /* _LINUX_HW_BREAKPOINT_H */