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 = 1; 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 } 61 62 int ptrace_get_debugreg(struct task_struct *child, unsigned long addr, 63 unsigned long __user *datalp) 64 { 65 unsigned long dabr_fake; 66 67 /* We only support one DABR and no IABRS at the moment */ 68 if (addr > 0) 69 return -EINVAL; 70 dabr_fake = ((child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | 71 (child->thread.hw_brk.type & HW_BRK_TYPE_DABR)); 72 return put_user(dabr_fake, datalp); 73 } 74 75 int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, unsigned long data) 76 { 77 #ifdef CONFIG_HAVE_HW_BREAKPOINT 78 int ret; 79 struct thread_struct *thread = &task->thread; 80 struct perf_event *bp; 81 struct perf_event_attr attr; 82 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 83 bool set_bp = true; 84 struct arch_hw_breakpoint hw_brk; 85 86 /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). 87 * For embedded processors we support one DAC and no IAC's at the 88 * moment. 89 */ 90 if (addr > 0) 91 return -EINVAL; 92 93 /* The bottom 3 bits in dabr are flags */ 94 if ((data & ~0x7UL) >= TASK_SIZE) 95 return -EIO; 96 97 /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. 98 * It was assumed, on previous implementations, that 3 bits were 99 * passed together with the data address, fitting the design of the 100 * DABR register, as follows: 101 * 102 * bit 0: Read flag 103 * bit 1: Write flag 104 * bit 2: Breakpoint translation 105 * 106 * Thus, we use them here as so. 107 */ 108 109 /* Ensure breakpoint translation bit is set */ 110 if (data && !(data & HW_BRK_TYPE_TRANSLATE)) 111 return -EIO; 112 hw_brk.address = data & (~HW_BRK_TYPE_DABR); 113 hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL; 114 hw_brk.len = DABR_MAX_LEN; 115 hw_brk.hw_len = DABR_MAX_LEN; 116 set_bp = (data) && (hw_brk.type & HW_BRK_TYPE_RDWR); 117 #ifdef CONFIG_HAVE_HW_BREAKPOINT 118 bp = thread->ptrace_bps[0]; 119 if (!set_bp) { 120 if (bp) { 121 unregister_hw_breakpoint(bp); 122 thread->ptrace_bps[0] = NULL; 123 } 124 return 0; 125 } 126 if (bp) { 127 attr = bp->attr; 128 attr.bp_addr = hw_brk.address; 129 attr.bp_len = DABR_MAX_LEN; 130 arch_bp_generic_fields(hw_brk.type, &attr.bp_type); 131 132 /* Enable breakpoint */ 133 attr.disabled = false; 134 135 ret = modify_user_hw_breakpoint(bp, &attr); 136 if (ret) 137 return ret; 138 139 thread->ptrace_bps[0] = bp; 140 thread->hw_brk = hw_brk; 141 return 0; 142 } 143 144 /* Create a new breakpoint request if one doesn't exist already */ 145 hw_breakpoint_init(&attr); 146 attr.bp_addr = hw_brk.address; 147 attr.bp_len = DABR_MAX_LEN; 148 arch_bp_generic_fields(hw_brk.type, 149 &attr.bp_type); 150 151 thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, 152 ptrace_triggered, NULL, task); 153 if (IS_ERR(bp)) { 154 thread->ptrace_bps[0] = NULL; 155 return PTR_ERR(bp); 156 } 157 158 #else /* !CONFIG_HAVE_HW_BREAKPOINT */ 159 if (set_bp && (!ppc_breakpoint_available())) 160 return -ENODEV; 161 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 162 task->thread.hw_brk = hw_brk; 163 return 0; 164 } 165 166 long ppc_set_hwdebug(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) 167 { 168 #ifdef CONFIG_HAVE_HW_BREAKPOINT 169 int len = 0; 170 struct thread_struct *thread = &child->thread; 171 struct perf_event *bp; 172 struct perf_event_attr attr; 173 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 174 struct arch_hw_breakpoint brk; 175 176 if (bp_info->version != 1) 177 return -ENOTSUPP; 178 /* 179 * We only support one data breakpoint 180 */ 181 if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 || 182 (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 || 183 bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) 184 return -EINVAL; 185 186 if ((unsigned long)bp_info->addr >= TASK_SIZE) 187 return -EIO; 188 189 brk.address = bp_info->addr & ~HW_BREAKPOINT_ALIGN; 190 brk.type = HW_BRK_TYPE_TRANSLATE; 191 brk.len = DABR_MAX_LEN; 192 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) 193 brk.type |= HW_BRK_TYPE_READ; 194 if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) 195 brk.type |= HW_BRK_TYPE_WRITE; 196 #ifdef CONFIG_HAVE_HW_BREAKPOINT 197 if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) 198 len = bp_info->addr2 - bp_info->addr; 199 else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT) 200 len = 1; 201 else 202 return -EINVAL; 203 bp = thread->ptrace_bps[0]; 204 if (bp) 205 return -ENOSPC; 206 207 /* Create a new breakpoint request if one doesn't exist already */ 208 hw_breakpoint_init(&attr); 209 attr.bp_addr = (unsigned long)bp_info->addr; 210 attr.bp_len = len; 211 arch_bp_generic_fields(brk.type, &attr.bp_type); 212 213 bp = register_user_hw_breakpoint(&attr, ptrace_triggered, NULL, child); 214 thread->ptrace_bps[0] = bp; 215 if (IS_ERR(bp)) { 216 thread->ptrace_bps[0] = NULL; 217 return PTR_ERR(bp); 218 } 219 220 return 1; 221 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 222 223 if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) 224 return -EINVAL; 225 226 if (child->thread.hw_brk.address) 227 return -ENOSPC; 228 229 if (!ppc_breakpoint_available()) 230 return -ENODEV; 231 232 child->thread.hw_brk = brk; 233 234 return 1; 235 } 236 237 long ppc_del_hwdebug(struct task_struct *child, long data) 238 { 239 #ifdef CONFIG_HAVE_HW_BREAKPOINT 240 int ret = 0; 241 struct thread_struct *thread = &child->thread; 242 struct perf_event *bp; 243 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 244 if (data != 1) 245 return -EINVAL; 246 247 #ifdef CONFIG_HAVE_HW_BREAKPOINT 248 bp = thread->ptrace_bps[0]; 249 if (bp) { 250 unregister_hw_breakpoint(bp); 251 thread->ptrace_bps[0] = NULL; 252 } else { 253 ret = -ENOENT; 254 } 255 return ret; 256 #else /* CONFIG_HAVE_HW_BREAKPOINT */ 257 if (child->thread.hw_brk.address == 0) 258 return -ENOENT; 259 260 child->thread.hw_brk.address = 0; 261 child->thread.hw_brk.type = 0; 262 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 263 264 return 0; 265 } 266