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 79 #define MWPnCFG3_LoadEn 8 80 #define MWPnCFG3_StoreEn 9 81 82 #define MWPnCFG3_Type_mask 0x3 83 #define MWPnCFG3_Size_mask 0x3 84 85 static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl) 86 { 87 return (ctrl.len << 10) | (ctrl.type << 8); 88 } 89 90 static inline void decode_ctrl_reg(u32 reg, struct arch_hw_breakpoint_ctrl *ctrl) 91 { 92 reg >>= 8; 93 ctrl->type = reg & MWPnCFG3_Type_mask; 94 reg >>= 2; 95 ctrl->len = reg & MWPnCFG3_Size_mask; 96 } 97 98 struct task_struct; 99 struct notifier_block; 100 struct perf_event; 101 struct perf_event_attr; 102 103 extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, 104 int *gen_len, int *gen_type, int *offset); 105 extern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw); 106 extern int hw_breakpoint_arch_parse(struct perf_event *bp, 107 const struct perf_event_attr *attr, 108 struct arch_hw_breakpoint *hw); 109 extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, 110 unsigned long val, void *data); 111 112 extern int arch_install_hw_breakpoint(struct perf_event *bp); 113 extern void arch_uninstall_hw_breakpoint(struct perf_event *bp); 114 extern int hw_breakpoint_slots(int type); 115 extern void hw_breakpoint_pmu_read(struct perf_event *bp); 116 117 void breakpoint_handler(struct pt_regs *regs); 118 void watchpoint_handler(struct pt_regs *regs); 119 120 #ifdef CONFIG_HAVE_HW_BREAKPOINT 121 extern void ptrace_hw_copy_thread(struct task_struct *task); 122 extern void hw_breakpoint_thread_switch(struct task_struct *next); 123 #else 124 static inline void ptrace_hw_copy_thread(struct task_struct *task) 125 { 126 } 127 static inline void hw_breakpoint_thread_switch(struct task_struct *next) 128 { 129 } 130 #endif 131 132 /* Determine number of BRP registers available. */ 133 static inline int get_num_brps(void) 134 { 135 return csr_read64(LOONGARCH_CSR_FWPC) & CSR_FWPC_NUM; 136 } 137 138 /* Determine number of WRP registers available. */ 139 static inline int get_num_wrps(void) 140 { 141 return csr_read64(LOONGARCH_CSR_MWPC) & CSR_MWPC_NUM; 142 } 143 144 #endif /* __KERNEL__ */ 145 #endif /* __ASM_BREAKPOINT_H */ 146