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