0001
0002
0003
0004
0005 #ifndef __ASM_HW_BREAKPOINT_H
0006 #define __ASM_HW_BREAKPOINT_H
0007
0008 #include <asm/cputype.h>
0009 #include <asm/cpufeature.h>
0010 #include <asm/sysreg.h>
0011 #include <asm/virt.h>
0012
0013 struct arch_hw_breakpoint_ctrl {
0014 u32 __reserved : 19,
0015 len : 8,
0016 type : 2,
0017 privilege : 2,
0018 enabled : 1;
0019 };
0020
0021 struct arch_hw_breakpoint {
0022 u64 address;
0023 u64 trigger;
0024 struct arch_hw_breakpoint_ctrl ctrl;
0025 };
0026
0027
0028 #define AARCH64_BREAKPOINT_EL1 1
0029 #define AARCH64_BREAKPOINT_EL0 2
0030
0031 #define DBG_HMC_HYP (1 << 13)
0032
0033 static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
0034 {
0035 u32 val = (ctrl.len << 5) | (ctrl.type << 3) | (ctrl.privilege << 1) |
0036 ctrl.enabled;
0037
0038 if (is_kernel_in_hyp_mode() && ctrl.privilege == AARCH64_BREAKPOINT_EL1)
0039 val |= DBG_HMC_HYP;
0040
0041 return val;
0042 }
0043
0044 static inline void decode_ctrl_reg(u32 reg,
0045 struct arch_hw_breakpoint_ctrl *ctrl)
0046 {
0047 ctrl->enabled = reg & 0x1;
0048 reg >>= 1;
0049 ctrl->privilege = reg & 0x3;
0050 reg >>= 2;
0051 ctrl->type = reg & 0x3;
0052 reg >>= 2;
0053 ctrl->len = reg & 0xff;
0054 }
0055
0056
0057 #define ARM_BREAKPOINT_EXECUTE 0
0058
0059
0060 #define ARM_BREAKPOINT_LOAD 1
0061 #define ARM_BREAKPOINT_STORE 2
0062 #define AARCH64_ESR_ACCESS_MASK (1 << 6)
0063
0064
0065 #define ARM_BREAKPOINT_LEN_1 0x1
0066 #define ARM_BREAKPOINT_LEN_2 0x3
0067 #define ARM_BREAKPOINT_LEN_3 0x7
0068 #define ARM_BREAKPOINT_LEN_4 0xf
0069 #define ARM_BREAKPOINT_LEN_5 0x1f
0070 #define ARM_BREAKPOINT_LEN_6 0x3f
0071 #define ARM_BREAKPOINT_LEN_7 0x7f
0072 #define ARM_BREAKPOINT_LEN_8 0xff
0073
0074
0075 #define ARM_KERNEL_STEP_NONE 0
0076 #define ARM_KERNEL_STEP_ACTIVE 1
0077 #define ARM_KERNEL_STEP_SUSPEND 2
0078
0079
0080
0081
0082
0083 #define ARM_MAX_BRP 16
0084 #define ARM_MAX_WRP 16
0085
0086
0087 #define AARCH64_DBG_REG_BVR 0
0088 #define AARCH64_DBG_REG_BCR (AARCH64_DBG_REG_BVR + ARM_MAX_BRP)
0089 #define AARCH64_DBG_REG_WVR (AARCH64_DBG_REG_BCR + ARM_MAX_BRP)
0090 #define AARCH64_DBG_REG_WCR (AARCH64_DBG_REG_WVR + ARM_MAX_WRP)
0091
0092
0093 #define AARCH64_DBG_REG_NAME_BVR bvr
0094 #define AARCH64_DBG_REG_NAME_BCR bcr
0095 #define AARCH64_DBG_REG_NAME_WVR wvr
0096 #define AARCH64_DBG_REG_NAME_WCR wcr
0097
0098
0099 #define AARCH64_DBG_READ(N, REG, VAL) do {\
0100 VAL = read_sysreg(dbg##REG##N##_el1);\
0101 } while (0)
0102
0103 #define AARCH64_DBG_WRITE(N, REG, VAL) do {\
0104 write_sysreg(VAL, dbg##REG##N##_el1);\
0105 } while (0)
0106
0107 struct task_struct;
0108 struct notifier_block;
0109 struct perf_event_attr;
0110 struct perf_event;
0111 struct pmu;
0112
0113 extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
0114 int *gen_len, int *gen_type, int *offset);
0115 extern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw);
0116 extern int hw_breakpoint_arch_parse(struct perf_event *bp,
0117 const struct perf_event_attr *attr,
0118 struct arch_hw_breakpoint *hw);
0119 extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
0120 unsigned long val, void *data);
0121
0122 extern int arch_install_hw_breakpoint(struct perf_event *bp);
0123 extern void arch_uninstall_hw_breakpoint(struct perf_event *bp);
0124 extern void hw_breakpoint_pmu_read(struct perf_event *bp);
0125 extern int hw_breakpoint_slots(int type);
0126
0127 #ifdef CONFIG_HAVE_HW_BREAKPOINT
0128 extern void hw_breakpoint_thread_switch(struct task_struct *next);
0129 extern void ptrace_hw_copy_thread(struct task_struct *task);
0130 #else
0131 static inline void hw_breakpoint_thread_switch(struct task_struct *next)
0132 {
0133 }
0134 static inline void ptrace_hw_copy_thread(struct task_struct *task)
0135 {
0136 }
0137 #endif
0138
0139
0140 static inline int get_num_brps(void)
0141 {
0142 u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
0143 return 1 +
0144 cpuid_feature_extract_unsigned_field(dfr0,
0145 ID_AA64DFR0_BRPS_SHIFT);
0146 }
0147
0148
0149 static inline int get_num_wrps(void)
0150 {
0151 u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
0152 return 1 +
0153 cpuid_feature_extract_unsigned_field(dfr0,
0154 ID_AA64DFR0_WRPS_SHIFT);
0155 }
0156
0157 #endif