aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuentin Barnes <qbarnes@gmail.com>2007-06-11 18:20:10 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 10:25:16 -0500
commit35aa1df4328340f38edc46f00837f08d33d49f63 (patch)
tree8ed273b1d39462282fadd4c854f17bf545024528
parent9b73e76f3cf63379dcf45fcd4f112f5812418d0a (diff)
ARM kprobes: instruction single-stepping support
This is the code implementing instruction single-stepping for kprobes on ARM. To get around the limitation of no Next-PC and no hardware single- stepping, all kprobe'd instructions are split into three camps: simulation, emulation, and rejected. "Simulated" instructions are those instructions which behavior is reproduced by straight C code. "Emulated" instructions are ones that are copied, slightly altered and executed directly in the instruction slot to reproduce their behavior. "Rejected" instructions are ones that could be simulated, but work hasn't been put into simulating them. These instructions should be very rare, if not unencountered, in the kernel. If ever needed, code could be added to simulate them. One might wonder why this and the ptrace singlestep facility are not sharing some code. Both approaches are fundamentally different because the ptrace code regains control after the stepped instruction by installing a breakpoint after the instruction itself, and possibly at the location where the instruction might be branching to, instead of simulating or emulating the target instruction. The ptrace approach isn't suitable for kprobes because the breakpoints would have to be moved back, and the icache flushed, everytime the probe is hit to let normal code execution resume, which would have a significant performance impact. It is also racy on SMP since another CPU could, with the right timing, sail through the probe point without being caught. Because ptrace single-stepping always result in a different process to be scheduled, the concern for performance is much less significant. On the other hand, the kprobes approach isn't (currently) suitable for ptrace because it has no provision for proper user space memory protection and translation, and even if that was implemented, the gain wouldn't be worth the added complexity in the ptrace path compared to the current approach. So, until kprobes does support user space, both kprobes and ptrace are best kept independent and separate. Signed-off-by: Quentin Barnes <qbarnes@gmail.com> Signed-off-by: Abhishek Sagar <sagar.abhishek@gmail.com> Signed-off-by: Nicolas Pitre <nico@marvell.com>
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/kprobes-decode.c1529
-rw-r--r--include/asm-arm/kprobes.h43
3 files changed, 1573 insertions, 0 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 593b56509f4f..9e0eebacd3d9 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ISA_DMA) += dma-isa.o
19obj-$(CONFIG_PCI) += bios32.o isa.o 19obj-$(CONFIG_PCI) += bios32.o isa.o
20obj-$(CONFIG_SMP) += smp.o 20obj-$(CONFIG_SMP) += smp.o
21obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 21obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
22obj-$(CONFIG_KPROBES) += kprobes-decode.o
22obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o 23obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
23 24
24obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o 25obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
new file mode 100644
index 000000000000..d51bc8b60557
--- /dev/null
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -0,0 +1,1529 @@
1/*
2 * arch/arm/kernel/kprobes-decode.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 * If it is a conditional instruction, the handler
38 * will use insn[0] to copy its condition code to
39 * set r0 to 1 and insn[1] to "mov pc, lr" to return.
40 *
41 * *) Otherwise, a modified form of the instruction is
42 * directly executed. Its handler calls the
43 * instruction in insn[0]. In insn[1] is a
44 * "mov pc, lr" to return.
45 *
46 * Before calling, load up the reordered registers
47 * from the original instruction's registers. If one
48 * of the original input registers is the PC, compute
49 * and adjust the appropriate input register.
50 *
51 * After call completes, copy the output registers to
52 * the original instruction's original registers.
53 *
54 * We don't use a real breakpoint instruction since that
55 * would have us in the kernel go from SVC mode to SVC
56 * mode losing the link register. Instead we use an
57 * undefined instruction. To simplify processing, the
58 * undefined instruction used for kprobes must be reserved
59 * exclusively for kprobes use.
60 *
61 * TODO: ifdef out some instruction decoding based on architecture.
62 */
63
64#include <linux/kernel.h>
65#include <linux/kprobes.h>
66
67#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
68
69#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
70
71#define PSR_fs (PSR_f|PSR_s)
72
73#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */
74#define SET_R0_TRUE_INSTRUCTION 0xe3a00001 /* mov r0, #1 */
75
76#define truecc_insn(insn) (((insn) & 0xf0000000) | \
77 (SET_R0_TRUE_INSTRUCTION & 0x0fffffff))
78
79typedef long (insn_0arg_fn_t)(void);
80typedef long (insn_1arg_fn_t)(long);
81typedef long (insn_2arg_fn_t)(long, long);
82typedef long (insn_3arg_fn_t)(long, long, long);
83typedef long (insn_4arg_fn_t)(long, long, long, long);
84typedef long long (insn_llret_0arg_fn_t)(void);
85typedef long long (insn_llret_3arg_fn_t)(long, long, long);
86typedef long long (insn_llret_4arg_fn_t)(long, long, long, long);
87
88union reg_pair {
89 long long dr;
90#ifdef __LITTLE_ENDIAN
91 struct { long r0, r1; };
92#else
93 struct { long r1, r0; };
94#endif
95};
96
97/*
98 * For STR and STM instructions, an ARM core may choose to use either
99 * a +8 or a +12 displacement from the current instruction's address.
100 * Whichever value is chosen for a given core, it must be the same for
101 * both instructions and may not change. This function measures it.
102 */
103
104static int str_pc_offset;
105
106static void __init find_str_pc_offset(void)
107{
108 int addr, scratch, ret;
109
110 __asm__ (
111 "sub %[ret], pc, #4 \n\t"
112 "str pc, %[addr] \n\t"
113 "ldr %[scr], %[addr] \n\t"
114 "sub %[ret], %[scr], %[ret] \n\t"
115 : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
116
117 str_pc_offset = ret;
118}
119
120/*
121 * The insnslot_?arg_r[w]flags() functions below are to keep the
122 * msr -> *fn -> mrs instruction sequences indivisible so that
123 * the state of the CPSR flags aren't inadvertently modified
124 * just before or just after the call.
125 */
126
127static inline long __kprobes
128insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn)
129{
130 register long ret asm("r0");
131
132 __asm__ __volatile__ (
133 "msr cpsr_fs, %[cpsr] \n\t"
134 "mov lr, pc \n\t"
135 "mov pc, %[fn] \n\t"
136 : "=r" (ret)
137 : [cpsr] "r" (cpsr), [fn] "r" (fn)
138 : "lr", "cc"
139 );
140 return ret;
141}
142
143static inline long long __kprobes
144insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn)
145{
146 register long ret0 asm("r0");
147 register long ret1 asm("r1");
148 union reg_pair fnr;
149
150 __asm__ __volatile__ (
151 "msr cpsr_fs, %[cpsr] \n\t"
152 "mov lr, pc \n\t"
153 "mov pc, %[fn] \n\t"
154 : "=r" (ret0), "=r" (ret1)
155 : [cpsr] "r" (cpsr), [fn] "r" (fn)
156 : "lr", "cc"
157 );
158 fnr.r0 = ret0;
159 fnr.r1 = ret1;
160 return fnr.dr;
161}
162
163static inline long __kprobes
164insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn)
165{
166 register long rr0 asm("r0") = r0;
167 register long ret asm("r0");
168
169 __asm__ __volatile__ (
170 "msr cpsr_fs, %[cpsr] \n\t"
171 "mov lr, pc \n\t"
172 "mov pc, %[fn] \n\t"
173 : "=r" (ret)
174 : "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn)
175 : "lr", "cc"
176 );
177 return ret;
178}
179
180static inline long __kprobes
181insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn)
182{
183 register long rr0 asm("r0") = r0;
184 register long rr1 asm("r1") = r1;
185 register long ret asm("r0");
186
187 __asm__ __volatile__ (
188 "msr cpsr_fs, %[cpsr] \n\t"
189 "mov lr, pc \n\t"
190 "mov pc, %[fn] \n\t"
191 : "=r" (ret)
192 : "0" (rr0), "r" (rr1),
193 [cpsr] "r" (cpsr), [fn] "r" (fn)
194 : "lr", "cc"
195 );
196 return ret;
197}
198
199static inline long __kprobes
200insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn)
201{
202 register long rr0 asm("r0") = r0;
203 register long rr1 asm("r1") = r1;
204 register long rr2 asm("r2") = r2;
205 register long ret asm("r0");
206
207 __asm__ __volatile__ (
208 "msr cpsr_fs, %[cpsr] \n\t"
209 "mov lr, pc \n\t"
210 "mov pc, %[fn] \n\t"
211 : "=r" (ret)
212 : "0" (rr0), "r" (rr1), "r" (rr2),
213 [cpsr] "r" (cpsr), [fn] "r" (fn)
214 : "lr", "cc"
215 );
216 return ret;
217}
218
219static inline long long __kprobes
220insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr,
221 insn_llret_3arg_fn_t *fn)
222{
223 register long rr0 asm("r0") = r0;
224 register long rr1 asm("r1") = r1;
225 register long rr2 asm("r2") = r2;
226 register long ret0 asm("r0");
227 register long ret1 asm("r1");
228 union reg_pair fnr;
229
230 __asm__ __volatile__ (
231 "msr cpsr_fs, %[cpsr] \n\t"
232 "mov lr, pc \n\t"
233 "mov pc, %[fn] \n\t"
234 : "=r" (ret0), "=r" (ret1)
235 : "0" (rr0), "r" (rr1), "r" (rr2),
236 [cpsr] "r" (cpsr), [fn] "r" (fn)
237 : "lr", "cc"
238 );
239 fnr.r0 = ret0;
240 fnr.r1 = ret1;
241 return fnr.dr;
242}
243
244static inline long __kprobes
245insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr,
246 insn_4arg_fn_t *fn)
247{
248 register long rr0 asm("r0") = r0;
249 register long rr1 asm("r1") = r1;
250 register long rr2 asm("r2") = r2;
251 register long rr3 asm("r3") = r3;
252 register long ret asm("r0");
253
254 __asm__ __volatile__ (
255 "msr cpsr_fs, %[cpsr] \n\t"
256 "mov lr, pc \n\t"
257 "mov pc, %[fn] \n\t"
258 : "=r" (ret)
259 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
260 [cpsr] "r" (cpsr), [fn] "r" (fn)
261 : "lr", "cc"
262 );
263 return ret;
264}
265
266static inline long __kprobes
267insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn)
268{
269 register long rr0 asm("r0") = r0;
270 register long ret asm("r0");
271 long oldcpsr = *cpsr;
272 long newcpsr;
273
274 __asm__ __volatile__ (
275 "msr cpsr_fs, %[oldcpsr] \n\t"
276 "mov lr, pc \n\t"
277 "mov pc, %[fn] \n\t"
278 "mrs %[newcpsr], cpsr \n\t"
279 : "=r" (ret), [newcpsr] "=r" (newcpsr)
280 : "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
281 : "lr", "cc"
282 );
283 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
284 return ret;
285}
286
287static inline long __kprobes
288insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn)
289{
290 register long rr0 asm("r0") = r0;
291 register long rr1 asm("r1") = r1;
292 register long ret asm("r0");
293 long oldcpsr = *cpsr;
294 long newcpsr;
295
296 __asm__ __volatile__ (
297 "msr cpsr_fs, %[oldcpsr] \n\t"
298 "mov lr, pc \n\t"
299 "mov pc, %[fn] \n\t"
300 "mrs %[newcpsr], cpsr \n\t"
301 : "=r" (ret), [newcpsr] "=r" (newcpsr)
302 : "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
303 : "lr", "cc"
304 );
305 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
306 return ret;
307}
308
309static inline long __kprobes
310insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr,
311 insn_3arg_fn_t *fn)
312{
313 register long rr0 asm("r0") = r0;
314 register long rr1 asm("r1") = r1;
315 register long rr2 asm("r2") = r2;
316 register long ret asm("r0");
317 long oldcpsr = *cpsr;
318 long newcpsr;
319
320 __asm__ __volatile__ (
321 "msr cpsr_fs, %[oldcpsr] \n\t"
322 "mov lr, pc \n\t"
323 "mov pc, %[fn] \n\t"
324 "mrs %[newcpsr], cpsr \n\t"
325 : "=r" (ret), [newcpsr] "=r" (newcpsr)
326 : "0" (rr0), "r" (rr1), "r" (rr2),
327 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
328 : "lr", "cc"
329 );
330 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
331 return ret;
332}
333
334static inline long __kprobes
335insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
336 insn_4arg_fn_t *fn)
337{
338 register long rr0 asm("r0") = r0;
339 register long rr1 asm("r1") = r1;
340 register long rr2 asm("r2") = r2;
341 register long rr3 asm("r3") = r3;
342 register long ret asm("r0");
343 long oldcpsr = *cpsr;
344 long newcpsr;
345
346 __asm__ __volatile__ (
347 "msr cpsr_fs, %[oldcpsr] \n\t"
348 "mov lr, pc \n\t"
349 "mov pc, %[fn] \n\t"
350 "mrs %[newcpsr], cpsr \n\t"
351 : "=r" (ret), [newcpsr] "=r" (newcpsr)
352 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
353 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
354 : "lr", "cc"
355 );
356 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
357 return ret;
358}
359
360static inline long long __kprobes
361insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
362 insn_llret_4arg_fn_t *fn)
363{
364 register long rr0 asm("r0") = r0;
365 register long rr1 asm("r1") = r1;
366 register long rr2 asm("r2") = r2;
367 register long rr3 asm("r3") = r3;
368 register long ret0 asm("r0");
369 register long ret1 asm("r1");
370 long oldcpsr = *cpsr;
371 long newcpsr;
372 union reg_pair fnr;
373
374 __asm__ __volatile__ (
375 "msr cpsr_fs, %[oldcpsr] \n\t"
376 "mov lr, pc \n\t"
377 "mov pc, %[fn] \n\t"
378 "mrs %[newcpsr], cpsr \n\t"
379 : "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr)
380 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
381 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
382 : "lr", "cc"
383 );
384 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
385 fnr.r0 = ret0;
386 fnr.r1 = ret1;
387 return fnr.dr;
388}
389
390/*
391 * To avoid the complications of mimicing single-stepping on a
392 * processor without a Next-PC or a single-step mode, and to
393 * avoid having to deal with the side-effects of boosting, we
394 * simulate or emulate (almost) all ARM instructions.
395 *
396 * "Simulation" is where the instruction's behavior is duplicated in
397 * C code. "Emulation" is where the original instruction is rewritten
398 * and executed, often by altering its registers.
399 *
400 * By having all behavior of the kprobe'd instruction completed before
401 * returning from the kprobe_handler(), all locks (scheduler and
402 * interrupt) can safely be released. There is no need for secondary
403 * breakpoints, no race with MP or preemptable kernels, nor having to
404 * clean up resources counts at a later time impacting overall system
405 * performance. By rewriting the instruction, only the minimum registers
406 * need to be loaded and saved back optimizing performance.
407 *
408 * Calling the insnslot_*_rwflags version of a function doesn't hurt
409 * anything even when the CPSR flags aren't updated by the
410 * instruction. It's just a little slower in return for saving
411 * a little space by not having a duplicate function that doesn't
412 * update the flags. (The same optimization can be said for
413 * instructions that do or don't perform register writeback)
414 * Also, instructions can either read the flags, only write the
415 * flags, or read and write the flags. To save combinations
416 * rather than for sheer performance, flag functions just assume
417 * read and write of flags.
418 */
419
420static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
421{
422 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
423 kprobe_opcode_t insn = p->opcode;
424 long iaddr = (long)p->addr;
425 int disp = branch_displacement(insn);
426
427 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
428 return;
429
430 if (insn & (1 << 24))
431 regs->ARM_lr = iaddr + 4;
432
433 regs->ARM_pc = iaddr + 8 + disp;
434}
435
436static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
437{
438 kprobe_opcode_t insn = p->opcode;
439 long iaddr = (long)p->addr;
440 int disp = branch_displacement(insn);
441
442 regs->ARM_lr = iaddr + 4;
443 regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
444 regs->ARM_cpsr |= PSR_T_BIT;
445}
446
447static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
448{
449 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
450 kprobe_opcode_t insn = p->opcode;
451 int rm = insn & 0xf;
452 long rmv = regs->uregs[rm];
453
454 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
455 return;
456
457 if (insn & (1 << 5))
458 regs->ARM_lr = (long)p->addr + 4;
459
460 regs->ARM_pc = rmv & ~0x1;
461 regs->ARM_cpsr &= ~PSR_T_BIT;
462 if (rmv & 0x1)
463 regs->ARM_cpsr |= PSR_T_BIT;
464}
465
466static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
467{
468 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
469 kprobe_opcode_t insn = p->opcode;
470 int rn = (insn >> 16) & 0xf;
471 int lbit = insn & (1 << 20);
472 int wbit = insn & (1 << 21);
473 int ubit = insn & (1 << 23);
474 int pbit = insn & (1 << 24);
475 long *addr = (long *)regs->uregs[rn];
476 int reg_bit_vector;
477 int reg_count;
478
479 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
480 return;
481
482 reg_count = 0;
483 reg_bit_vector = insn & 0xffff;
484 while (reg_bit_vector) {
485 reg_bit_vector &= (reg_bit_vector - 1);
486 ++reg_count;
487 }
488
489 if (!ubit)
490 addr -= reg_count;
491 addr += (!pbit ^ !ubit);
492
493 reg_bit_vector = insn & 0xffff;
494 while (reg_bit_vector) {
495 int reg = __ffs(reg_bit_vector);
496 reg_bit_vector &= (reg_bit_vector - 1);
497 if (lbit)
498 regs->uregs[reg] = *addr++;
499 else
500 *addr++ = regs->uregs[reg];
501 }
502
503 if (wbit) {
504 if (!ubit)
505 addr -= reg_count;
506 addr -= (!pbit ^ !ubit);
507 regs->uregs[rn] = (long)addr;
508 }
509}
510
511static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
512{
513 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
514
515 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
516 return;
517
518 regs->ARM_pc = (long)p->addr + str_pc_offset;
519 simulate_ldm1stm1(p, regs);
520 regs->ARM_pc = (long)p->addr + 4;
521}
522
523static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
524{
525 regs->uregs[12] = regs->uregs[13];
526}
527
528static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs)
529{
530 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
531 kprobe_opcode_t insn = p->opcode;
532 int rn = (insn >> 16) & 0xf;
533 long rnv = regs->uregs[rn];
534
535 /* Save Rn in case of writeback. */
536 regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
537}
538
539static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
540{
541 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
542 kprobe_opcode_t insn = p->opcode;
543 int rd = (insn >> 12) & 0xf;
544 int rn = (insn >> 16) & 0xf;
545 int rm = insn & 0xf; /* rm may be invalid, don't care. */
546
547 /* Not following the C calling convention here, so need asm(). */
548 __asm__ __volatile__ (
549 "ldr r0, %[rn] \n\t"
550 "ldr r1, %[rm] \n\t"
551 "msr cpsr_fs, %[cpsr]\n\t"
552 "mov lr, pc \n\t"
553 "mov pc, %[i_fn] \n\t"
554 "str r0, %[rn] \n\t" /* in case of writeback */
555 "str r2, %[rd0] \n\t"
556 "str r3, %[rd1] \n\t"
557 : [rn] "+m" (regs->uregs[rn]),
558 [rd0] "=m" (regs->uregs[rd]),
559 [rd1] "=m" (regs->uregs[rd+1])
560 : [rm] "m" (regs->uregs[rm]),
561 [cpsr] "r" (regs->ARM_cpsr),
562 [i_fn] "r" (i_fn)
563 : "r0", "r1", "r2", "r3", "lr", "cc"
564 );
565}
566
567static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
568{
569 insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
570 kprobe_opcode_t insn = p->opcode;
571 int rd = (insn >> 12) & 0xf;
572 int rn = (insn >> 16) & 0xf;
573 int rm = insn & 0xf;
574 long rnv = regs->uregs[rn];
575 long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */
576
577 regs->uregs[rn] = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
578 regs->uregs[rd+1],
579 regs->ARM_cpsr, i_fn);
580}
581
582static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
583{
584 insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];
585 kprobe_opcode_t insn = p->opcode;
586 union reg_pair fnr;
587 int rd = (insn >> 12) & 0xf;
588 int rn = (insn >> 16) & 0xf;
589 int rm = insn & 0xf;
590 long rdv;
591 long rnv = regs->uregs[rn];
592 long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */
593 long cpsr = regs->ARM_cpsr;
594
595 fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
596 regs->uregs[rn] = fnr.r0; /* Save Rn in case of writeback. */
597 rdv = fnr.r1;
598
599 if (rd == 15) {
600#if __LINUX_ARM_ARCH__ >= 5
601 cpsr &= ~PSR_T_BIT;
602 if (rdv & 0x1)
603 cpsr |= PSR_T_BIT;
604 regs->ARM_cpsr = cpsr;
605 rdv &= ~0x1;
606#else
607 rdv &= ~0x2;
608#endif
609 }
610 regs->uregs[rd] = rdv;
611}
612
613static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
614{
615 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
616 kprobe_opcode_t insn = p->opcode;
617 long iaddr = (long)p->addr;
618 int rd = (insn >> 12) & 0xf;
619 int rn = (insn >> 16) & 0xf;
620 int rm = insn & 0xf;
621 long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
622 long rnv = (rn == 15) ? iaddr + 8 : regs->uregs[rn];
623 long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */
624
625 /* Save Rn in case of writeback. */
626 regs->uregs[rn] =
627 insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
628}
629
630static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
631{
632 insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
633 kprobe_opcode_t insn = p->opcode;
634 union reg_pair fnr;
635 int rd = (insn >> 12) & 0xf;
636 int rn = (insn >> 16) & 0xf;
637
638 fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
639 regs->uregs[rn] = fnr.r0;
640 regs->uregs[rd] = fnr.r1;
641}
642
643static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
644{
645 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
646 kprobe_opcode_t insn = p->opcode;
647 int rd = (insn >> 12) & 0xf;
648 int rn = (insn >> 16) & 0xf;
649 long rnv = regs->uregs[rn];
650 long rdv = regs->uregs[rd];
651
652 insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
653}
654
655static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
656{
657 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
658 kprobe_opcode_t insn = p->opcode;
659 int rd = (insn >> 12) & 0xf;
660 int rm = insn & 0xf;
661 long rmv = regs->uregs[rm];
662
663 /* Writes Q flag */
664 regs->uregs[rd] = insnslot_1arg_rwflags(rmv, &regs->ARM_cpsr, i_fn);
665}
666
667static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)
668{
669 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
670 kprobe_opcode_t insn = p->opcode;
671 int rd = (insn >> 12) & 0xf;
672 int rn = (insn >> 16) & 0xf;
673 int rm = insn & 0xf;
674 long rnv = regs->uregs[rn];
675 long rmv = regs->uregs[rm];
676
677 /* Reads GE bits */
678 regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);
679}
680
681static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
682{
683 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
684
685 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
686}
687
688static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
689{
690 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
691 kprobe_opcode_t insn = p->opcode;
692 int rd = (insn >> 12) & 0xf;
693
694 regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
695}
696
697static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
698{
699 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
700 kprobe_opcode_t insn = p->opcode;
701 int ird = (insn >> 12) & 0xf;
702
703 insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
704}
705
706static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
707{
708 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
709 kprobe_opcode_t insn = p->opcode;
710 int rn = (insn >> 16) & 0xf;
711 long rnv = regs->uregs[rn];
712
713 insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
714}
715
716static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
717{
718 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
719 kprobe_opcode_t insn = p->opcode;
720 int rd = (insn >> 12) & 0xf;
721 int rm = insn & 0xf;
722 long rmv = regs->uregs[rm];
723
724 regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);
725}
726
727static void __kprobes
728emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
729{
730 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
731 kprobe_opcode_t insn = p->opcode;
732 int rd = (insn >> 12) & 0xf;
733 int rn = (insn >> 16) & 0xf;
734 int rm = insn & 0xf;
735 long rnv = regs->uregs[rn];
736 long rmv = regs->uregs[rm];
737
738 regs->uregs[rd] =
739 insnslot_2arg_rwflags(rnv, rmv, &regs->ARM_cpsr, i_fn);
740}
741
742static void __kprobes
743emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
744{
745 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
746 kprobe_opcode_t insn = p->opcode;
747 int rd = (insn >> 16) & 0xf;
748 int rn = (insn >> 12) & 0xf;
749 int rs = (insn >> 8) & 0xf;
750 int rm = insn & 0xf;
751 long rnv = regs->uregs[rn];
752 long rsv = regs->uregs[rs];
753 long rmv = regs->uregs[rm];
754
755 regs->uregs[rd] =
756 insnslot_3arg_rwflags(rnv, rsv, rmv, &regs->ARM_cpsr, i_fn);
757}
758
759static void __kprobes
760emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
761{
762 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
763 kprobe_opcode_t insn = p->opcode;
764 int rd = (insn >> 16) & 0xf;
765 int rs = (insn >> 8) & 0xf;
766 int rm = insn & 0xf;
767 long rsv = regs->uregs[rs];
768 long rmv = regs->uregs[rm];
769
770 regs->uregs[rd] =
771 insnslot_2arg_rwflags(rsv, rmv, &regs->ARM_cpsr, i_fn);
772}
773
774static void __kprobes
775emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
776{
777 insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];
778 kprobe_opcode_t insn = p->opcode;
779 union reg_pair fnr;
780 int rdhi = (insn >> 16) & 0xf;
781 int rdlo = (insn >> 12) & 0xf;
782 int rs = (insn >> 8) & 0xf;
783 int rm = insn & 0xf;
784 long rsv = regs->uregs[rs];
785 long rmv = regs->uregs[rm];
786
787 fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],
788 regs->uregs[rdlo], rsv, rmv,
789 &regs->ARM_cpsr, i_fn);
790 regs->uregs[rdhi] = fnr.r0;
791 regs->uregs[rdlo] = fnr.r1;
792}
793
794static void __kprobes
795emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)
796{
797 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
798 kprobe_opcode_t insn = p->opcode;
799 int rd = (insn >> 12) & 0xf;
800 int rn = (insn >> 16) & 0xf;
801 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
802
803 regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
804}
805
806static void __kprobes
807emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
808{
809 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
810 kprobe_opcode_t insn = p->opcode;
811 int rd = (insn >> 12) & 0xf;
812 int rn = (insn >> 16) & 0xf;
813 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
814
815 regs->uregs[rd] = insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
816}
817
818static void __kprobes
819emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
820{
821 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
822 kprobe_opcode_t insn = p->opcode;
823 long ppc = (long)p->addr + 8;
824 int rd = (insn >> 12) & 0xf;
825 int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */
826 int rs = (insn >> 8) & 0xf; /* invalid, don't care. */
827 int rm = insn & 0xf;
828 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
829 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
830 long rsv = regs->uregs[rs];
831
832 regs->uregs[rd] =
833 insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);
834}
835
836static void __kprobes
837emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
838{
839 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
840 kprobe_opcode_t insn = p->opcode;
841 long ppc = (long)p->addr + 8;
842 int rd = (insn >> 12) & 0xf;
843 int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */
844 int rs = (insn >> 8) & 0xf; /* invalid, don't care. */
845 int rm = insn & 0xf;
846 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
847 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
848 long rsv = regs->uregs[rs];
849
850 regs->uregs[rd] =
851 insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
852}
853
854static enum kprobe_insn __kprobes
855prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
856{
857 int ibit = (insn & (1 << 26)) ? 25 : 22;
858
859 insn &= 0xfff00fff;
860 insn |= 0x00001000; /* Rn = r0, Rd = r1 */
861 if (insn & (1 << ibit)) {
862 insn &= ~0xf;
863 insn |= 2; /* Rm = r2 */
864 }
865 asi->insn[0] = insn;
866 asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr : emulate_str;
867 return INSN_GOOD;
868}
869
870static enum kprobe_insn __kprobes
871prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
872{
873 insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */
874 asi->insn[0] = insn;
875 asi->insn_handler = emulate_rd12rm0;
876 return INSN_GOOD;
877}
878
879static enum kprobe_insn __kprobes
880prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi)
881{
882 insn &= 0xffff0fff; /* Rd = r0 */
883 asi->insn[0] = insn;
884 asi->insn_handler = emulate_rd12;
885 return INSN_GOOD;
886}
887
888static enum kprobe_insn __kprobes
889prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
890 struct arch_specific_insn *asi)
891{
892 insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */
893 insn |= 0x00000001; /* Rm = r1 */
894 asi->insn[0] = insn;
895 asi->insn_handler = emulate_rd12rn16rm0_rwflags;
896 return INSN_GOOD;
897}
898
899static enum kprobe_insn __kprobes
900prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
901 struct arch_specific_insn *asi)
902{
903 insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */
904 insn |= 0x00000001; /* Rm = r1 */
905 asi->insn[0] = insn;
906 asi->insn_handler = emulate_rd16rs8rm0_rwflags;
907 return INSN_GOOD;
908}
909
910static enum kprobe_insn __kprobes
911prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
912 struct arch_specific_insn *asi)
913{
914 insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */
915 insn |= 0x00000102; /* Rs = r1, Rm = r2 */
916 asi->insn[0] = insn;
917 asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;
918 return INSN_GOOD;
919}
920
921static enum kprobe_insn __kprobes
922prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
923 struct arch_specific_insn *asi)
924{
925 insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */
926 insn |= 0x00001203; /* Rs = r2, Rm = r3 */
927 asi->insn[0] = insn;
928 asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;
929 return INSN_GOOD;
930}
931
932/*
933 * For the instruction masking and comparisons in all the "space_*"
934 * functions below, Do _not_ rearrange the order of tests unless
935 * you're very, very sure of what you are doing. For the sake of
936 * efficiency, the masks for some tests sometimes assume other test
937 * have been done prior to them so the number of patterns to test
938 * for an instruction set can be as broad as possible to reduce the
939 * number of tests needed.
940 */
941
942static enum kprobe_insn __kprobes
943space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
944{
945 /* CPS mmod == 1 : 1111 0001 0000 xx10 xxxx xxxx xx0x xxxx */
946 /* RFE : 1111 100x x0x1 xxxx xxxx 1010 xxxx xxxx */
947 /* SRS : 1111 100x x1x0 1101 xxxx 0101 xxxx xxxx */
948 if ((insn & 0xfff30020) == 0xf1020000 ||
949 (insn & 0xfe500f00) == 0xf8100a00 ||
950 (insn & 0xfe5f0f00) == 0xf84d0500)
951 return INSN_REJECTED;
952
953 /* PLD : 1111 01x1 x101 xxxx xxxx xxxx xxxx xxxx : */
954 if ((insn & 0xfd700000) == 0xf4500000) {
955 insn &= 0xfff0ffff; /* Rn = r0 */
956 asi->insn[0] = insn;
957 asi->insn_handler = emulate_rn16;
958 return INSN_GOOD;
959 }
960
961 /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
962 if ((insn & 0xfe000000) == 0xfa000000) {
963 asi->insn_handler = simulate_blx1;
964 return INSN_GOOD_NO_SLOT;
965 }
966
967 /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
968 /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
969 if ((insn & 0xffff00f0) == 0xf1010000 ||
970 (insn & 0xff000010) == 0xfe000000) {
971 asi->insn[0] = insn;
972 asi->insn_handler = emulate_none;
973 return INSN_GOOD;
974 }
975
976 /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
977 /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
978 if ((insn & 0xffe00000) == 0xfc400000) {
979 insn &= 0xfff00fff; /* Rn = r0 */
980 insn |= 0x00001000; /* Rd = r1 */
981 asi->insn[0] = insn;
982 asi->insn_handler =
983 (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
984 return INSN_GOOD;
985 }
986
987 /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
988 /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
989 if ((insn & 0xfe000000) == 0xfc000000) {
990 insn &= 0xfff0ffff; /* Rn = r0 */
991 asi->insn[0] = insn;
992 asi->insn_handler = emulate_ldcstc;
993 return INSN_GOOD;
994 }
995
996 /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
997 /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
998 insn &= 0xffff0fff; /* Rd = r0 */
999 asi->insn[0] = insn;
1000 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1001 return INSN_GOOD;
1002}
1003
1004static enum kprobe_insn __kprobes
1005space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1006{
1007 /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
1008 if ((insn & 0x0f900010) == 0x01000000) {
1009
1010 /* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
1011 /* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
1012 if ((insn & 0x0ff000f0) == 0x01200020 ||
1013 (insn & 0x0fb000f0) == 0x01200000)
1014 return INSN_REJECTED;
1015
1016 /* MRS : cccc 0001 0x00 xxxx xxxx xxxx 0000 xxxx */
1017 if ((insn & 0x0fb00010) == 0x01000000)
1018 return prep_emulate_rd12(insn, asi);
1019
1020 /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
1021 if ((insn & 0x0ff00090) == 0x01400080)
1022 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1023
1024 /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
1025 /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
1026 if ((insn & 0x0ff000b0) == 0x012000a0 ||
1027 (insn & 0x0ff00090) == 0x01600080)
1028 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1029
1030 /* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
1031 /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 0x00 xxxx : Q */
1032 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1033
1034 }
1035
1036 /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
1037 else if ((insn & 0x0f900090) == 0x01000010) {
1038
1039 /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
1040 if ((insn & 0xfff000f0) == 0xe1200070)
1041 return INSN_REJECTED;
1042
1043 /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
1044 /* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
1045 if ((insn & 0x0ff000d0) == 0x01200010) {
1046 asi->insn[0] = truecc_insn(insn);
1047 asi->insn_handler = simulate_blx2bx;
1048 return INSN_GOOD;
1049 }
1050
1051 /* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
1052 if ((insn & 0x0ff000f0) == 0x01600010)
1053 return prep_emulate_rd12rm0(insn, asi);
1054
1055 /* QADD : cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx :Q */
1056 /* QSUB : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
1057 /* QDADD : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
1058 /* QDSUB : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
1059 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1060 }
1061
1062 /* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
1063 else if ((insn & 0x0f000090) == 0x00000090) {
1064
1065 /* MUL : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx : */
1066 /* MULS : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
1067 /* MLA : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx : */
1068 /* MLAS : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
1069 /* UMAAL : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx : */
1070 /* UMULL : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx : */
1071 /* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
1072 /* UMLAL : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx : */
1073 /* UMLALS : cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx :cc */
1074 /* SMULL : cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx : */
1075 /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
1076 /* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */
1077 /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
1078 if ((insn & 0x0fe000f0) == 0x00000090) {
1079 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1080 } else if ((insn & 0x0fe000f0) == 0x00200090) {
1081 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1082 } else {
1083 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1084 }
1085 }
1086
1087 /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
1088 else if ((insn & 0x0e000090) == 0x00000090) {
1089
1090 /* SWP : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
1091 /* SWPB : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
1092 /* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
1093 /* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
1094 /* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
1095 /* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
1096 /* LDRH : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
1097 /* STRH : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
1098 /* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
1099 /* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
1100 if ((insn & 0x0fb000f0) == 0x01000090) {
1101 /* SWP/SWPB */
1102 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1103 } else if ((insn & 0x0e1000d0) == 0x00000d0) {
1104 /* STRD/LDRD */
1105 insn &= 0xfff00fff;
1106 insn |= 0x00002000; /* Rn = r0, Rd = r2 */
1107 if (insn & (1 << 22)) {
1108 /* I bit */
1109 insn &= ~0xf;
1110 insn |= 1; /* Rm = r1 */
1111 }
1112 asi->insn[0] = insn;
1113 asi->insn_handler =
1114 (insn & (1 << 5)) ? emulate_strd : emulate_ldrd;
1115 return INSN_GOOD;
1116 }
1117
1118 return prep_emulate_ldr_str(insn, asi);
1119 }
1120
1121 /* cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx */
1122
1123 /*
1124 * ALU op with S bit and Rd == 15 :
1125 * cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
1126 */
1127 if ((insn & 0x0e10f000) == 0x0010f000)
1128 return INSN_REJECTED;
1129
1130 /*
1131 * "mov ip, sp" is the most common kprobe'd instruction by far.
1132 * Check and optimize for it explicitly.
1133 */
1134 if (insn == 0xe1a0c00d) {
1135 asi->insn_handler = simulate_mov_ipsp;
1136 return INSN_GOOD_NO_SLOT;
1137 }
1138
1139 /*
1140 * Data processing: Immediate-shift / Register-shift
1141 * ALU op : cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx
1142 * CPY : cccc 0001 1010 xxxx xxxx 0000 0000 xxxx
1143 * MOV : cccc 0001 101x xxxx xxxx xxxx xxxx xxxx
1144 * *S (bit 20) updates condition codes
1145 * ADC/SBC/RSC reads the C flag
1146 */
1147 insn &= 0xfff00ff0; /* Rn = r0, Rd = r0 */
1148 insn |= 0x00000001; /* Rm = r1 */
1149 if (insn & 0x010) {
1150 insn &= 0xfffff0ff; /* register shift */
1151 insn |= 0x00000200; /* Rs = r2 */
1152 }
1153 asi->insn[0] = insn;
1154 asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */
1155 emulate_alu_rwflags : emulate_alu_rflags;
1156 return INSN_GOOD;
1157}
1158
1159static enum kprobe_insn __kprobes
1160space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1161{
1162 /*
1163 * MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
1164 * Undef : cccc 0011 0x00 xxxx xxxx xxxx xxxx xxxx
1165 * ALU op with S bit and Rd == 15 :
1166 * cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
1167 */
1168 if ((insn & 0x0f900000) == 0x03200000 || /* MSR & Undef */
1169 (insn & 0x0e10f000) == 0x0210f000) /* ALU s-bit, R15 */
1170 return INSN_REJECTED;
1171
1172 /*
1173 * Data processing: 32-bit Immediate
1174 * ALU op : cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
1175 * MOV : cccc 0011 101x xxxx xxxx xxxx xxxx xxxx
1176 * *S (bit 20) updates condition codes
1177 * ADC/SBC/RSC reads the C flag
1178 */
1179 insn &= 0xfff00ff0; /* Rn = r0, Rd = r0 */
1180 asi->insn[0] = insn;
1181 asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */
1182 emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
1183 return INSN_GOOD;
1184}
1185
1186static enum kprobe_insn __kprobes
1187space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1188{
1189 /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
1190 if ((insn & 0x0ff000f0) == 0x068000b0) {
1191 insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */
1192 insn |= 0x00000001; /* Rm = r1 */
1193 asi->insn[0] = insn;
1194 asi->insn_handler = emulate_sel;
1195 return INSN_GOOD;
1196 }
1197
1198 /* SSAT : cccc 0110 101x xxxx xxxx xxxx xx01 xxxx :Q */
1199 /* USAT : cccc 0110 111x xxxx xxxx xxxx xx01 xxxx :Q */
1200 /* SSAT16 : cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx :Q */
1201 /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
1202 if ((insn & 0x0fa00030) == 0x06a00010 ||
1203 (insn & 0x0fb000f0) == 0x06a00030) {
1204 insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */
1205 asi->insn[0] = insn;
1206 asi->insn_handler = emulate_sat;
1207 return INSN_GOOD;
1208 }
1209
1210 /* REV : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
1211 /* REV16 : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
1212 /* REVSH : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
1213 if ((insn & 0x0ff00070) == 0x06b00030 ||
1214 (insn & 0x0ff000f0) == 0x06f000b0)
1215 return prep_emulate_rd12rm0(insn, asi);
1216
1217 /* SADD16 : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
1218 /* SADDSUBX : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
1219 /* SSUBADDX : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
1220 /* SSUB16 : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
1221 /* SADD8 : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
1222 /* SSUB8 : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
1223 /* QADD16 : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx : */
1224 /* QADDSUBX : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx : */
1225 /* QSUBADDX : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx : */
1226 /* QSUB16 : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx : */
1227 /* QADD8 : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx : */
1228 /* QSUB8 : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx : */
1229 /* SHADD16 : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx : */
1230 /* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx : */
1231 /* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx : */
1232 /* SHSUB16 : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx : */
1233 /* SHADD8 : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx : */
1234 /* SHSUB8 : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx : */
1235 /* UADD16 : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
1236 /* UADDSUBX : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
1237 /* USUBADDX : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
1238 /* USUB16 : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
1239 /* UADD8 : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
1240 /* USUB8 : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
1241 /* UQADD16 : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx : */
1242 /* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx : */
1243 /* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx : */
1244 /* UQSUB16 : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx : */
1245 /* UQADD8 : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx : */
1246 /* UQSUB8 : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx : */
1247 /* UHADD16 : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx : */
1248 /* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx : */
1249 /* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx : */
1250 /* UHSUB16 : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx : */
1251 /* UHADD8 : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx : */
1252 /* UHSUB8 : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx : */
1253 /* PKHBT : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx : */
1254 /* PKHTB : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx : */
1255 /* SXTAB16 : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx : */
1256 /* SXTB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */
1257 /* SXTAB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */
1258 /* SXTAH : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx : */
1259 /* UXTAB16 : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx : */
1260 /* UXTAB : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx : */
1261 /* UXTAH : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx : */
1262 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1263}
1264
1265static enum kprobe_insn __kprobes
1266space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1267{
1268 /* Undef : cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
1269 if ((insn & 0x0ff000f0) == 0x03f000f0)
1270 return INSN_REJECTED;
1271
1272 /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
1273 /* USAD8 : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
1274 if ((insn & 0x0ff000f0) == 0x07800010)
1275 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1276
1277 /* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
1278 /* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
1279 if ((insn & 0x0ff00090) == 0x07400010)
1280 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1281
1282 /* SMLAD : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
1283 /* SMLSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
1284 /* SMMLA : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx : */
1285 /* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */
1286 if ((insn & 0x0ff00090) == 0x07000010 ||
1287 (insn & 0x0ff000d0) == 0x07500010 ||
1288 (insn & 0x0ff000d0) == 0x075000d0)
1289 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1290
1291 /* SMUSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx : */
1292 /* SMUAD : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
1293 /* SMMUL : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx : */
1294 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1295}
1296
1297static enum kprobe_insn __kprobes
1298space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1299{
1300 /* LDR : cccc 01xx x0x1 xxxx xxxx xxxx xxxx xxxx */
1301 /* LDRB : cccc 01xx x1x1 xxxx xxxx xxxx xxxx xxxx */
1302 /* LDRBT : cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
1303 /* LDRT : cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
1304 /* STR : cccc 01xx x0x0 xxxx xxxx xxxx xxxx xxxx */
1305 /* STRB : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
1306 /* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
1307 /* STRT : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
1308 return prep_emulate_ldr_str(insn, asi);
1309}
1310
1311static enum kprobe_insn __kprobes
1312space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1313{
1314 /* LDM(2) : cccc 100x x101 xxxx 0xxx xxxx xxxx xxxx */
1315 /* LDM(3) : cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
1316 if ((insn & 0x0e708000) == 0x85000000 ||
1317 (insn & 0x0e508000) == 0x85010000)
1318 return INSN_REJECTED;
1319
1320 /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
1321 /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
1322 asi->insn[0] = truecc_insn(insn);
1323 asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
1324 simulate_stm1_pc : simulate_ldm1stm1;
1325 return INSN_GOOD;
1326}
1327
1328static enum kprobe_insn __kprobes
1329space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1330{
1331 /* B : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
1332 /* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
1333 asi->insn[0] = truecc_insn(insn);
1334 asi->insn_handler = simulate_bbl;
1335 return INSN_GOOD;
1336}
1337
1338static enum kprobe_insn __kprobes
1339space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1340{
1341 /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1342 /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1343 insn &= 0xfff00fff;
1344 insn |= 0x00001000; /* Rn = r0, Rd = r1 */
1345 asi->insn[0] = insn;
1346 asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
1347 return INSN_GOOD;
1348}
1349
1350static enum kprobe_insn __kprobes
1351space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1352{
1353 /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
1354 /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1355 insn &= 0xfff0ffff; /* Rn = r0 */
1356 asi->insn[0] = insn;
1357 asi->insn_handler = emulate_ldcstc;
1358 return INSN_GOOD;
1359}
1360
1361static enum kprobe_insn __kprobes
1362space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1363{
1364 /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
1365 /* SWI : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
1366 if ((insn & 0xfff000f0) == 0xe1200070 ||
1367 (insn & 0x0f000000) == 0x0f000000)
1368 return INSN_REJECTED;
1369
1370 /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
1371 if ((insn & 0x0f000010) == 0x0e000000) {
1372 asi->insn[0] = insn;
1373 asi->insn_handler = emulate_none;
1374 return INSN_GOOD;
1375 }
1376
1377 /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1378 /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1379 insn &= 0xffff0fff; /* Rd = r0 */
1380 asi->insn[0] = insn;
1381 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1382 return INSN_GOOD;
1383}
1384
1385/* Return:
1386 * INSN_REJECTED If instruction is one not allowed to kprobe,
1387 * INSN_GOOD If instruction is supported and uses instruction slot,
1388 * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
1389 *
1390 * For instructions we don't want to kprobe (INSN_REJECTED return result):
1391 * These are generally ones that modify the processor state making
1392 * them "hard" to simulate such as switches processor modes or
1393 * make accesses in alternate modes. Any of these could be simulated
1394 * if the work was put into it, but low return considering they
1395 * should also be very rare.
1396 */
1397enum kprobe_insn __kprobes
1398arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1399{
1400 asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
1401
1402 if ((insn & 0xf0000000) == 0xf0000000) {
1403
1404 return space_1111(insn, asi);
1405
1406 } else if ((insn & 0x0e000000) == 0x00000000) {
1407
1408 return space_cccc_000x(insn, asi);
1409
1410 } else if ((insn & 0x0e000000) == 0x02000000) {
1411
1412 return space_cccc_001x(insn, asi);
1413
1414 } else if ((insn & 0x0f000010) == 0x06000010) {
1415
1416 return space_cccc_0110__1(insn, asi);
1417
1418 } else if ((insn & 0x0f000010) == 0x07000010) {
1419
1420 return space_cccc_0111__1(insn, asi);
1421
1422 } else if ((insn & 0x0c000000) == 0x04000000) {
1423
1424 return space_cccc_01xx(insn, asi);
1425
1426 } else if ((insn & 0x0e000000) == 0x08000000) {
1427
1428 return space_cccc_100x(insn, asi);
1429
1430 } else if ((insn & 0x0e000000) == 0x0a000000) {
1431
1432 return space_cccc_101x(insn, asi);
1433
1434 } else if ((insn & 0x0fe00000) == 0x0c400000) {
1435
1436 return space_cccc_1100_010x(insn, asi);
1437
1438 } else if ((insn & 0x0e000000) == 0x0c400000) {
1439
1440 return space_cccc_110x(insn, asi);
1441
1442 }
1443
1444 return space_cccc_111x(insn, asi);
1445}
1446
1447void __init arm_kprobe_decode_init(void)
1448{
1449 find_str_pc_offset();
1450}
1451
1452
1453/*
1454 * All ARM instructions listed below.
1455 *
1456 * Instructions and their general purpose registers are given.
1457 * If a particular register may not use R15, it is prefixed with a "!".
1458 * If marked with a "*" means the value returned by reading R15
1459 * is implementation defined.
1460 *
1461 * ADC/ADD/AND/BIC/CMN/CMP/EOR/MOV/MVN/ORR/RSB/RSC/SBC/SUB/TEQ
1462 * TST: Rd, Rn, Rm, !Rs
1463 * BX: Rm
1464 * BLX(2): !Rm
1465 * BX: Rm (R15 legal, but discouraged)
1466 * BXJ: !Rm,
1467 * CLZ: !Rd, !Rm
1468 * CPY: Rd, Rm
1469 * LDC/2,STC/2 immediate offset & unindex: Rn
1470 * LDC/2,STC/2 immediate pre/post-indexed: !Rn
1471 * LDM(1/3): !Rn, register_list
1472 * LDM(2): !Rn, !register_list
1473 * LDR,STR,PLD immediate offset: Rd, Rn
1474 * LDR,STR,PLD register offset: Rd, Rn, !Rm
1475 * LDR,STR,PLD scaled register offset: Rd, !Rn, !Rm
1476 * LDR,STR immediate pre/post-indexed: Rd, !Rn
1477 * LDR,STR register pre/post-indexed: Rd, !Rn, !Rm
1478 * LDR,STR scaled register pre/post-indexed: Rd, !Rn, !Rm
1479 * LDRB,STRB immediate offset: !Rd, Rn
1480 * LDRB,STRB register offset: !Rd, Rn, !Rm
1481 * LDRB,STRB scaled register offset: !Rd, !Rn, !Rm
1482 * LDRB,STRB immediate pre/post-indexed: !Rd, !Rn
1483 * LDRB,STRB register pre/post-indexed: !Rd, !Rn, !Rm
1484 * LDRB,STRB scaled register pre/post-indexed: !Rd, !Rn, !Rm
1485 * LDRT,LDRBT,STRBT immediate pre/post-indexed: !Rd, !Rn
1486 * LDRT,LDRBT,STRBT register pre/post-indexed: !Rd, !Rn, !Rm
1487 * LDRT,LDRBT,STRBT scaled register pre/post-indexed: !Rd, !Rn, !Rm
1488 * LDRH/SH/SB/D,STRH/SH/SB/D immediate offset: !Rd, Rn
1489 * LDRH/SH/SB/D,STRH/SH/SB/D register offset: !Rd, Rn, !Rm
1490 * LDRH/SH/SB/D,STRH/SH/SB/D immediate pre/post-indexed: !Rd, !Rn
1491 * LDRH/SH/SB/D,STRH/SH/SB/D register pre/post-indexed: !Rd, !Rn, !Rm
1492 * LDREX: !Rd, !Rn
1493 * MCR/2: !Rd
1494 * MCRR/2,MRRC/2: !Rd, !Rn
1495 * MLA: !Rd, !Rn, !Rm, !Rs
1496 * MOV: Rd
1497 * MRC/2: !Rd (if Rd==15, only changes cond codes, not the register)
1498 * MRS,MSR: !Rd
1499 * MUL: !Rd, !Rm, !Rs
1500 * PKH{BT,TB}: !Rd, !Rn, !Rm
1501 * QDADD,[U]QADD/16/8/SUBX: !Rd, !Rm, !Rn
1502 * QDSUB,[U]QSUB/16/8/ADDX: !Rd, !Rm, !Rn
1503 * REV/16/SH: !Rd, !Rm
1504 * RFE: !Rn
1505 * {S,U}[H]ADD{16,8,SUBX},{S,U}[H]SUB{16,8,ADDX}: !Rd, !Rn, !Rm
1506 * SEL: !Rd, !Rn, !Rm
1507 * SMLA<x><y>,SMLA{D,W<y>},SMLSD,SMML{A,S}: !Rd, !Rn, !Rm, !Rs
1508 * SMLAL<x><y>,SMLA{D,LD},SMLSLD,SMMULL,SMULW<y>: !RdHi, !RdLo, !Rm, !Rs
1509 * SMMUL,SMUAD,SMUL<x><y>,SMUSD: !Rd, !Rm, !Rs
1510 * SSAT/16: !Rd, !Rm
1511 * STM(1/2): !Rn, register_list* (R15 in reg list not recommended)
1512 * STRT immediate pre/post-indexed: Rd*, !Rn
1513 * STRT register pre/post-indexed: Rd*, !Rn, !Rm
1514 * STRT scaled register pre/post-indexed: Rd*, !Rn, !Rm
1515 * STREX: !Rd, !Rn, !Rm
1516 * SWP/B: !Rd, !Rn, !Rm
1517 * {S,U}XTA{B,B16,H}: !Rd, !Rn, !Rm
1518 * {S,U}XT{B,B16,H}: !Rd, !Rm
1519 * UM{AA,LA,UL}L: !RdHi, !RdLo, !Rm, !Rs
1520 * USA{D8,A8,T,T16}: !Rd, !Rm, !Rs
1521 *
1522 * May transfer control by writing R15 (possible mode changes or alternate
1523 * mode accesses marked by "*"):
1524 * ALU op (* with s-bit), B, BL, BKPT, BLX(1/2), BX, BXJ, CPS*, CPY,
1525 * LDM(1), LDM(2/3)*, LDR, MOV, RFE*, SWI*
1526 *
1527 * Instructions that do not take general registers, nor transfer control:
1528 * CDP/2, SETEND, SRS*
1529 */
diff --git a/include/asm-arm/kprobes.h b/include/asm-arm/kprobes.h
new file mode 100644
index 000000000000..951322328793
--- /dev/null
+++ b/include/asm-arm/kprobes.h
@@ -0,0 +1,43 @@
1/*
2 * include/asm-arm/kprobes.h
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#ifndef _ARM_KPROBES_H
17#define _ARM_KPROBES_H
18
19#include <linux/types.h>
20#include <linux/ptrace.h>
21
22typedef u32 kprobe_opcode_t;
23
24struct kprobe;
25typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
26
27/* Architecture specific copy of original instruction. */
28struct arch_specific_insn {
29 kprobe_opcode_t *insn;
30 kprobe_insn_handler_t *insn_handler;
31};
32
33enum kprobe_insn {
34 INSN_REJECTED,
35 INSN_GOOD,
36 INSN_GOOD_NO_SLOT
37};
38
39enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
40 struct arch_specific_insn *);
41void __init arm_kprobe_decode_init(void);
42
43#endif /* _ARM_KPROBES_H */