Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (C) 2012 ARM Ltd.
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 /* Privilege Levels */
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 /* Breakpoint */
0057 #define ARM_BREAKPOINT_EXECUTE  0
0058 
0059 /* Watchpoints */
0060 #define ARM_BREAKPOINT_LOAD 1
0061 #define ARM_BREAKPOINT_STORE    2
0062 #define AARCH64_ESR_ACCESS_MASK (1 << 6)
0063 
0064 /* Lengths */
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 /* Kernel stepping */
0075 #define ARM_KERNEL_STEP_NONE    0
0076 #define ARM_KERNEL_STEP_ACTIVE  1
0077 #define ARM_KERNEL_STEP_SUSPEND 2
0078 
0079 /*
0080  * Limits.
0081  * Changing these will require modifications to the register accessors.
0082  */
0083 #define ARM_MAX_BRP     16
0084 #define ARM_MAX_WRP     16
0085 
0086 /* Virtual debug register bases. */
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 /* Debug register names. */
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 /* Accessor macros for the debug registers. */
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 /* Determine number of BRP registers available. */
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 /* Determine number of WRP registers available. */
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  /* __ASM_BREAKPOINT_H */