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
76static void __kprobes
77emulate_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
105static void __kprobes
106emulate_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
135static void __kprobes
136emulate_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
162static void __kprobes
163emulate_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
197static void __kprobes
198emulate_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
224static void __kprobes
225emulate_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
254static void __kprobes
255emulate_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
274static void __kprobes
275emulate_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
305const 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
344const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL};
345