hw_breakpoint.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
  4. */
  5. #ifndef __ASM_HW_BREAKPOINT_H
  6. #define __ASM_HW_BREAKPOINT_H
  7. #include <asm/loongarch.h>
  8. #ifdef __KERNEL__
  9. /* Breakpoint */
  10. #define LOONGARCH_BREAKPOINT_EXECUTE (0 << 0)
  11. /* Watchpoints */
  12. #define LOONGARCH_BREAKPOINT_LOAD (1 << 0)
  13. #define LOONGARCH_BREAKPOINT_STORE (1 << 1)
  14. struct arch_hw_breakpoint_ctrl {
  15. u32 __reserved : 28,
  16. len : 2,
  17. type : 2;
  18. };
  19. struct arch_hw_breakpoint {
  20. u64 address;
  21. u64 mask;
  22. struct arch_hw_breakpoint_ctrl ctrl;
  23. };
  24. /* Lengths */
  25. #define LOONGARCH_BREAKPOINT_LEN_1 0b11
  26. #define LOONGARCH_BREAKPOINT_LEN_2 0b10
  27. #define LOONGARCH_BREAKPOINT_LEN_4 0b01
  28. #define LOONGARCH_BREAKPOINT_LEN_8 0b00
  29. /*
  30. * Limits.
  31. * Changing these will require modifications to the register accessors.
  32. */
  33. #define LOONGARCH_MAX_BRP 14
  34. #define LOONGARCH_MAX_WRP 14
  35. /* Virtual debug register bases. */
  36. #define CSR_CFG_ADDR 0
  37. #define CSR_CFG_MASK (CSR_CFG_ADDR + LOONGARCH_MAX_BRP)
  38. #define CSR_CFG_CTRL (CSR_CFG_MASK + LOONGARCH_MAX_BRP)
  39. #define CSR_CFG_ASID (CSR_CFG_CTRL + LOONGARCH_MAX_WRP)
  40. /* Debug register names. */
  41. #define LOONGARCH_CSR_NAME_ADDR ADDR
  42. #define LOONGARCH_CSR_NAME_MASK MASK
  43. #define LOONGARCH_CSR_NAME_CTRL CTRL
  44. #define LOONGARCH_CSR_NAME_ASID ASID
  45. /* Accessor macros for the debug registers. */
  46. #define LOONGARCH_CSR_WATCH_READ(N, REG, T, VAL) \
  47. do { \
  48. if (T == 0) \
  49. VAL = csr_read64(LOONGARCH_CSR_##IB##N##REG); \
  50. else \
  51. VAL = csr_read64(LOONGARCH_CSR_##DB##N##REG); \
  52. } while (0)
  53. #define LOONGARCH_CSR_WATCH_WRITE(N, REG, T, VAL) \
  54. do { \
  55. if (T == 0) \
  56. csr_write64(VAL, LOONGARCH_CSR_##IB##N##REG); \
  57. else \
  58. csr_write64(VAL, LOONGARCH_CSR_##DB##N##REG); \
  59. } while (0)
  60. /* Exact number */
  61. #define CSR_FWPC_NUM 0x3f
  62. #define CSR_MWPC_NUM 0x3f
  63. #define CTRL_PLV_ENABLE 0x1e
  64. #define CTRL_PLV0_ENABLE 0x02
  65. #define CTRL_PLV3_ENABLE 0x10
  66. #define MWPnCFG3_LoadEn 8
  67. #define MWPnCFG3_StoreEn 9
  68. #define MWPnCFG3_Type_mask 0x3
  69. #define MWPnCFG3_Size_mask 0x3
  70. static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
  71. {
  72. return (ctrl.len << 10) | (ctrl.type << 8);
  73. }
  74. static inline void decode_ctrl_reg(u32 reg, struct arch_hw_breakpoint_ctrl *ctrl)
  75. {
  76. reg >>= 8;
  77. ctrl->type = reg & MWPnCFG3_Type_mask;
  78. reg >>= 2;
  79. ctrl->len = reg & MWPnCFG3_Size_mask;
  80. }
  81. struct task_struct;
  82. struct notifier_block;
  83. struct perf_event;
  84. struct perf_event_attr;
  85. extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
  86. int *gen_len, int *gen_type);
  87. extern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw);
  88. extern int hw_breakpoint_arch_parse(struct perf_event *bp,
  89. const struct perf_event_attr *attr,
  90. struct arch_hw_breakpoint *hw);
  91. extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
  92. unsigned long val, void *data);
  93. extern int arch_install_hw_breakpoint(struct perf_event *bp);
  94. extern void arch_uninstall_hw_breakpoint(struct perf_event *bp);
  95. extern int hw_breakpoint_slots(int type);
  96. extern void hw_breakpoint_pmu_read(struct perf_event *bp);
  97. void breakpoint_handler(struct pt_regs *regs);
  98. void watchpoint_handler(struct pt_regs *regs);
  99. #ifdef CONFIG_HAVE_HW_BREAKPOINT
  100. extern void ptrace_hw_copy_thread(struct task_struct *task);
  101. extern void hw_breakpoint_thread_switch(struct task_struct *next);
  102. #else
  103. static inline void ptrace_hw_copy_thread(struct task_struct *task)
  104. {
  105. }
  106. static inline void hw_breakpoint_thread_switch(struct task_struct *next)
  107. {
  108. }
  109. #endif
  110. /* Determine number of BRP registers available. */
  111. static inline int get_num_brps(void)
  112. {
  113. return csr_read32(LOONGARCH_CSR_FWPC) & CSR_FWPC_NUM;
  114. }
  115. /* Determine number of WRP registers available. */
  116. static inline int get_num_wrps(void)
  117. {
  118. return csr_read32(LOONGARCH_CSR_MWPC) & CSR_MWPC_NUM;
  119. }
  120. #endif /* __KERNEL__ */
  121. #endif /* __ASM_BREAKPOINT_H */