xref: /linux/arch/arm/probes/kprobes/actions-arm.c (revision e0bf6c5ca2d3281f231c5f0c9bf145e9513644de)
1 /*
2  * arch/arm/probes/kprobes/actions-arm.c
3  *
4  * Copyright (C) 2006, 2007 Motorola Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  */
15 
16 /*
17  * We do not have hardware single-stepping on ARM, This
18  * effort is further complicated by the ARM not having a
19  * "next PC" register.  Instructions that change the PC
20  * can't be safely single-stepped in a MP environment, so
21  * we have a lot of work to do:
22  *
23  * In the prepare phase:
24  *   *) If it is an instruction that does anything
25  *      with the CPU mode, we reject it for a kprobe.
26  *      (This is out of laziness rather than need.  The
27  *      instructions could be simulated.)
28  *
29  *   *) Otherwise, decode the instruction rewriting its
30  *      registers to take fixed, ordered registers and
31  *      setting a handler for it to run the instruction.
32  *
33  * In the execution phase by an instruction's handler:
34  *
35  *   *) If the PC is written to by the instruction, the
36  *      instruction must be fully simulated in software.
37  *
38  *   *) Otherwise, a modified form of the instruction is
39  *      directly executed.  Its handler calls the
40  *      instruction in insn[0].  In insn[1] is a
41  *      "mov pc, lr" to return.
42  *
43  *      Before calling, load up the reordered registers
44  *      from the original instruction's registers.  If one
45  *      of the original input registers is the PC, compute
46  *      and adjust the appropriate input register.
47  *
48  *	After call completes, copy the output registers to
49  *      the original instruction's original registers.
50  *
51  * We don't use a real breakpoint instruction since that
52  * would have us in the kernel go from SVC mode to SVC
53  * mode losing the link register.  Instead we use an
54  * undefined instruction.  To simplify processing, the
55  * undefined instruction used for kprobes must be reserved
56  * exclusively for kprobes use.
57  *
58  * TODO: ifdef out some instruction decoding based on architecture.
59  */
60 
61 #include <linux/kernel.h>
62 #include <linux/kprobes.h>
63 #include <linux/ptrace.h>
64 
65 #include "../decode-arm.h"
66 #include "core.h"
67 #include "checkers.h"
68 
69 #if  __LINUX_ARM_ARCH__ >= 6
70 #define BLX(reg)	"blx	"reg"		\n\t"
71 #else
72 #define BLX(reg)	"mov	lr, pc		\n\t"	\
73 			"mov	pc, "reg"	\n\t"
74 #endif
75 
76 static void __kprobes
77 emulate_ldrdstrd(probes_opcode_t insn,
78 	struct arch_probes_insn *asi, struct pt_regs *regs)
79 {
80 	unsigned long pc = regs->ARM_pc + 4;
81 	int rt = (insn >> 12) & 0xf;
82 	int rn = (insn >> 16) & 0xf;
83 	int rm = insn & 0xf;
84 
85 	register unsigned long rtv asm("r0") = regs->uregs[rt];
86 	register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
87 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
88 							  : regs->uregs[rn];
89 	register unsigned long rmv asm("r3") = regs->uregs[rm];
90 
91 	__asm__ __volatile__ (
92 		BLX("%[fn]")
93 		: "=r" (rtv), "=r" (rt2v), "=r" (rnv)
94 		: "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
95 		  [fn] "r" (asi->insn_fn)
96 		: "lr", "memory", "cc"
97 	);
98 
99 	regs->uregs[rt] = rtv;
100 	regs->uregs[rt+1] = rt2v;
101 	if (is_writeback(insn))
102 		regs->uregs[rn] = rnv;
103 }
104 
105 static void __kprobes
106 emulate_ldr(probes_opcode_t insn,
107 	struct arch_probes_insn *asi, struct pt_regs *regs)
108 {
109 	unsigned long pc = regs->ARM_pc + 4;
110 	int rt = (insn >> 12) & 0xf;
111 	int rn = (insn >> 16) & 0xf;
112 	int rm = insn & 0xf;
113 
114 	register unsigned long rtv asm("r0");
115 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
116 							  : regs->uregs[rn];
117 	register unsigned long rmv asm("r3") = regs->uregs[rm];
118 
119 	__asm__ __volatile__ (
120 		BLX("%[fn]")
121 		: "=r" (rtv), "=r" (rnv)
122 		: "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
123 		: "lr", "memory", "cc"
124 	);
125 
126 	if (rt == 15)
127 		load_write_pc(rtv, regs);
128 	else
129 		regs->uregs[rt] = rtv;
130 
131 	if (is_writeback(insn))
132 		regs->uregs[rn] = rnv;
133 }
134 
135 static void __kprobes
136 emulate_str(probes_opcode_t insn,
137 	struct arch_probes_insn *asi, struct pt_regs *regs)
138 {
139 	unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
140 	unsigned long rnpc = regs->ARM_pc + 4;
141 	int rt = (insn >> 12) & 0xf;
142 	int rn = (insn >> 16) & 0xf;
143 	int rm = insn & 0xf;
144 
145 	register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
146 							  : regs->uregs[rt];
147 	register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
148 							  : regs->uregs[rn];
149 	register unsigned long rmv asm("r3") = regs->uregs[rm];
150 
151 	__asm__ __volatile__ (
152 		BLX("%[fn]")
153 		: "=r" (rnv)
154 		: "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
155 		: "lr", "memory", "cc"
156 	);
157 
158 	if (is_writeback(insn))
159 		regs->uregs[rn] = rnv;
160 }
161 
162 static void __kprobes
163 emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
164 	struct arch_probes_insn *asi, struct pt_regs *regs)
165 {
166 	unsigned long pc = regs->ARM_pc + 4;
167 	int rd = (insn >> 12) & 0xf;
168 	int rn = (insn >> 16) & 0xf;
169 	int rm = insn & 0xf;
170 	int rs = (insn >> 8) & 0xf;
171 
172 	register unsigned long rdv asm("r0") = regs->uregs[rd];
173 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
174 							  : regs->uregs[rn];
175 	register unsigned long rmv asm("r3") = (rm == 15) ? pc
176 							  : regs->uregs[rm];
177 	register unsigned long rsv asm("r1") = regs->uregs[rs];
178 	unsigned long cpsr = regs->ARM_cpsr;
179 
180 	__asm__ __volatile__ (
181 		"msr	cpsr_fs, %[cpsr]	\n\t"
182 		BLX("%[fn]")
183 		"mrs	%[cpsr], cpsr		\n\t"
184 		: "=r" (rdv), [cpsr] "=r" (cpsr)
185 		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
186 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
187 		: "lr", "memory", "cc"
188 	);
189 
190 	if (rd == 15)
191 		alu_write_pc(rdv, regs);
192 	else
193 		regs->uregs[rd] = rdv;
194 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
195 }
196 
197 static void __kprobes
198 emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
199 	struct arch_probes_insn *asi, struct pt_regs *regs)
200 {
201 	int rd = (insn >> 12) & 0xf;
202 	int rn = (insn >> 16) & 0xf;
203 	int rm = insn & 0xf;
204 
205 	register unsigned long rdv asm("r0") = regs->uregs[rd];
206 	register unsigned long rnv asm("r2") = regs->uregs[rn];
207 	register unsigned long rmv asm("r3") = regs->uregs[rm];
208 	unsigned long cpsr = regs->ARM_cpsr;
209 
210 	__asm__ __volatile__ (
211 		"msr	cpsr_fs, %[cpsr]	\n\t"
212 		BLX("%[fn]")
213 		"mrs	%[cpsr], cpsr		\n\t"
214 		: "=r" (rdv), [cpsr] "=r" (cpsr)
215 		: "0" (rdv), "r" (rnv), "r" (rmv),
216 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
217 		: "lr", "memory", "cc"
218 	);
219 
220 	regs->uregs[rd] = rdv;
221 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
222 }
223 
224 static void __kprobes
225 emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
226 	struct arch_probes_insn *asi,
227 	struct pt_regs *regs)
228 {
229 	int rd = (insn >> 16) & 0xf;
230 	int rn = (insn >> 12) & 0xf;
231 	int rm = insn & 0xf;
232 	int rs = (insn >> 8) & 0xf;
233 
234 	register unsigned long rdv asm("r2") = regs->uregs[rd];
235 	register unsigned long rnv asm("r0") = regs->uregs[rn];
236 	register unsigned long rmv asm("r3") = regs->uregs[rm];
237 	register unsigned long rsv asm("r1") = regs->uregs[rs];
238 	unsigned long cpsr = regs->ARM_cpsr;
239 
240 	__asm__ __volatile__ (
241 		"msr	cpsr_fs, %[cpsr]	\n\t"
242 		BLX("%[fn]")
243 		"mrs	%[cpsr], cpsr		\n\t"
244 		: "=r" (rdv), [cpsr] "=r" (cpsr)
245 		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
246 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
247 		: "lr", "memory", "cc"
248 	);
249 
250 	regs->uregs[rd] = rdv;
251 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
252 }
253 
254 static void __kprobes
255 emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
256 	struct arch_probes_insn *asi, struct pt_regs *regs)
257 {
258 	int rd = (insn >> 12) & 0xf;
259 	int rm = insn & 0xf;
260 
261 	register unsigned long rdv asm("r0") = regs->uregs[rd];
262 	register unsigned long rmv asm("r3") = regs->uregs[rm];
263 
264 	__asm__ __volatile__ (
265 		BLX("%[fn]")
266 		: "=r" (rdv)
267 		: "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
268 		: "lr", "memory", "cc"
269 	);
270 
271 	regs->uregs[rd] = rdv;
272 }
273 
274 static void __kprobes
275 emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
276 	struct arch_probes_insn *asi,
277 	struct pt_regs *regs)
278 {
279 	int rdlo = (insn >> 12) & 0xf;
280 	int rdhi = (insn >> 16) & 0xf;
281 	int rn = insn & 0xf;
282 	int rm = (insn >> 8) & 0xf;
283 
284 	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
285 	register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
286 	register unsigned long rnv asm("r3") = regs->uregs[rn];
287 	register unsigned long rmv asm("r1") = regs->uregs[rm];
288 	unsigned long cpsr = regs->ARM_cpsr;
289 
290 	__asm__ __volatile__ (
291 		"msr	cpsr_fs, %[cpsr]	\n\t"
292 		BLX("%[fn]")
293 		"mrs	%[cpsr], cpsr		\n\t"
294 		: "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
295 		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
296 		  "2" (cpsr), [fn] "r" (asi->insn_fn)
297 		: "lr", "memory", "cc"
298 	);
299 
300 	regs->uregs[rdlo] = rdlov;
301 	regs->uregs[rdhi] = rdhiv;
302 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
303 }
304 
305 const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
306 	[PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
307 	[PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
308 	[PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
309 	[PROBES_MRS] = {.handler = simulate_mrs},
310 	[PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
311 	[PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
312 	[PROBES_SATURATING_ARITHMETIC] = {
313 		.handler = emulate_rd12rn16rm0_rwflags_nopc},
314 	[PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
315 	[PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
316 	[PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
317 	[PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
318 	[PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
319 	[PROBES_LOAD] = {.handler = emulate_ldr},
320 	[PROBES_STORE_EXTRA] = {.handler = emulate_str},
321 	[PROBES_STORE] = {.handler = emulate_str},
322 	[PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
323 	[PROBES_DATA_PROCESSING_REG] = {
324 		.handler = emulate_rd12rn16rm0rs8_rwflags},
325 	[PROBES_DATA_PROCESSING_IMM] = {
326 		.handler = emulate_rd12rn16rm0rs8_rwflags},
327 	[PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
328 	[PROBES_SEV] = {.handler = probes_emulate_none},
329 	[PROBES_WFE] = {.handler = probes_simulate_nop},
330 	[PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
331 	[PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
332 	[PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
333 	[PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
334 	[PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
335 	[PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
336 	[PROBES_MUL_ADD_LONG] = {
337 		.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
338 	[PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
339 	[PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
340 	[PROBES_BRANCH] = {.handler = simulate_bbl},
341 	[PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
342 };
343 
344 const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL};
345