1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/regset.h> 4 #include <linux/hw_breakpoint.h> 5 6 #include <asm/debug.h> 7 8 #include "ptrace-decl.h" 9 10 void user_enable_single_step(struct task_struct *task) 11 { 12 struct pt_regs *regs = task->thread.regs; 13 14 if (regs != NULL) { 15 regs->msr &= ~MSR_BE; 16 regs->msr |= MSR_SE; 17 } 18 set_tsk_thread_flag(task, TIF_SINGLESTEP); 19 } 20 21 void user_enable_block_step(struct task_struct *task) 22 { 23 struct pt_regs *regs = task->thread.regs; 24 25 if (regs != NULL) { 26 regs->msr &= ~MSR_SE; 27 regs->msr |= MSR_BE; 28 } 29 set_tsk_thread_flag(task, TIF_SINGLESTEP); 30 } 31 32 void user_disable_single_step(struct task_struct *task) 33 { 34 struct pt_regs *regs = task->thread.regs; 35 36 if (regs != NULL) 37 regs->msr &= ~(MSR_SE | MSR_BE); 38 39 clear_tsk_thread_flag(task, TIF_SINGLESTEP); 40 } 41 42 void ppc_gethwdinfo(struct ppc_debug_info *dbginfo) 43 { 44 dbginfo->version = 1; 45 dbginfo->num_instruction_bps = 0; 46 if (ppc_breakpoint_available()) 47 dbginfo->num_data_bps = nr_wp_slots(); 48 else 49 dbginfo->num_data_bps = 0; 50 dbginfo->num_condition_regs = 0; 51 dbginfo->data_bp_alignment = sizeof(long); 52 dbginfo->sizeof_condition = 0; 53 if (IS_ENABLED(CONFIG_HAVE_HW_BREAKPOINT)) { 54 dbginfo->features = PPC_DEBUG_FEATURE_DATA_BP_RANGE; 55 if (dawr_enabled()) 56 dbginfo->features |= PPC_DEBUG_FEATURE_DATA_BP_DAWR; 57 } else { 58 dbginfo->features = 0; 59 } 60 if (cpu_has_feature(CPU_FTR_ARCH_31)) 61 dbginfo->features |= PPC_DEBUG_FEATURE_DATA_BP_ARCH_31; 62 } 63 64 int ptrace_get_debugreg(struct task_struct *child, unsigned long addr, 65 unsigned long __user *datalp) 66 { 67 unsigned long dabr_fake; 68 69 /* We only support one DABR and no IABRS at the moment */ 70 if (addr > 0) 71 return -EINVAL; 72 dabr_fake = ((child->thread.hw_brk[0].address & (~HW_BRK_TYPE_DABR)) | 73 (child->thread.hw_brk[0].type & HW_BRK_TYPE_DABR)); 74 return put_user(dabr_fake, datalp); 75 } 76 77 /* 78 * ptrace_set_debugreg() fakes DABR and DABR is only one. So even if 79 * internal hw supports more than one watchpoint, we support only one 80 * watchpoint with this interface. 81 */ 82 int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, unsigned long data) 83 { 84 #ifdef CONFIG_HAVE_HW_BREAKPOINT 85 int ret; 86 struct thread_struct *thread = &task->thread; 87 struct perf_event *bp; 88 struct perf_event_attr attr; 89 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 90 bool set_bp = true; 91 struct arch_hw_breakpoint hw_brk; 92 93 /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). 94 * For embedded processors we support one DAC and no IAC's at the 95 * moment. 96 */ 97 if (addr > 0) 98 return -EINVAL; 99 100 /* The bottom 3 bits in dabr are flags */ 101 if ((data & ~0x7UL) >= TASK_SIZE) 102 return -EIO; 103 104 /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. 105 * It was assumed, on previous implementations, that 3 bits were 106 * passed together with the data address, fitting the design of the 107 * DABR register, as follows: 108 * 109 * bit 0: Read flag 110 * bit 1: Write flag 111 * bit 2: Breakpoint translation 112 * 113 * Thus, we use them here as so. 114 */ 115 116 /* Ensure breakpoint translation bit is set */ 117 if (data && !(data & HW_BRK_TYPE_TRANSLATE)) 118 return -EIO; 119 hw_brk.address = data & (~HW_BRK_TYPE_DABR); 120 hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL; 121 hw_brk.len = DABR_MAX_LEN; 122 hw_brk.hw_len = DABR_MAX_LEN; 123 set_bp = (data) && (hw_brk.type & HW_BRK_TYPE_RDWR); 124 #ifdef CONFIG_HAVE_HW_BREAKPOINT 125 bp = thread->ptrace_bps[0]; 126 if (!set_bp) { 127 if (bp) { 128 unregister_hw_breakpoint(bp); 129 thread->ptrace_bps[0] = NULL; 130 } 131 return 0; 132 } 133 if (bp) { 134 attr = bp->attr; 135 attr.bp_addr = hw_brk.address; 136 attr.bp_len = DABR_MAX_LEN; 137 arch_bp_generic_fields(hw_brk.type, &attr.bp_type); 138 139 /* Enable breakpoint */ 140 attr.disabled = false; 141 142 ret = modify_user_hw_breakpoint(bp, &attr); 143 if (ret) 144 return ret; 145 146 thread->ptrace_bps[0] = bp; 147 thread->hw_brk[0] = hw_brk; 148 return 0; 149 } 150 151 /* Create a new breakpoint request if one doesn't exist already */ 152 hw_breakpoint_init(&attr); 153 attr.bp_addr = hw_brk.address; 154 attr.bp_len = DABR_MAX_LEN; 155 arch_bp_generic_fields(hw_brk.type, 156 &attr.bp_type); 157 158 thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, 159 ptrace_triggered, NULL, task); 160 if (IS_ERR(bp)) { 161 thread->ptrace_bps[0] = NULL; 162 return PTR_ERR(bp); 163 } 164 165 #else /* !CONFIG_HAVE_HW_BREAKPOINT */ 166 if (set_bp && (!ppc_breakpoint_available())) 167 return -ENODEV; 168 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 169 task->thread.hw_brk[0] = hw_brk; 170 return 0; 171 } 172 173 #ifdef CONFIG_HAVE_HW_BREAKPOINT 174 static int find_empty_ptrace_bp(struct thread_struct *thread) 175 { 176 int i; 177 178 for (i = 0; i < nr_wp_slots(); i++) { 179 if (!thread->ptrace_bps[i]) 180 return i; 181 } 182 return -1; 183 } 184 #endif 185 186 static int find_empty_hw_brk(struct thread_struct *thread) 187 { 188 int i; 189 190 for (i = 0; i < nr_wp_slots(); i++) { 191 if (!thread->hw_brk[i].address) 192 return i; 193 } 194 return -1; 195 } 196 197 long ppc_set_hwdebug(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) 198 { 199 int i; 200 #ifdef CONFIG_HAVE_HW_BREAKPOINT 201 int len = 0; 202 struct thread_struct *thread = &child->thread; 203 struct perf_event *bp; 204 struct perf_event_attr attr; 205 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 206 struct arch_hw_breakpoint brk; 207 208 if (bp_info->version != 1) 209 return -ENOTSUPP; 210 /* 211 * We only support one data breakpoint 212 */ 213 if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 || 214 (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 || 215 bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) 216 return -EINVAL; 217 218 if ((unsigned long)bp_info->addr >= TASK_SIZE) 219 return -EIO; 220 221 brk.address = ALIGN_DOWN(bp_info->addr, HW_BREAKPOINT_SIZE); 222 brk.type = HW_BRK_TYPE_TRANSLATE | HW_BRK_TYPE_PRIV_ALL; 223 brk.len = DABR_MAX_LEN; 224 brk.hw_len = DABR_MAX_LEN; 225 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) 226 brk.type |= HW_BRK_TYPE_READ; 227 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) 228 brk.type |= HW_BRK_TYPE_WRITE; 229 #ifdef CONFIG_HAVE_HW_BREAKPOINT 230 if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) 231 len = bp_info->addr2 - bp_info->addr; 232 else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT) 233 len = 1; 234 else 235 return -EINVAL; 236 237 i = find_empty_ptrace_bp(thread); 238 if (i < 0) 239 return -ENOSPC; 240 241 /* Create a new breakpoint request if one doesn't exist already */ 242 hw_breakpoint_init(&attr); 243 attr.bp_addr = (unsigned long)bp_info->addr; 244 attr.bp_len = len; 245 arch_bp_generic_fields(brk.type, &attr.bp_type); 246 247 bp = register_user_hw_breakpoint(&attr, ptrace_triggered, NULL, child); 248 thread->ptrace_bps[i] = bp; 249 if (IS_ERR(bp)) { 250 thread->ptrace_bps[i] = NULL; 251 return PTR_ERR(bp); 252 } 253 254 return i + 1; 255 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 256 257 if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) 258 return -EINVAL; 259 260 i = find_empty_hw_brk(&child->thread); 261 if (i < 0) 262 return -ENOSPC; 263 264 if (!ppc_breakpoint_available()) 265 return -ENODEV; 266 267 child->thread.hw_brk[i] = brk; 268 269 return i + 1; 270 } 271 272 long ppc_del_hwdebug(struct task_struct *child, long data) 273 { 274 #ifdef CONFIG_HAVE_HW_BREAKPOINT 275 int ret = 0; 276 struct thread_struct *thread = &child->thread; 277 struct perf_event *bp; 278 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 279 if (data < 1 || data > nr_wp_slots()) 280 return -EINVAL; 281 282 #ifdef CONFIG_HAVE_HW_BREAKPOINT 283 bp = thread->ptrace_bps[data - 1]; 284 if (bp) { 285 unregister_hw_breakpoint(bp); 286 thread->ptrace_bps[data - 1] = NULL; 287 } else { 288 ret = -ENOENT; 289 } 290 return ret; 291 #else /* CONFIG_HAVE_HW_BREAKPOINT */ 292 if (!(child->thread.hw_brk[data - 1].flags & HW_BRK_FLAG_DISABLED) && 293 child->thread.hw_brk[data - 1].address == 0) 294 return -ENOENT; 295 296 child->thread.hw_brk[data - 1].address = 0; 297 child->thread.hw_brk[data - 1].type = 0; 298 child->thread.hw_brk[data - 1].flags = 0; 299 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 300 301 return 0; 302 } 303