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