diff options
-rw-r--r-- | arch/arm/include/asm/probes.h | 2 | ||||
-rw-r--r-- | arch/arm/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 724 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-common.c | 425 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes.h | 373 | ||||
-rw-r--r-- | arch/arm/kernel/probes-arm.c | 731 | ||||
-rw-r--r-- | arch/arm/kernel/probes-arm.h | 38 | ||||
-rw-r--r-- | arch/arm/kernel/probes.c | 443 | ||||
-rw-r--r-- | arch/arm/kernel/probes.h | 397 |
9 files changed, 1624 insertions, 1513 deletions
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index 90c5f5485202..737a9b310efc 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #ifndef _ASM_PROBES_H | 19 | #ifndef _ASM_PROBES_H |
20 | #define _ASM_PROBES_H | 20 | #define _ASM_PROBES_H |
21 | 21 | ||
22 | struct kprobe; | ||
23 | |||
22 | typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); | 24 | typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); |
23 | typedef unsigned long (kprobe_check_cc)(unsigned long); | 25 | typedef unsigned long (kprobe_check_cc)(unsigned long); |
24 | typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); | 26 | typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index a30fc9be9e9e..4c8b13e64280 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -50,11 +50,11 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o | |||
50 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o | 50 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o |
51 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o | 51 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o |
52 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 52 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
53 | obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o patch.o | 53 | obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o |
54 | ifdef CONFIG_THUMB2_KERNEL | 54 | ifdef CONFIG_THUMB2_KERNEL |
55 | obj-$(CONFIG_KPROBES) += kprobes-thumb.o | 55 | obj-$(CONFIG_KPROBES) += kprobes-thumb.o |
56 | else | 56 | else |
57 | obj-$(CONFIG_KPROBES) += kprobes-arm.o | 57 | obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o |
58 | endif | 58 | endif |
59 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o | 59 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o |
60 | test-kprobes-objs := kprobes-test.o | 60 | test-kprobes-objs := kprobes-test.o |
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 8a30c89da70e..a1d0a8f00f9e 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
@@ -60,13 +60,10 @@ | |||
60 | 60 | ||
61 | #include <linux/kernel.h> | 61 | #include <linux/kernel.h> |
62 | #include <linux/kprobes.h> | 62 | #include <linux/kprobes.h> |
63 | #include <linux/module.h> | 63 | #include <linux/ptrace.h> |
64 | 64 | ||
65 | #include "kprobes.h" | 65 | #include "kprobes.h" |
66 | 66 | #include "probes-arm.h" | |
67 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) | ||
68 | |||
69 | #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) | ||
70 | 67 | ||
71 | #if __LINUX_ARM_ARCH__ >= 6 | 68 | #if __LINUX_ARM_ARCH__ >= 6 |
72 | #define BLX(reg) "blx "reg" \n\t" | 69 | #define BLX(reg) "blx "reg" \n\t" |
@@ -75,88 +72,8 @@ | |||
75 | "mov pc, "reg" \n\t" | 72 | "mov pc, "reg" \n\t" |
76 | #endif | 73 | #endif |
77 | 74 | ||
78 | /* | ||
79 | * To avoid the complications of mimicing single-stepping on a | ||
80 | * processor without a Next-PC or a single-step mode, and to | ||
81 | * avoid having to deal with the side-effects of boosting, we | ||
82 | * simulate or emulate (almost) all ARM instructions. | ||
83 | * | ||
84 | * "Simulation" is where the instruction's behavior is duplicated in | ||
85 | * C code. "Emulation" is where the original instruction is rewritten | ||
86 | * and executed, often by altering its registers. | ||
87 | * | ||
88 | * By having all behavior of the kprobe'd instruction completed before | ||
89 | * returning from the kprobe_handler(), all locks (scheduler and | ||
90 | * interrupt) can safely be released. There is no need for secondary | ||
91 | * breakpoints, no race with MP or preemptable kernels, nor having to | ||
92 | * clean up resources counts at a later time impacting overall system | ||
93 | * performance. By rewriting the instruction, only the minimum registers | ||
94 | * need to be loaded and saved back optimizing performance. | ||
95 | * | ||
96 | * Calling the insnslot_*_rwflags version of a function doesn't hurt | ||
97 | * anything even when the CPSR flags aren't updated by the | ||
98 | * instruction. It's just a little slower in return for saving | ||
99 | * a little space by not having a duplicate function that doesn't | ||
100 | * update the flags. (The same optimization can be said for | ||
101 | * instructions that do or don't perform register writeback) | ||
102 | * Also, instructions can either read the flags, only write the | ||
103 | * flags, or read and write the flags. To save combinations | ||
104 | * rather than for sheer performance, flag functions just assume | ||
105 | * read and write of flags. | ||
106 | */ | ||
107 | |||
108 | static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) | ||
109 | { | ||
110 | kprobe_opcode_t insn = p->opcode; | ||
111 | long iaddr = (long)p->addr; | ||
112 | int disp = branch_displacement(insn); | ||
113 | |||
114 | if (insn & (1 << 24)) | ||
115 | regs->ARM_lr = iaddr + 4; | ||
116 | |||
117 | regs->ARM_pc = iaddr + 8 + disp; | ||
118 | } | ||
119 | |||
120 | static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) | ||
121 | { | ||
122 | kprobe_opcode_t insn = p->opcode; | ||
123 | long iaddr = (long)p->addr; | ||
124 | int disp = branch_displacement(insn); | ||
125 | |||
126 | regs->ARM_lr = iaddr + 4; | ||
127 | regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2); | ||
128 | regs->ARM_cpsr |= PSR_T_BIT; | ||
129 | } | ||
130 | 75 | ||
131 | static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) | 76 | void __kprobes |
132 | { | ||
133 | kprobe_opcode_t insn = p->opcode; | ||
134 | int rm = insn & 0xf; | ||
135 | long rmv = regs->uregs[rm]; | ||
136 | |||
137 | if (insn & (1 << 5)) | ||
138 | regs->ARM_lr = (long)p->addr + 4; | ||
139 | |||
140 | regs->ARM_pc = rmv & ~0x1; | ||
141 | regs->ARM_cpsr &= ~PSR_T_BIT; | ||
142 | if (rmv & 0x1) | ||
143 | regs->ARM_cpsr |= PSR_T_BIT; | ||
144 | } | ||
145 | |||
146 | static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) | ||
147 | { | ||
148 | kprobe_opcode_t insn = p->opcode; | ||
149 | int rd = (insn >> 12) & 0xf; | ||
150 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | ||
151 | regs->uregs[rd] = regs->ARM_cpsr & mask; | ||
152 | } | ||
153 | |||
154 | static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) | ||
155 | { | ||
156 | regs->uregs[12] = regs->uregs[13]; | ||
157 | } | ||
158 | |||
159 | static void __kprobes | ||
160 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | 77 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) |
161 | { | 78 | { |
162 | kprobe_opcode_t insn = p->opcode; | 79 | kprobe_opcode_t insn = p->opcode; |
@@ -185,7 +102,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | |||
185 | regs->uregs[rn] = rnv; | 102 | regs->uregs[rn] = rnv; |
186 | } | 103 | } |
187 | 104 | ||
188 | static void __kprobes | 105 | void __kprobes |
189 | emulate_ldr(struct kprobe *p, struct pt_regs *regs) | 106 | emulate_ldr(struct kprobe *p, struct pt_regs *regs) |
190 | { | 107 | { |
191 | kprobe_opcode_t insn = p->opcode; | 108 | kprobe_opcode_t insn = p->opcode; |
@@ -215,7 +132,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs) | |||
215 | regs->uregs[rn] = rnv; | 132 | regs->uregs[rn] = rnv; |
216 | } | 133 | } |
217 | 134 | ||
218 | static void __kprobes | 135 | void __kprobes |
219 | emulate_str(struct kprobe *p, struct pt_regs *regs) | 136 | emulate_str(struct kprobe *p, struct pt_regs *regs) |
220 | { | 137 | { |
221 | kprobe_opcode_t insn = p->opcode; | 138 | kprobe_opcode_t insn = p->opcode; |
@@ -242,7 +159,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs) | |||
242 | regs->uregs[rn] = rnv; | 159 | regs->uregs[rn] = rnv; |
243 | } | 160 | } |
244 | 161 | ||
245 | static void __kprobes | 162 | void __kprobes |
246 | emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | 163 | emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) |
247 | { | 164 | { |
248 | kprobe_opcode_t insn = p->opcode; | 165 | kprobe_opcode_t insn = p->opcode; |
@@ -277,7 +194,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) | |||
277 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 194 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
278 | } | 195 | } |
279 | 196 | ||
280 | static void __kprobes | 197 | void __kprobes |
281 | emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 198 | emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) |
282 | { | 199 | { |
283 | kprobe_opcode_t insn = p->opcode; | 200 | kprobe_opcode_t insn = p->opcode; |
@@ -304,7 +221,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
304 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 221 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
305 | } | 222 | } |
306 | 223 | ||
307 | static void __kprobes | 224 | void __kprobes |
308 | emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 225 | emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) |
309 | { | 226 | { |
310 | kprobe_opcode_t insn = p->opcode; | 227 | kprobe_opcode_t insn = p->opcode; |
@@ -333,7 +250,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
333 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 250 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
334 | } | 251 | } |
335 | 252 | ||
336 | static void __kprobes | 253 | void __kprobes |
337 | emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | 254 | emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) |
338 | { | 255 | { |
339 | kprobe_opcode_t insn = p->opcode; | 256 | kprobe_opcode_t insn = p->opcode; |
@@ -353,7 +270,7 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
353 | regs->uregs[rd] = rdv; | 270 | regs->uregs[rd] = rdv; |
354 | } | 271 | } |
355 | 272 | ||
356 | static void __kprobes | 273 | void __kprobes |
357 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | 274 | emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) |
358 | { | 275 | { |
359 | kprobe_opcode_t insn = p->opcode; | 276 | kprobe_opcode_t insn = p->opcode; |
@@ -382,624 +299,3 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) | |||
382 | regs->uregs[rdhi] = rdhiv; | 299 | regs->uregs[rdhi] = rdhiv; |
383 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); | 300 | regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); |
384 | } | 301 | } |
385 | |||
386 | /* | ||
387 | * For the instruction masking and comparisons in all the "space_*" | ||
388 | * functions below, Do _not_ rearrange the order of tests unless | ||
389 | * you're very, very sure of what you are doing. For the sake of | ||
390 | * efficiency, the masks for some tests sometimes assume other test | ||
391 | * have been done prior to them so the number of patterns to test | ||
392 | * for an instruction set can be as broad as possible to reduce the | ||
393 | * number of tests needed. | ||
394 | */ | ||
395 | |||
396 | static const union decode_item arm_1111_table[] = { | ||
397 | /* Unconditional instructions */ | ||
398 | |||
399 | /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */ | ||
400 | /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */ | ||
401 | /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */ | ||
402 | /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */ | ||
403 | DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop), | ||
404 | |||
405 | /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */ | ||
406 | /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */ | ||
407 | /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */ | ||
408 | /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */ | ||
409 | DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop), | ||
410 | |||
411 | /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
412 | DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1), | ||
413 | |||
414 | /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ | ||
415 | /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ | ||
416 | /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
417 | /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
418 | |||
419 | /* Coprocessor instructions... */ | ||
420 | /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
421 | /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
422 | /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | ||
423 | /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | ||
424 | /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | ||
425 | /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
426 | /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
427 | |||
428 | /* Other unallocated instructions... */ | ||
429 | DECODE_END | ||
430 | }; | ||
431 | |||
432 | static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { | ||
433 | /* Miscellaneous instructions */ | ||
434 | |||
435 | /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
436 | DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs, | ||
437 | REGS(0, NOPC, 0, 0, 0)), | ||
438 | |||
439 | /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
440 | DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx), | ||
441 | |||
442 | /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
443 | DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx, | ||
444 | REGS(0, 0, 0, 0, NOPC)), | ||
445 | |||
446 | /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
447 | DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc, | ||
448 | REGS(0, NOPC, 0, 0, NOPC)), | ||
449 | |||
450 | /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ | ||
451 | /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
452 | /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ | ||
453 | /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
454 | DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc, | ||
455 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
456 | |||
457 | /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ | ||
458 | /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ | ||
459 | /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ | ||
460 | /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
461 | /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
462 | /* And unallocated instructions... */ | ||
463 | DECODE_END | ||
464 | }; | ||
465 | |||
466 | static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { | ||
467 | /* Halfword multiply and multiply-accumulate */ | ||
468 | |||
469 | /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | ||
470 | DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
471 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
472 | |||
473 | /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | ||
474 | DECODE_OR (0x0ff000b0, 0x012000a0), | ||
475 | /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | ||
476 | DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
477 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
478 | |||
479 | /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ | ||
480 | DECODE_OR (0x0ff00090, 0x01000080), | ||
481 | /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ | ||
482 | DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
483 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
484 | |||
485 | DECODE_END | ||
486 | }; | ||
487 | |||
488 | static const union decode_item arm_cccc_0000_____1001_table[] = { | ||
489 | /* Multiply and multiply-accumulate */ | ||
490 | |||
491 | /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ | ||
492 | /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
493 | DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
494 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
495 | |||
496 | /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
497 | /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
498 | DECODE_OR (0x0fe000f0, 0x00200090), | ||
499 | /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
500 | DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
501 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
502 | |||
503 | /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ | ||
504 | DECODE_OR (0x0ff000f0, 0x00400090), | ||
505 | /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */ | ||
506 | /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */ | ||
507 | /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */ | ||
508 | /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */ | ||
509 | /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */ | ||
510 | /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ | ||
511 | /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ | ||
512 | /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ | ||
513 | DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
514 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
515 | |||
516 | DECODE_END | ||
517 | }; | ||
518 | |||
519 | static const union decode_item arm_cccc_0001_____1001_table[] = { | ||
520 | /* Synchronization primitives */ | ||
521 | |||
522 | #if __LINUX_ARM_ARCH__ < 6 | ||
523 | /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ | ||
524 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ | ||
525 | DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, | ||
526 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
527 | #endif | ||
528 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ | ||
529 | /* And unallocated instructions... */ | ||
530 | DECODE_END | ||
531 | }; | ||
532 | |||
533 | static const union decode_item arm_cccc_000x_____1xx1_table[] = { | ||
534 | /* Extra load/store instructions */ | ||
535 | |||
536 | /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */ | ||
537 | /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */ | ||
538 | /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */ | ||
539 | /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */ | ||
540 | /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */ | ||
541 | DECODE_REJECT (0x0f200090, 0x00200090), | ||
542 | |||
543 | /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ | ||
544 | DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), | ||
545 | |||
546 | /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */ | ||
547 | /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */ | ||
548 | DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd, | ||
549 | REGS(NOPCWB, NOPCX, 0, 0, NOPC)), | ||
550 | |||
551 | /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */ | ||
552 | /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */ | ||
553 | DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, | ||
554 | REGS(NOPCWB, NOPCX, 0, 0, 0)), | ||
555 | |||
556 | /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ | ||
557 | DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str, | ||
558 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
559 | |||
560 | /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ | ||
561 | /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ | ||
562 | /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ | ||
563 | DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr, | ||
564 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
565 | |||
566 | /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ | ||
567 | DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str, | ||
568 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
569 | |||
570 | /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ | ||
571 | /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ | ||
572 | /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ | ||
573 | DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr, | ||
574 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
575 | |||
576 | DECODE_END | ||
577 | }; | ||
578 | |||
579 | static const union decode_item arm_cccc_000x_table[] = { | ||
580 | /* Data-processing (register) */ | ||
581 | |||
582 | /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
583 | DECODE_REJECT (0x0e10f000, 0x0010f000), | ||
584 | |||
585 | /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */ | ||
586 | DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp), | ||
587 | |||
588 | /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */ | ||
589 | /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */ | ||
590 | /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */ | ||
591 | /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */ | ||
592 | DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags, | ||
593 | REGS(ANY, 0, 0, 0, ANY)), | ||
594 | |||
595 | /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
596 | /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
597 | DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags, | ||
598 | REGS(0, ANY, 0, 0, ANY)), | ||
599 | |||
600 | /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */ | ||
601 | /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */ | ||
602 | /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */ | ||
603 | /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */ | ||
604 | /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
605 | /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
606 | /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
607 | /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
608 | /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
609 | /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
610 | DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags, | ||
611 | REGS(ANY, ANY, 0, 0, ANY)), | ||
612 | |||
613 | /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */ | ||
614 | /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */ | ||
615 | /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */ | ||
616 | /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */ | ||
617 | DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags, | ||
618 | REGS(ANY, 0, NOPC, 0, ANY)), | ||
619 | |||
620 | /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
621 | /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
622 | DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags, | ||
623 | REGS(0, ANY, NOPC, 0, ANY)), | ||
624 | |||
625 | /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */ | ||
626 | /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */ | ||
627 | /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */ | ||
628 | /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */ | ||
629 | /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
630 | /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
631 | /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
632 | /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
633 | /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
634 | /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
635 | DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, | ||
636 | REGS(ANY, ANY, NOPC, 0, ANY)), | ||
637 | |||
638 | DECODE_END | ||
639 | }; | ||
640 | |||
641 | static const union decode_item arm_cccc_001x_table[] = { | ||
642 | /* Data-processing (immediate) */ | ||
643 | |||
644 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | ||
645 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
646 | DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc, | ||
647 | REGS(0, NOPC, 0, 0, 0)), | ||
648 | |||
649 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | ||
650 | DECODE_OR (0x0fff00ff, 0x03200001), | ||
651 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | ||
652 | DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none), | ||
653 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | ||
654 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | ||
655 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | ||
656 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop), | ||
657 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ | ||
658 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | ||
659 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ | ||
660 | DECODE_REJECT (0x0fb00000, 0x03200000), | ||
661 | |||
662 | /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
663 | DECODE_REJECT (0x0e10f000, 0x0210f000), | ||
664 | |||
665 | /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */ | ||
666 | /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ | ||
667 | /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
668 | /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ | ||
669 | DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags, | ||
670 | REGS(ANY, 0, 0, 0, 0)), | ||
671 | |||
672 | /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ | ||
673 | /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ | ||
674 | DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags, | ||
675 | REGS(0, ANY, 0, 0, 0)), | ||
676 | |||
677 | /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ | ||
678 | /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */ | ||
679 | /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */ | ||
680 | /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */ | ||
681 | /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */ | ||
682 | /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */ | ||
683 | /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */ | ||
684 | /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ | ||
685 | /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ | ||
686 | /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ | ||
687 | DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags, | ||
688 | REGS(ANY, ANY, 0, 0, 0)), | ||
689 | |||
690 | DECODE_END | ||
691 | }; | ||
692 | |||
693 | static const union decode_item arm_cccc_0110_____xxx1_table[] = { | ||
694 | /* Media instructions */ | ||
695 | |||
696 | /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */ | ||
697 | DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc, | ||
698 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
699 | |||
700 | /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */ | ||
701 | /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */ | ||
702 | DECODE_OR(0x0fa00030, 0x06a00010), | ||
703 | /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */ | ||
704 | /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */ | ||
705 | DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc, | ||
706 | REGS(0, NOPC, 0, 0, NOPC)), | ||
707 | |||
708 | /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ | ||
709 | /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ | ||
710 | /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ | ||
711 | /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ | ||
712 | DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc, | ||
713 | REGS(0, NOPC, 0, 0, NOPC)), | ||
714 | |||
715 | /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */ | ||
716 | DECODE_REJECT (0x0fb00010, 0x06000010), | ||
717 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */ | ||
718 | DECODE_REJECT (0x0f8000f0, 0x060000b0), | ||
719 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */ | ||
720 | DECODE_REJECT (0x0f8000f0, 0x060000d0), | ||
721 | /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */ | ||
722 | /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */ | ||
723 | /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */ | ||
724 | /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */ | ||
725 | /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
726 | /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */ | ||
727 | /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
728 | /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
729 | /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
730 | /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
731 | /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
732 | /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */ | ||
733 | /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */ | ||
734 | /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */ | ||
735 | /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */ | ||
736 | /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */ | ||
737 | /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
738 | /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */ | ||
739 | /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */ | ||
740 | /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */ | ||
741 | /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */ | ||
742 | /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */ | ||
743 | /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */ | ||
744 | /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */ | ||
745 | /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
746 | /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */ | ||
747 | /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
748 | /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
749 | /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
750 | /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */ | ||
751 | /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */ | ||
752 | /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */ | ||
753 | /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */ | ||
754 | /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */ | ||
755 | /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */ | ||
756 | /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */ | ||
757 | DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc, | ||
758 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
759 | |||
760 | /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */ | ||
761 | /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */ | ||
762 | DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc, | ||
763 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
764 | |||
765 | /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */ | ||
766 | /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */ | ||
767 | DECODE_REJECT (0x0fb000f0, 0x06900070), | ||
768 | |||
769 | /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */ | ||
770 | /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */ | ||
771 | /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */ | ||
772 | /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */ | ||
773 | /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */ | ||
774 | /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */ | ||
775 | DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc, | ||
776 | REGS(0, NOPC, 0, 0, NOPC)), | ||
777 | |||
778 | /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */ | ||
779 | /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */ | ||
780 | /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */ | ||
781 | /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */ | ||
782 | /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */ | ||
783 | /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */ | ||
784 | DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc, | ||
785 | REGS(NOPCX, NOPC, 0, 0, NOPC)), | ||
786 | |||
787 | DECODE_END | ||
788 | }; | ||
789 | |||
790 | static const union decode_item arm_cccc_0111_____xxx1_table[] = { | ||
791 | /* Media instructions */ | ||
792 | |||
793 | /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */ | ||
794 | DECODE_REJECT (0x0ff000f0, 0x07f000f0), | ||
795 | |||
796 | /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ | ||
797 | /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ | ||
798 | DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
799 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
800 | |||
801 | /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */ | ||
802 | /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */ | ||
803 | DECODE_OR (0x0ff0f090, 0x0700f010), | ||
804 | /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */ | ||
805 | DECODE_OR (0x0ff0f0d0, 0x0750f010), | ||
806 | /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ | ||
807 | DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
808 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
809 | |||
810 | /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */ | ||
811 | /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */ | ||
812 | DECODE_OR (0x0ff00090, 0x07000010), | ||
813 | /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */ | ||
814 | DECODE_OR (0x0ff000d0, 0x07500010), | ||
815 | /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ | ||
816 | DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
817 | REGS(NOPC, NOPCX, NOPC, 0, NOPC)), | ||
818 | |||
819 | /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ | ||
820 | DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
821 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
822 | |||
823 | /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */ | ||
824 | /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */ | ||
825 | DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc, | ||
826 | REGS(0, NOPC, 0, 0, NOPC)), | ||
827 | |||
828 | /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ | ||
829 | DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc, | ||
830 | REGS(0, NOPC, 0, 0, 0)), | ||
831 | |||
832 | /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ | ||
833 | DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc, | ||
834 | REGS(0, NOPC, 0, 0, NOPCX)), | ||
835 | |||
836 | DECODE_END | ||
837 | }; | ||
838 | |||
839 | static const union decode_item arm_cccc_01xx_table[] = { | ||
840 | /* Load/store word and unsigned byte */ | ||
841 | |||
842 | /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */ | ||
843 | DECODE_REJECT (0x0c40f000, 0x0440f000), | ||
844 | |||
845 | /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */ | ||
846 | /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */ | ||
847 | /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */ | ||
848 | /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */ | ||
849 | DECODE_REJECT (0x0d200000, 0x04200000), | ||
850 | |||
851 | /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
852 | /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
853 | DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str, | ||
854 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
855 | |||
856 | /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
857 | /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
858 | DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr, | ||
859 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
860 | |||
861 | /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
862 | /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
863 | DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str, | ||
864 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
865 | |||
866 | /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
867 | /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
868 | DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr, | ||
869 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
870 | |||
871 | DECODE_END | ||
872 | }; | ||
873 | |||
874 | static const union decode_item arm_cccc_100x_table[] = { | ||
875 | /* Block data transfer instructions */ | ||
876 | |||
877 | /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
878 | /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
879 | DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm), | ||
880 | |||
881 | /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
882 | /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */ | ||
883 | /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */ | ||
884 | DECODE_END | ||
885 | }; | ||
886 | |||
887 | const union decode_item kprobe_decode_arm_table[] = { | ||
888 | /* | ||
889 | * Unconditional instructions | ||
890 | * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx | ||
891 | */ | ||
892 | DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table), | ||
893 | |||
894 | /* | ||
895 | * Miscellaneous instructions | ||
896 | * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx | ||
897 | */ | ||
898 | DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table), | ||
899 | |||
900 | /* | ||
901 | * Halfword multiply and multiply-accumulate | ||
902 | * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx | ||
903 | */ | ||
904 | DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table), | ||
905 | |||
906 | /* | ||
907 | * Multiply and multiply-accumulate | ||
908 | * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx | ||
909 | */ | ||
910 | DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table), | ||
911 | |||
912 | /* | ||
913 | * Synchronization primitives | ||
914 | * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx | ||
915 | */ | ||
916 | DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table), | ||
917 | |||
918 | /* | ||
919 | * Extra load/store instructions | ||
920 | * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx | ||
921 | */ | ||
922 | DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table), | ||
923 | |||
924 | /* | ||
925 | * Data-processing (register) | ||
926 | * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx | ||
927 | * Data-processing (register-shifted register) | ||
928 | * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx | ||
929 | */ | ||
930 | DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table), | ||
931 | |||
932 | /* | ||
933 | * Data-processing (immediate) | ||
934 | * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx | ||
935 | */ | ||
936 | DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table), | ||
937 | |||
938 | /* | ||
939 | * Media instructions | ||
940 | * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx | ||
941 | */ | ||
942 | DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table), | ||
943 | DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table), | ||
944 | |||
945 | /* | ||
946 | * Load/store word and unsigned byte | ||
947 | * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
948 | */ | ||
949 | DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table), | ||
950 | |||
951 | /* | ||
952 | * Block data transfer instructions | ||
953 | * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx | ||
954 | */ | ||
955 | DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table), | ||
956 | |||
957 | /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
958 | /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
959 | DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl), | ||
960 | |||
961 | /* | ||
962 | * Supervisor Call, and coprocessor instructions | ||
963 | */ | ||
964 | |||
965 | /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
966 | /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
967 | /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | ||
968 | /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | ||
969 | /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | ||
970 | /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
971 | /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
972 | /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
973 | DECODE_REJECT (0x0c000000, 0x0c000000), | ||
974 | |||
975 | DECODE_END | ||
976 | }; | ||
977 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
978 | EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); | ||
979 | #endif | ||
980 | |||
981 | static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) | ||
982 | { | ||
983 | regs->ARM_pc += 4; | ||
984 | p->ainsn.insn_handler(p, regs); | ||
985 | } | ||
986 | |||
987 | /* Return: | ||
988 | * INSN_REJECTED If instruction is one not allowed to kprobe, | ||
989 | * INSN_GOOD If instruction is supported and uses instruction slot, | ||
990 | * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. | ||
991 | * | ||
992 | * For instructions we don't want to kprobe (INSN_REJECTED return result): | ||
993 | * These are generally ones that modify the processor state making | ||
994 | * them "hard" to simulate such as switches processor modes or | ||
995 | * make accesses in alternate modes. Any of these could be simulated | ||
996 | * if the work was put into it, but low return considering they | ||
997 | * should also be very rare. | ||
998 | */ | ||
999 | enum kprobe_insn __kprobes | ||
1000 | arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | ||
1001 | { | ||
1002 | asi->insn_singlestep = arm_singlestep; | ||
1003 | asi->insn_check_cc = kprobe_condition_checks[insn>>28]; | ||
1004 | return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false); | ||
1005 | } | ||
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c index 455c8003bffb..f02c038059c3 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/kernel/kprobes-common.c | |||
@@ -13,178 +13,10 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/kprobes.h> | 15 | #include <linux/kprobes.h> |
16 | #include <asm/system_info.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/bug.h> | ||
20 | 16 | ||
21 | #include "kprobes.h" | 17 | #include "kprobes.h" |
22 | 18 | ||
23 | 19 | ||
24 | #ifndef find_str_pc_offset | ||
25 | |||
26 | /* | ||
27 | * For STR and STM instructions, an ARM core may choose to use either | ||
28 | * a +8 or a +12 displacement from the current instruction's address. | ||
29 | * Whichever value is chosen for a given core, it must be the same for | ||
30 | * both instructions and may not change. This function measures it. | ||
31 | */ | ||
32 | |||
33 | int str_pc_offset; | ||
34 | |||
35 | void __init find_str_pc_offset(void) | ||
36 | { | ||
37 | int addr, scratch, ret; | ||
38 | |||
39 | __asm__ ( | ||
40 | "sub %[ret], pc, #4 \n\t" | ||
41 | "str pc, %[addr] \n\t" | ||
42 | "ldr %[scr], %[addr] \n\t" | ||
43 | "sub %[ret], %[scr], %[ret] \n\t" | ||
44 | : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr)); | ||
45 | |||
46 | str_pc_offset = ret; | ||
47 | } | ||
48 | |||
49 | #endif /* !find_str_pc_offset */ | ||
50 | |||
51 | |||
52 | #ifndef test_load_write_pc_interworking | ||
53 | |||
54 | bool load_write_pc_interworks; | ||
55 | |||
56 | void __init test_load_write_pc_interworking(void) | ||
57 | { | ||
58 | int arch = cpu_architecture(); | ||
59 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
60 | load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T; | ||
61 | } | ||
62 | |||
63 | #endif /* !test_load_write_pc_interworking */ | ||
64 | |||
65 | |||
66 | #ifndef test_alu_write_pc_interworking | ||
67 | |||
68 | bool alu_write_pc_interworks; | ||
69 | |||
70 | void __init test_alu_write_pc_interworking(void) | ||
71 | { | ||
72 | int arch = cpu_architecture(); | ||
73 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
74 | alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; | ||
75 | } | ||
76 | |||
77 | #endif /* !test_alu_write_pc_interworking */ | ||
78 | |||
79 | |||
80 | void __init arm_kprobe_decode_init(void) | ||
81 | { | ||
82 | find_str_pc_offset(); | ||
83 | test_load_write_pc_interworking(); | ||
84 | test_alu_write_pc_interworking(); | ||
85 | } | ||
86 | |||
87 | |||
88 | static unsigned long __kprobes __check_eq(unsigned long cpsr) | ||
89 | { | ||
90 | return cpsr & PSR_Z_BIT; | ||
91 | } | ||
92 | |||
93 | static unsigned long __kprobes __check_ne(unsigned long cpsr) | ||
94 | { | ||
95 | return (~cpsr) & PSR_Z_BIT; | ||
96 | } | ||
97 | |||
98 | static unsigned long __kprobes __check_cs(unsigned long cpsr) | ||
99 | { | ||
100 | return cpsr & PSR_C_BIT; | ||
101 | } | ||
102 | |||
103 | static unsigned long __kprobes __check_cc(unsigned long cpsr) | ||
104 | { | ||
105 | return (~cpsr) & PSR_C_BIT; | ||
106 | } | ||
107 | |||
108 | static unsigned long __kprobes __check_mi(unsigned long cpsr) | ||
109 | { | ||
110 | return cpsr & PSR_N_BIT; | ||
111 | } | ||
112 | |||
113 | static unsigned long __kprobes __check_pl(unsigned long cpsr) | ||
114 | { | ||
115 | return (~cpsr) & PSR_N_BIT; | ||
116 | } | ||
117 | |||
118 | static unsigned long __kprobes __check_vs(unsigned long cpsr) | ||
119 | { | ||
120 | return cpsr & PSR_V_BIT; | ||
121 | } | ||
122 | |||
123 | static unsigned long __kprobes __check_vc(unsigned long cpsr) | ||
124 | { | ||
125 | return (~cpsr) & PSR_V_BIT; | ||
126 | } | ||
127 | |||
128 | static unsigned long __kprobes __check_hi(unsigned long cpsr) | ||
129 | { | ||
130 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
131 | return cpsr & PSR_C_BIT; | ||
132 | } | ||
133 | |||
134 | static unsigned long __kprobes __check_ls(unsigned long cpsr) | ||
135 | { | ||
136 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
137 | return (~cpsr) & PSR_C_BIT; | ||
138 | } | ||
139 | |||
140 | static unsigned long __kprobes __check_ge(unsigned long cpsr) | ||
141 | { | ||
142 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
143 | return (~cpsr) & PSR_N_BIT; | ||
144 | } | ||
145 | |||
146 | static unsigned long __kprobes __check_lt(unsigned long cpsr) | ||
147 | { | ||
148 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
149 | return cpsr & PSR_N_BIT; | ||
150 | } | ||
151 | |||
152 | static unsigned long __kprobes __check_gt(unsigned long cpsr) | ||
153 | { | ||
154 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
155 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
156 | return (~temp) & PSR_N_BIT; | ||
157 | } | ||
158 | |||
159 | static unsigned long __kprobes __check_le(unsigned long cpsr) | ||
160 | { | ||
161 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
162 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
163 | return temp & PSR_N_BIT; | ||
164 | } | ||
165 | |||
166 | static unsigned long __kprobes __check_al(unsigned long cpsr) | ||
167 | { | ||
168 | return true; | ||
169 | } | ||
170 | |||
171 | kprobe_check_cc * const kprobe_condition_checks[16] = { | ||
172 | &__check_eq, &__check_ne, &__check_cs, &__check_cc, | ||
173 | &__check_mi, &__check_pl, &__check_vs, &__check_vc, | ||
174 | &__check_hi, &__check_ls, &__check_ge, &__check_lt, | ||
175 | &__check_gt, &__check_le, &__check_al, &__check_al | ||
176 | }; | ||
177 | |||
178 | |||
179 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs) | ||
180 | { | ||
181 | } | ||
182 | |||
183 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs) | ||
184 | { | ||
185 | p->ainsn.insn_fn(); | ||
186 | } | ||
187 | |||
188 | static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) | 20 | static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) |
189 | { | 21 | { |
190 | kprobe_opcode_t insn = p->opcode; | 22 | kprobe_opcode_t insn = p->opcode; |
@@ -322,260 +154,3 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
322 | return INSN_GOOD_NO_SLOT; | 154 | return INSN_GOOD_NO_SLOT; |
323 | } | 155 | } |
324 | 156 | ||
325 | |||
326 | /* | ||
327 | * Prepare an instruction slot to receive an instruction for emulating. | ||
328 | * This is done by placing a subroutine return after the location where the | ||
329 | * instruction will be placed. We also modify ARM instructions to be | ||
330 | * unconditional as the condition code will already be checked before any | ||
331 | * emulation handler is called. | ||
332 | */ | ||
333 | static kprobe_opcode_t __kprobes | ||
334 | prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
335 | bool thumb) | ||
336 | { | ||
337 | #ifdef CONFIG_THUMB2_KERNEL | ||
338 | if (thumb) { | ||
339 | u16 *thumb_insn = (u16 *)asi->insn; | ||
340 | thumb_insn[1] = 0x4770; /* Thumb bx lr */ | ||
341 | thumb_insn[2] = 0x4770; /* Thumb bx lr */ | ||
342 | return insn; | ||
343 | } | ||
344 | asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ | ||
345 | #else | ||
346 | asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ | ||
347 | #endif | ||
348 | /* Make an ARM instruction unconditional */ | ||
349 | if (insn < 0xe0000000) | ||
350 | insn = (insn | 0xe0000000) & ~0x10000000; | ||
351 | return insn; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * Write a (probably modified) instruction into the slot previously prepared by | ||
356 | * prepare_emulated_insn | ||
357 | */ | ||
358 | static void __kprobes | ||
359 | set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
360 | bool thumb) | ||
361 | { | ||
362 | #ifdef CONFIG_THUMB2_KERNEL | ||
363 | if (thumb) { | ||
364 | u16 *ip = (u16 *)asi->insn; | ||
365 | if (is_wide_instruction(insn)) | ||
366 | *ip++ = insn >> 16; | ||
367 | *ip++ = insn; | ||
368 | return; | ||
369 | } | ||
370 | #endif | ||
371 | asi->insn[0] = insn; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * When we modify the register numbers encoded in an instruction to be emulated, | ||
376 | * the new values come from this define. For ARM and 32-bit Thumb instructions | ||
377 | * this gives... | ||
378 | * | ||
379 | * bit position 16 12 8 4 0 | ||
380 | * ---------------+---+---+---+---+---+ | ||
381 | * register r2 r0 r1 -- r3 | ||
382 | */ | ||
383 | #define INSN_NEW_BITS 0x00020103 | ||
384 | |||
385 | /* Each nibble has same value as that at INSN_NEW_BITS bit 16 */ | ||
386 | #define INSN_SAMEAS16_BITS 0x22222222 | ||
387 | |||
388 | /* | ||
389 | * Validate and modify each of the registers encoded in an instruction. | ||
390 | * | ||
391 | * Each nibble in regs contains a value from enum decode_reg_type. For each | ||
392 | * non-zero value, the corresponding nibble in pinsn is validated and modified | ||
393 | * according to the type. | ||
394 | */ | ||
395 | static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs) | ||
396 | { | ||
397 | kprobe_opcode_t insn = *pinsn; | ||
398 | kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */ | ||
399 | |||
400 | for (; regs != 0; regs >>= 4, mask <<= 4) { | ||
401 | |||
402 | kprobe_opcode_t new_bits = INSN_NEW_BITS; | ||
403 | |||
404 | switch (regs & 0xf) { | ||
405 | |||
406 | case REG_TYPE_NONE: | ||
407 | /* Nibble not a register, skip to next */ | ||
408 | continue; | ||
409 | |||
410 | case REG_TYPE_ANY: | ||
411 | /* Any register is allowed */ | ||
412 | break; | ||
413 | |||
414 | case REG_TYPE_SAMEAS16: | ||
415 | /* Replace register with same as at bit position 16 */ | ||
416 | new_bits = INSN_SAMEAS16_BITS; | ||
417 | break; | ||
418 | |||
419 | case REG_TYPE_SP: | ||
420 | /* Only allow SP (R13) */ | ||
421 | if ((insn ^ 0xdddddddd) & mask) | ||
422 | goto reject; | ||
423 | break; | ||
424 | |||
425 | case REG_TYPE_PC: | ||
426 | /* Only allow PC (R15) */ | ||
427 | if ((insn ^ 0xffffffff) & mask) | ||
428 | goto reject; | ||
429 | break; | ||
430 | |||
431 | case REG_TYPE_NOSP: | ||
432 | /* Reject SP (R13) */ | ||
433 | if (((insn ^ 0xdddddddd) & mask) == 0) | ||
434 | goto reject; | ||
435 | break; | ||
436 | |||
437 | case REG_TYPE_NOSPPC: | ||
438 | case REG_TYPE_NOSPPCX: | ||
439 | /* Reject SP and PC (R13 and R15) */ | ||
440 | if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0) | ||
441 | goto reject; | ||
442 | break; | ||
443 | |||
444 | case REG_TYPE_NOPCWB: | ||
445 | if (!is_writeback(insn)) | ||
446 | break; /* No writeback, so any register is OK */ | ||
447 | /* fall through... */ | ||
448 | case REG_TYPE_NOPC: | ||
449 | case REG_TYPE_NOPCX: | ||
450 | /* Reject PC (R15) */ | ||
451 | if (((insn ^ 0xffffffff) & mask) == 0) | ||
452 | goto reject; | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | /* Replace value of nibble with new register number... */ | ||
457 | insn &= ~mask; | ||
458 | insn |= new_bits & mask; | ||
459 | } | ||
460 | |||
461 | *pinsn = insn; | ||
462 | return true; | ||
463 | |||
464 | reject: | ||
465 | return false; | ||
466 | } | ||
467 | |||
468 | static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | ||
469 | [DECODE_TYPE_TABLE] = sizeof(struct decode_table), | ||
470 | [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), | ||
471 | [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), | ||
472 | [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), | ||
473 | [DECODE_TYPE_OR] = sizeof(struct decode_or), | ||
474 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) | ||
475 | }; | ||
476 | |||
477 | /* | ||
478 | * kprobe_decode_insn operates on data tables in order to decode an ARM | ||
479 | * architecture instruction onto which a kprobe has been placed. | ||
480 | * | ||
481 | * These instruction decoding tables are a concatenation of entries each | ||
482 | * of which consist of one of the following structs: | ||
483 | * | ||
484 | * decode_table | ||
485 | * decode_custom | ||
486 | * decode_simulate | ||
487 | * decode_emulate | ||
488 | * decode_or | ||
489 | * decode_reject | ||
490 | * | ||
491 | * Each of these starts with a struct decode_header which has the following | ||
492 | * fields: | ||
493 | * | ||
494 | * type_regs | ||
495 | * mask | ||
496 | * value | ||
497 | * | ||
498 | * The least significant DECODE_TYPE_BITS of type_regs contains a value | ||
499 | * from enum decode_type, this indicates which of the decode_* structs | ||
500 | * the entry contains. The value DECODE_TYPE_END indicates the end of the | ||
501 | * table. | ||
502 | * | ||
503 | * When the table is parsed, each entry is checked in turn to see if it | ||
504 | * matches the instruction to be decoded using the test: | ||
505 | * | ||
506 | * (insn & mask) == value | ||
507 | * | ||
508 | * If no match is found before the end of the table is reached then decoding | ||
509 | * fails with INSN_REJECTED. | ||
510 | * | ||
511 | * When a match is found, decode_regs() is called to validate and modify each | ||
512 | * of the registers encoded in the instruction; the data it uses to do this | ||
513 | * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding | ||
514 | * to fail with INSN_REJECTED. | ||
515 | * | ||
516 | * Once the instruction has passed the above tests, further processing | ||
517 | * depends on the type of the table entry's decode struct. | ||
518 | * | ||
519 | */ | ||
520 | int __kprobes | ||
521 | kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
522 | const union decode_item *table, bool thumb) | ||
523 | { | ||
524 | const struct decode_header *h = (struct decode_header *)table; | ||
525 | const struct decode_header *next; | ||
526 | bool matched = false; | ||
527 | |||
528 | insn = prepare_emulated_insn(insn, asi, thumb); | ||
529 | |||
530 | for (;; h = next) { | ||
531 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; | ||
532 | u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; | ||
533 | |||
534 | if (type == DECODE_TYPE_END) | ||
535 | return INSN_REJECTED; | ||
536 | |||
537 | next = (struct decode_header *) | ||
538 | ((uintptr_t)h + decode_struct_sizes[type]); | ||
539 | |||
540 | if (!matched && (insn & h->mask.bits) != h->value.bits) | ||
541 | continue; | ||
542 | |||
543 | if (!decode_regs(&insn, regs)) | ||
544 | return INSN_REJECTED; | ||
545 | |||
546 | switch (type) { | ||
547 | |||
548 | case DECODE_TYPE_TABLE: { | ||
549 | struct decode_table *d = (struct decode_table *)h; | ||
550 | next = (struct decode_header *)d->table.table; | ||
551 | break; | ||
552 | } | ||
553 | |||
554 | case DECODE_TYPE_CUSTOM: { | ||
555 | struct decode_custom *d = (struct decode_custom *)h; | ||
556 | return (*d->decoder.decoder)(insn, asi); | ||
557 | } | ||
558 | |||
559 | case DECODE_TYPE_SIMULATE: { | ||
560 | struct decode_simulate *d = (struct decode_simulate *)h; | ||
561 | asi->insn_handler = d->handler.handler; | ||
562 | return INSN_GOOD_NO_SLOT; | ||
563 | } | ||
564 | |||
565 | case DECODE_TYPE_EMULATE: { | ||
566 | struct decode_emulate *d = (struct decode_emulate *)h; | ||
567 | asi->insn_handler = d->handler.handler; | ||
568 | set_emulated_insn(insn, asi, thumb); | ||
569 | return INSN_GOOD; | ||
570 | } | ||
571 | |||
572 | case DECODE_TYPE_OR: | ||
573 | matched = true; | ||
574 | break; | ||
575 | |||
576 | case DECODE_TYPE_REJECT: | ||
577 | default: | ||
578 | return INSN_REJECTED; | ||
579 | } | ||
580 | } | ||
581 | } | ||
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h index 38945f78f9f1..aa68c0ea1a0b 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/kernel/kprobes.h | |||
@@ -52,377 +52,6 @@ enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t, | |||
52 | 52 | ||
53 | void __init arm_kprobe_decode_init(void); | 53 | void __init arm_kprobe_decode_init(void); |
54 | 54 | ||
55 | extern kprobe_check_cc * const kprobe_condition_checks[16]; | 55 | #include "probes.h" |
56 | |||
57 | |||
58 | #if __LINUX_ARM_ARCH__ >= 7 | ||
59 | |||
60 | /* str_pc_offset is architecturally defined from ARMv7 onwards */ | ||
61 | #define str_pc_offset 8 | ||
62 | #define find_str_pc_offset() | ||
63 | |||
64 | #else /* __LINUX_ARM_ARCH__ < 7 */ | ||
65 | |||
66 | /* We need a run-time check to determine str_pc_offset */ | ||
67 | extern int str_pc_offset; | ||
68 | void __init find_str_pc_offset(void); | ||
69 | |||
70 | #endif | ||
71 | |||
72 | |||
73 | /* | ||
74 | * Update ITSTATE after normal execution of an IT block instruction. | ||
75 | * | ||
76 | * The 8 IT state bits are split into two parts in CPSR: | ||
77 | * ITSTATE<1:0> are in CPSR<26:25> | ||
78 | * ITSTATE<7:2> are in CPSR<15:10> | ||
79 | */ | ||
80 | static inline unsigned long it_advance(unsigned long cpsr) | ||
81 | { | ||
82 | if ((cpsr & 0x06000400) == 0) { | ||
83 | /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */ | ||
84 | cpsr &= ~PSR_IT_MASK; | ||
85 | } else { | ||
86 | /* We need to shift left ITSTATE<4:0> */ | ||
87 | const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */ | ||
88 | unsigned long it = cpsr & mask; | ||
89 | it <<= 1; | ||
90 | it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */ | ||
91 | it &= mask; | ||
92 | cpsr &= ~mask; | ||
93 | cpsr |= it; | ||
94 | } | ||
95 | return cpsr; | ||
96 | } | ||
97 | |||
98 | static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs) | ||
99 | { | ||
100 | long cpsr = regs->ARM_cpsr; | ||
101 | if (pcv & 0x1) { | ||
102 | cpsr |= PSR_T_BIT; | ||
103 | pcv &= ~0x1; | ||
104 | } else { | ||
105 | cpsr &= ~PSR_T_BIT; | ||
106 | pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */ | ||
107 | } | ||
108 | regs->ARM_cpsr = cpsr; | ||
109 | regs->ARM_pc = pcv; | ||
110 | } | ||
111 | |||
112 | |||
113 | #if __LINUX_ARM_ARCH__ >= 6 | ||
114 | |||
115 | /* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */ | ||
116 | #define load_write_pc_interworks true | ||
117 | #define test_load_write_pc_interworking() | ||
118 | |||
119 | #else /* __LINUX_ARM_ARCH__ < 6 */ | ||
120 | |||
121 | /* We need run-time testing to determine if load_write_pc() should interwork. */ | ||
122 | extern bool load_write_pc_interworks; | ||
123 | void __init test_load_write_pc_interworking(void); | ||
124 | |||
125 | #endif | ||
126 | |||
127 | static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs) | ||
128 | { | ||
129 | if (load_write_pc_interworks) | ||
130 | bx_write_pc(pcv, regs); | ||
131 | else | ||
132 | regs->ARM_pc = pcv; | ||
133 | } | ||
134 | |||
135 | |||
136 | #if __LINUX_ARM_ARCH__ >= 7 | ||
137 | |||
138 | #define alu_write_pc_interworks true | ||
139 | #define test_alu_write_pc_interworking() | ||
140 | |||
141 | #elif __LINUX_ARM_ARCH__ <= 5 | ||
142 | |||
143 | /* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */ | ||
144 | #define alu_write_pc_interworks false | ||
145 | #define test_alu_write_pc_interworking() | ||
146 | |||
147 | #else /* __LINUX_ARM_ARCH__ == 6 */ | ||
148 | |||
149 | /* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */ | ||
150 | extern bool alu_write_pc_interworks; | ||
151 | void __init test_alu_write_pc_interworking(void); | ||
152 | |||
153 | #endif /* __LINUX_ARM_ARCH__ == 6 */ | ||
154 | |||
155 | static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) | ||
156 | { | ||
157 | if (alu_write_pc_interworks) | ||
158 | bx_write_pc(pcv, regs); | ||
159 | else | ||
160 | regs->ARM_pc = pcv; | ||
161 | } | ||
162 | |||
163 | |||
164 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); | ||
165 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); | ||
166 | |||
167 | enum kprobe_insn __kprobes | ||
168 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); | ||
169 | |||
170 | /* | ||
171 | * Test if load/store instructions writeback the address register. | ||
172 | * if P (bit 24) == 0 or W (bit 21) == 1 | ||
173 | */ | ||
174 | #define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000) | ||
175 | |||
176 | /* | ||
177 | * The following definitions and macros are used to build instruction | ||
178 | * decoding tables for use by kprobe_decode_insn. | ||
179 | * | ||
180 | * These tables are a concatenation of entries each of which consist of one of | ||
181 | * the decode_* structs. All of the fields in every type of decode structure | ||
182 | * are of the union type decode_item, therefore the entire decode table can be | ||
183 | * viewed as an array of these and declared like: | ||
184 | * | ||
185 | * static const union decode_item table_name[] = {}; | ||
186 | * | ||
187 | * In order to construct each entry in the table, macros are used to | ||
188 | * initialise a number of sequential decode_item values in a layout which | ||
189 | * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct | ||
190 | * decode_simulate by initialising four decode_item objects like this... | ||
191 | * | ||
192 | * {.bits = _type}, | ||
193 | * {.bits = _mask}, | ||
194 | * {.bits = _value}, | ||
195 | * {.handler = _handler}, | ||
196 | * | ||
197 | * Initialising a specified member of the union means that the compiler | ||
198 | * will produce a warning if the argument is of an incorrect type. | ||
199 | * | ||
200 | * Below is a list of each of the macros used to initialise entries and a | ||
201 | * description of the action performed when that entry is matched to an | ||
202 | * instruction. A match is found when (instruction & mask) == value. | ||
203 | * | ||
204 | * DECODE_TABLE(mask, value, table) | ||
205 | * Instruction decoding jumps to parsing the new sub-table 'table'. | ||
206 | * | ||
207 | * DECODE_CUSTOM(mask, value, decoder) | ||
208 | * The custom function 'decoder' is called to the complete decoding | ||
209 | * of an instruction. | ||
210 | * | ||
211 | * DECODE_SIMULATE(mask, value, handler) | ||
212 | * Set the probes instruction handler to 'handler', this will be used | ||
213 | * to simulate the instruction when the probe is hit. Decoding returns | ||
214 | * with INSN_GOOD_NO_SLOT. | ||
215 | * | ||
216 | * DECODE_EMULATE(mask, value, handler) | ||
217 | * Set the probes instruction handler to 'handler', this will be used | ||
218 | * to emulate the instruction when the probe is hit. The modified | ||
219 | * instruction (see below) is placed in the probes instruction slot so it | ||
220 | * may be called by the emulation code. Decoding returns with INSN_GOOD. | ||
221 | * | ||
222 | * DECODE_REJECT(mask, value) | ||
223 | * Instruction decoding fails with INSN_REJECTED | ||
224 | * | ||
225 | * DECODE_OR(mask, value) | ||
226 | * This allows the mask/value test of multiple table entries to be | ||
227 | * logically ORed. Once an 'or' entry is matched the decoding action to | ||
228 | * be performed is that of the next entry which isn't an 'or'. E.g. | ||
229 | * | ||
230 | * DECODE_OR (mask1, value1) | ||
231 | * DECODE_OR (mask2, value2) | ||
232 | * DECODE_SIMULATE (mask3, value3, simulation_handler) | ||
233 | * | ||
234 | * This means that if any of the three mask/value pairs match the | ||
235 | * instruction being decoded, then 'simulation_handler' will be used | ||
236 | * for it. | ||
237 | * | ||
238 | * Both the SIMULATE and EMULATE macros have a second form which take an | ||
239 | * additional 'regs' argument. | ||
240 | * | ||
241 | * DECODE_SIMULATEX(mask, value, handler, regs) | ||
242 | * DECODE_EMULATEX (mask, value, handler, regs) | ||
243 | * | ||
244 | * These are used to specify what kind of CPU register is encoded in each of the | ||
245 | * least significant 5 nibbles of the instruction being decoded. The regs value | ||
246 | * is specified using the REGS macro, this takes any of the REG_TYPE_* values | ||
247 | * from enum decode_reg_type as arguments; only the '*' part of the name is | ||
248 | * given. E.g. | ||
249 | * | ||
250 | * REGS(0, ANY, NOPC, 0, ANY) | ||
251 | * | ||
252 | * This indicates an instruction is encoded like: | ||
253 | * | ||
254 | * bits 19..16 ignore | ||
255 | * bits 15..12 any register allowed here | ||
256 | * bits 11.. 8 any register except PC allowed here | ||
257 | * bits 7.. 4 ignore | ||
258 | * bits 3.. 0 any register allowed here | ||
259 | * | ||
260 | * This register specification is checked after a decode table entry is found to | ||
261 | * match an instruction (through the mask/value test). Any invalid register then | ||
262 | * found in the instruction will cause decoding to fail with INSN_REJECTED. In | ||
263 | * the above example this would happen if bits 11..8 of the instruction were | ||
264 | * 1111, indicating R15 or PC. | ||
265 | * | ||
266 | * As well as checking for legal combinations of registers, this data is also | ||
267 | * used to modify the registers encoded in the instructions so that an | ||
268 | * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.) | ||
269 | * | ||
270 | * Here is a real example which matches ARM instructions of the form | ||
271 | * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>" | ||
272 | * | ||
273 | * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, | ||
274 | * REGS(ANY, ANY, NOPC, 0, ANY)), | ||
275 | * ^ ^ ^ ^ | ||
276 | * Rn Rd Rs Rm | ||
277 | * | ||
278 | * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because | ||
279 | * Rs == R15 | ||
280 | * | ||
281 | * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the | ||
282 | * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into | ||
283 | * the kprobes instruction slot. This can then be called later by the handler | ||
284 | * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction. | ||
285 | */ | ||
286 | |||
287 | enum decode_type { | ||
288 | DECODE_TYPE_END, | ||
289 | DECODE_TYPE_TABLE, | ||
290 | DECODE_TYPE_CUSTOM, | ||
291 | DECODE_TYPE_SIMULATE, | ||
292 | DECODE_TYPE_EMULATE, | ||
293 | DECODE_TYPE_OR, | ||
294 | DECODE_TYPE_REJECT, | ||
295 | NUM_DECODE_TYPES /* Must be last enum */ | ||
296 | }; | ||
297 | |||
298 | #define DECODE_TYPE_BITS 4 | ||
299 | #define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1) | ||
300 | |||
301 | enum decode_reg_type { | ||
302 | REG_TYPE_NONE = 0, /* Not a register, ignore */ | ||
303 | REG_TYPE_ANY, /* Any register allowed */ | ||
304 | REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */ | ||
305 | REG_TYPE_SP, /* Register must be SP */ | ||
306 | REG_TYPE_PC, /* Register must be PC */ | ||
307 | REG_TYPE_NOSP, /* Register must not be SP */ | ||
308 | REG_TYPE_NOSPPC, /* Register must not be SP or PC */ | ||
309 | REG_TYPE_NOPC, /* Register must not be PC */ | ||
310 | REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */ | ||
311 | |||
312 | /* The following types are used when the encoding for PC indicates | ||
313 | * another instruction form. This distiction only matters for test | ||
314 | * case coverage checks. | ||
315 | */ | ||
316 | REG_TYPE_NOPCX, /* Register must not be PC */ | ||
317 | REG_TYPE_NOSPPCX, /* Register must not be SP or PC */ | ||
318 | |||
319 | /* Alias to allow '0' arg to be used in REGS macro. */ | ||
320 | REG_TYPE_0 = REG_TYPE_NONE | ||
321 | }; | ||
322 | |||
323 | #define REGS(r16, r12, r8, r4, r0) \ | ||
324 | ((REG_TYPE_##r16) << 16) + \ | ||
325 | ((REG_TYPE_##r12) << 12) + \ | ||
326 | ((REG_TYPE_##r8) << 8) + \ | ||
327 | ((REG_TYPE_##r4) << 4) + \ | ||
328 | (REG_TYPE_##r0) | ||
329 | |||
330 | union decode_item { | ||
331 | u32 bits; | ||
332 | const union decode_item *table; | ||
333 | kprobe_insn_handler_t *handler; | ||
334 | kprobe_decode_insn_t *decoder; | ||
335 | }; | ||
336 | |||
337 | |||
338 | #define DECODE_END \ | ||
339 | {.bits = DECODE_TYPE_END} | ||
340 | |||
341 | |||
342 | struct decode_header { | ||
343 | union decode_item type_regs; | ||
344 | union decode_item mask; | ||
345 | union decode_item value; | ||
346 | }; | ||
347 | |||
348 | #define DECODE_HEADER(_type, _mask, _value, _regs) \ | ||
349 | {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \ | ||
350 | {.bits = (_mask)}, \ | ||
351 | {.bits = (_value)} | ||
352 | |||
353 | |||
354 | struct decode_table { | ||
355 | struct decode_header header; | ||
356 | union decode_item table; | ||
357 | }; | ||
358 | |||
359 | #define DECODE_TABLE(_mask, _value, _table) \ | ||
360 | DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \ | ||
361 | {.table = (_table)} | ||
362 | |||
363 | |||
364 | struct decode_custom { | ||
365 | struct decode_header header; | ||
366 | union decode_item decoder; | ||
367 | }; | ||
368 | |||
369 | #define DECODE_CUSTOM(_mask, _value, _decoder) \ | ||
370 | DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \ | ||
371 | {.decoder = (_decoder)} | ||
372 | |||
373 | |||
374 | struct decode_simulate { | ||
375 | struct decode_header header; | ||
376 | union decode_item handler; | ||
377 | }; | ||
378 | |||
379 | #define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \ | ||
380 | DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \ | ||
381 | {.handler = (_handler)} | ||
382 | |||
383 | #define DECODE_SIMULATE(_mask, _value, _handler) \ | ||
384 | DECODE_SIMULATEX(_mask, _value, _handler, 0) | ||
385 | |||
386 | |||
387 | struct decode_emulate { | ||
388 | struct decode_header header; | ||
389 | union decode_item handler; | ||
390 | }; | ||
391 | |||
392 | #define DECODE_EMULATEX(_mask, _value, _handler, _regs) \ | ||
393 | DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \ | ||
394 | {.handler = (_handler)} | ||
395 | |||
396 | #define DECODE_EMULATE(_mask, _value, _handler) \ | ||
397 | DECODE_EMULATEX(_mask, _value, _handler, 0) | ||
398 | |||
399 | |||
400 | struct decode_or { | ||
401 | struct decode_header header; | ||
402 | }; | ||
403 | |||
404 | #define DECODE_OR(_mask, _value) \ | ||
405 | DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0) | ||
406 | |||
407 | |||
408 | struct decode_reject { | ||
409 | struct decode_header header; | ||
410 | }; | ||
411 | |||
412 | #define DECODE_REJECT(_mask, _value) \ | ||
413 | DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) | ||
414 | |||
415 | |||
416 | #ifdef CONFIG_THUMB2_KERNEL | ||
417 | extern const union decode_item kprobe_decode_thumb16_table[]; | ||
418 | extern const union decode_item kprobe_decode_thumb32_table[]; | ||
419 | #else | ||
420 | extern const union decode_item kprobe_decode_arm_table[]; | ||
421 | #endif | ||
422 | |||
423 | |||
424 | int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
425 | const union decode_item *table, bool thumb16); | ||
426 | |||
427 | 56 | ||
428 | #endif /* _ARM_KERNEL_KPROBES_H */ | 57 | #endif /* _ARM_KERNEL_KPROBES_H */ |
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c new file mode 100644 index 000000000000..57e08b28e87f --- /dev/null +++ b/arch/arm/kernel/probes-arm.c | |||
@@ -0,0 +1,731 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes-arm.c | ||
3 | * | ||
4 | * Some code moved here from arch/arm/kernel/kprobes-arm.c | ||
5 | * | ||
6 | * Copyright (C) 2006, 2007 Motorola Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/stddef.h> | ||
21 | #include <linux/ptrace.h> | ||
22 | #include <linux/kprobes.h> | ||
23 | |||
24 | #include "kprobes.h" | ||
25 | #include "probes-arm.h" | ||
26 | |||
27 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) | ||
28 | |||
29 | #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) | ||
30 | |||
31 | /* | ||
32 | * To avoid the complications of mimicing single-stepping on a | ||
33 | * processor without a Next-PC or a single-step mode, and to | ||
34 | * avoid having to deal with the side-effects of boosting, we | ||
35 | * simulate or emulate (almost) all ARM instructions. | ||
36 | * | ||
37 | * "Simulation" is where the instruction's behavior is duplicated in | ||
38 | * C code. "Emulation" is where the original instruction is rewritten | ||
39 | * and executed, often by altering its registers. | ||
40 | * | ||
41 | * By having all behavior of the kprobe'd instruction completed before | ||
42 | * returning from the kprobe_handler(), all locks (scheduler and | ||
43 | * interrupt) can safely be released. There is no need for secondary | ||
44 | * breakpoints, no race with MP or preemptable kernels, nor having to | ||
45 | * clean up resources counts at a later time impacting overall system | ||
46 | * performance. By rewriting the instruction, only the minimum registers | ||
47 | * need to be loaded and saved back optimizing performance. | ||
48 | * | ||
49 | * Calling the insnslot_*_rwflags version of a function doesn't hurt | ||
50 | * anything even when the CPSR flags aren't updated by the | ||
51 | * instruction. It's just a little slower in return for saving | ||
52 | * a little space by not having a duplicate function that doesn't | ||
53 | * update the flags. (The same optimization can be said for | ||
54 | * instructions that do or don't perform register writeback) | ||
55 | * Also, instructions can either read the flags, only write the | ||
56 | * flags, or read and write the flags. To save combinations | ||
57 | * rather than for sheer performance, flag functions just assume | ||
58 | * read and write of flags. | ||
59 | */ | ||
60 | |||
61 | void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) | ||
62 | { | ||
63 | kprobe_opcode_t insn = p->opcode; | ||
64 | long iaddr = (long)p->addr; | ||
65 | int disp = branch_displacement(insn); | ||
66 | |||
67 | if (insn & (1 << 24)) | ||
68 | regs->ARM_lr = iaddr + 4; | ||
69 | |||
70 | regs->ARM_pc = iaddr + 8 + disp; | ||
71 | } | ||
72 | |||
73 | void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) | ||
74 | { | ||
75 | kprobe_opcode_t insn = p->opcode; | ||
76 | long iaddr = (long)p->addr; | ||
77 | int disp = branch_displacement(insn); | ||
78 | |||
79 | regs->ARM_lr = iaddr + 4; | ||
80 | regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2); | ||
81 | regs->ARM_cpsr |= PSR_T_BIT; | ||
82 | } | ||
83 | |||
84 | void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) | ||
85 | { | ||
86 | kprobe_opcode_t insn = p->opcode; | ||
87 | int rm = insn & 0xf; | ||
88 | long rmv = regs->uregs[rm]; | ||
89 | |||
90 | if (insn & (1 << 5)) | ||
91 | regs->ARM_lr = (long)p->addr + 4; | ||
92 | |||
93 | regs->ARM_pc = rmv & ~0x1; | ||
94 | regs->ARM_cpsr &= ~PSR_T_BIT; | ||
95 | if (rmv & 0x1) | ||
96 | regs->ARM_cpsr |= PSR_T_BIT; | ||
97 | } | ||
98 | |||
99 | void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) | ||
100 | { | ||
101 | kprobe_opcode_t insn = p->opcode; | ||
102 | int rd = (insn >> 12) & 0xf; | ||
103 | unsigned long mask = 0xf8ff03df; /* Mask out execution state */ | ||
104 | regs->uregs[rd] = regs->ARM_cpsr & mask; | ||
105 | } | ||
106 | |||
107 | void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) | ||
108 | { | ||
109 | regs->uregs[12] = regs->uregs[13]; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * For the instruction masking and comparisons in all the "space_*" | ||
114 | * functions below, Do _not_ rearrange the order of tests unless | ||
115 | * you're very, very sure of what you are doing. For the sake of | ||
116 | * efficiency, the masks for some tests sometimes assume other test | ||
117 | * have been done prior to them so the number of patterns to test | ||
118 | * for an instruction set can be as broad as possible to reduce the | ||
119 | * number of tests needed. | ||
120 | */ | ||
121 | |||
122 | static const union decode_item arm_1111_table[] = { | ||
123 | /* Unconditional instructions */ | ||
124 | |||
125 | /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */ | ||
126 | /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */ | ||
127 | /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */ | ||
128 | /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */ | ||
129 | DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop), | ||
130 | |||
131 | /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */ | ||
132 | /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */ | ||
133 | /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */ | ||
134 | /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */ | ||
135 | DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop), | ||
136 | |||
137 | /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
138 | DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1), | ||
139 | |||
140 | /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ | ||
141 | /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ | ||
142 | /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
143 | /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
144 | |||
145 | /* Coprocessor instructions... */ | ||
146 | /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
147 | /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
148 | /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | ||
149 | /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | ||
150 | /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | ||
151 | /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
152 | /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
153 | |||
154 | /* Other unallocated instructions... */ | ||
155 | DECODE_END | ||
156 | }; | ||
157 | |||
158 | static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { | ||
159 | /* Miscellaneous instructions */ | ||
160 | |||
161 | /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
162 | DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs, | ||
163 | REGS(0, NOPC, 0, 0, 0)), | ||
164 | |||
165 | /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
166 | DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx), | ||
167 | |||
168 | /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
169 | DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx, | ||
170 | REGS(0, 0, 0, 0, NOPC)), | ||
171 | |||
172 | /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
173 | DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc, | ||
174 | REGS(0, NOPC, 0, 0, NOPC)), | ||
175 | |||
176 | /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ | ||
177 | /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
178 | /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ | ||
179 | /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
180 | DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc, | ||
181 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
182 | |||
183 | /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ | ||
184 | /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ | ||
185 | /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ | ||
186 | /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
187 | /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
188 | /* And unallocated instructions... */ | ||
189 | DECODE_END | ||
190 | }; | ||
191 | |||
192 | static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { | ||
193 | /* Halfword multiply and multiply-accumulate */ | ||
194 | |||
195 | /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | ||
196 | DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
197 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
198 | |||
199 | /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | ||
200 | DECODE_OR (0x0ff000b0, 0x012000a0), | ||
201 | /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | ||
202 | DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
203 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
204 | |||
205 | /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ | ||
206 | DECODE_OR (0x0ff00090, 0x01000080), | ||
207 | /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ | ||
208 | DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
209 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
210 | |||
211 | DECODE_END | ||
212 | }; | ||
213 | |||
214 | static const union decode_item arm_cccc_0000_____1001_table[] = { | ||
215 | /* Multiply and multiply-accumulate */ | ||
216 | |||
217 | /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ | ||
218 | /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
219 | DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
220 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
221 | |||
222 | /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
223 | /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
224 | DECODE_OR (0x0fe000f0, 0x00200090), | ||
225 | /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
226 | DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
227 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
228 | |||
229 | /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ | ||
230 | DECODE_OR (0x0ff000f0, 0x00400090), | ||
231 | /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */ | ||
232 | /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */ | ||
233 | /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */ | ||
234 | /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */ | ||
235 | /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */ | ||
236 | /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ | ||
237 | /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ | ||
238 | /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ | ||
239 | DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
240 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
241 | |||
242 | DECODE_END | ||
243 | }; | ||
244 | |||
245 | static const union decode_item arm_cccc_0001_____1001_table[] = { | ||
246 | /* Synchronization primitives */ | ||
247 | |||
248 | #if __LINUX_ARM_ARCH__ < 6 | ||
249 | /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ | ||
250 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ | ||
251 | DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, | ||
252 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
253 | #endif | ||
254 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ | ||
255 | /* And unallocated instructions... */ | ||
256 | DECODE_END | ||
257 | }; | ||
258 | |||
259 | static const union decode_item arm_cccc_000x_____1xx1_table[] = { | ||
260 | /* Extra load/store instructions */ | ||
261 | |||
262 | /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */ | ||
263 | /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */ | ||
264 | /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */ | ||
265 | /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */ | ||
266 | /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */ | ||
267 | DECODE_REJECT (0x0f200090, 0x00200090), | ||
268 | |||
269 | /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ | ||
270 | DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), | ||
271 | |||
272 | /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */ | ||
273 | /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */ | ||
274 | DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd, | ||
275 | REGS(NOPCWB, NOPCX, 0, 0, NOPC)), | ||
276 | |||
277 | /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */ | ||
278 | /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */ | ||
279 | DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, | ||
280 | REGS(NOPCWB, NOPCX, 0, 0, 0)), | ||
281 | |||
282 | /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ | ||
283 | DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str, | ||
284 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
285 | |||
286 | /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ | ||
287 | /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ | ||
288 | /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ | ||
289 | DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr, | ||
290 | REGS(NOPCWB, NOPC, 0, 0, NOPC)), | ||
291 | |||
292 | /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ | ||
293 | DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str, | ||
294 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
295 | |||
296 | /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ | ||
297 | /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ | ||
298 | /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ | ||
299 | DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr, | ||
300 | REGS(NOPCWB, NOPC, 0, 0, 0)), | ||
301 | |||
302 | DECODE_END | ||
303 | }; | ||
304 | |||
305 | static const union decode_item arm_cccc_000x_table[] = { | ||
306 | /* Data-processing (register) */ | ||
307 | |||
308 | /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
309 | DECODE_REJECT (0x0e10f000, 0x0010f000), | ||
310 | |||
311 | /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */ | ||
312 | DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp), | ||
313 | |||
314 | /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */ | ||
315 | /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */ | ||
316 | /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */ | ||
317 | /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */ | ||
318 | DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags, | ||
319 | REGS(ANY, 0, 0, 0, ANY)), | ||
320 | |||
321 | /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
322 | /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
323 | DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags, | ||
324 | REGS(0, ANY, 0, 0, ANY)), | ||
325 | |||
326 | /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */ | ||
327 | /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */ | ||
328 | /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */ | ||
329 | /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */ | ||
330 | /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
331 | /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */ | ||
332 | /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
333 | /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */ | ||
334 | /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */ | ||
335 | /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */ | ||
336 | DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags, | ||
337 | REGS(ANY, ANY, 0, 0, ANY)), | ||
338 | |||
339 | /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */ | ||
340 | /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */ | ||
341 | /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */ | ||
342 | /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */ | ||
343 | DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags, | ||
344 | REGS(ANY, 0, NOPC, 0, ANY)), | ||
345 | |||
346 | /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
347 | /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
348 | DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags, | ||
349 | REGS(0, ANY, NOPC, 0, ANY)), | ||
350 | |||
351 | /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */ | ||
352 | /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */ | ||
353 | /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */ | ||
354 | /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */ | ||
355 | /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
356 | /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */ | ||
357 | /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
358 | /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */ | ||
359 | /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */ | ||
360 | /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */ | ||
361 | DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, | ||
362 | REGS(ANY, ANY, NOPC, 0, ANY)), | ||
363 | |||
364 | DECODE_END | ||
365 | }; | ||
366 | |||
367 | static const union decode_item arm_cccc_001x_table[] = { | ||
368 | /* Data-processing (immediate) */ | ||
369 | |||
370 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | ||
371 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
372 | DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc, | ||
373 | REGS(0, NOPC, 0, 0, 0)), | ||
374 | |||
375 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | ||
376 | DECODE_OR (0x0fff00ff, 0x03200001), | ||
377 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | ||
378 | DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none), | ||
379 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | ||
380 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | ||
381 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | ||
382 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop), | ||
383 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ | ||
384 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | ||
385 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ | ||
386 | DECODE_REJECT (0x0fb00000, 0x03200000), | ||
387 | |||
388 | /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ | ||
389 | DECODE_REJECT (0x0e10f000, 0x0210f000), | ||
390 | |||
391 | /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */ | ||
392 | /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ | ||
393 | /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
394 | /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ | ||
395 | DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags, | ||
396 | REGS(ANY, 0, 0, 0, 0)), | ||
397 | |||
398 | /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ | ||
399 | /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ | ||
400 | DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags, | ||
401 | REGS(0, ANY, 0, 0, 0)), | ||
402 | |||
403 | /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ | ||
404 | /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */ | ||
405 | /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */ | ||
406 | /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */ | ||
407 | /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */ | ||
408 | /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */ | ||
409 | /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */ | ||
410 | /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ | ||
411 | /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ | ||
412 | /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ | ||
413 | DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags, | ||
414 | REGS(ANY, ANY, 0, 0, 0)), | ||
415 | |||
416 | DECODE_END | ||
417 | }; | ||
418 | |||
419 | static const union decode_item arm_cccc_0110_____xxx1_table[] = { | ||
420 | /* Media instructions */ | ||
421 | |||
422 | /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */ | ||
423 | DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc, | ||
424 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
425 | |||
426 | /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */ | ||
427 | /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */ | ||
428 | DECODE_OR(0x0fa00030, 0x06a00010), | ||
429 | /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */ | ||
430 | /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */ | ||
431 | DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc, | ||
432 | REGS(0, NOPC, 0, 0, NOPC)), | ||
433 | |||
434 | /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ | ||
435 | /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ | ||
436 | /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ | ||
437 | /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ | ||
438 | DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc, | ||
439 | REGS(0, NOPC, 0, 0, NOPC)), | ||
440 | |||
441 | /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */ | ||
442 | DECODE_REJECT (0x0fb00010, 0x06000010), | ||
443 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */ | ||
444 | DECODE_REJECT (0x0f8000f0, 0x060000b0), | ||
445 | /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */ | ||
446 | DECODE_REJECT (0x0f8000f0, 0x060000d0), | ||
447 | /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */ | ||
448 | /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */ | ||
449 | /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */ | ||
450 | /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */ | ||
451 | /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
452 | /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */ | ||
453 | /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
454 | /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
455 | /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
456 | /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
457 | /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
458 | /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */ | ||
459 | /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */ | ||
460 | /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */ | ||
461 | /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */ | ||
462 | /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */ | ||
463 | /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
464 | /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */ | ||
465 | /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */ | ||
466 | /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */ | ||
467 | /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */ | ||
468 | /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */ | ||
469 | /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */ | ||
470 | /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */ | ||
471 | /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
472 | /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */ | ||
473 | /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
474 | /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
475 | /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
476 | /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */ | ||
477 | /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */ | ||
478 | /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */ | ||
479 | /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */ | ||
480 | /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */ | ||
481 | /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */ | ||
482 | /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */ | ||
483 | DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc, | ||
484 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
485 | |||
486 | /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */ | ||
487 | /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */ | ||
488 | DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc, | ||
489 | REGS(NOPC, NOPC, 0, 0, NOPC)), | ||
490 | |||
491 | /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */ | ||
492 | /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */ | ||
493 | DECODE_REJECT (0x0fb000f0, 0x06900070), | ||
494 | |||
495 | /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */ | ||
496 | /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */ | ||
497 | /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */ | ||
498 | /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */ | ||
499 | /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */ | ||
500 | /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */ | ||
501 | DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc, | ||
502 | REGS(0, NOPC, 0, 0, NOPC)), | ||
503 | |||
504 | /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */ | ||
505 | /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */ | ||
506 | /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */ | ||
507 | /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */ | ||
508 | /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */ | ||
509 | /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */ | ||
510 | DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc, | ||
511 | REGS(NOPCX, NOPC, 0, 0, NOPC)), | ||
512 | |||
513 | DECODE_END | ||
514 | }; | ||
515 | |||
516 | static const union decode_item arm_cccc_0111_____xxx1_table[] = { | ||
517 | /* Media instructions */ | ||
518 | |||
519 | /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */ | ||
520 | DECODE_REJECT (0x0ff000f0, 0x07f000f0), | ||
521 | |||
522 | /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ | ||
523 | /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ | ||
524 | DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, | ||
525 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
526 | |||
527 | /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */ | ||
528 | /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */ | ||
529 | DECODE_OR (0x0ff0f090, 0x0700f010), | ||
530 | /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */ | ||
531 | DECODE_OR (0x0ff0f0d0, 0x0750f010), | ||
532 | /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ | ||
533 | DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
534 | REGS(NOPC, 0, NOPC, 0, NOPC)), | ||
535 | |||
536 | /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */ | ||
537 | /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */ | ||
538 | DECODE_OR (0x0ff00090, 0x07000010), | ||
539 | /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */ | ||
540 | DECODE_OR (0x0ff000d0, 0x07500010), | ||
541 | /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ | ||
542 | DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
543 | REGS(NOPC, NOPCX, NOPC, 0, NOPC)), | ||
544 | |||
545 | /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ | ||
546 | DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc, | ||
547 | REGS(NOPC, NOPC, NOPC, 0, NOPC)), | ||
548 | |||
549 | /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */ | ||
550 | /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */ | ||
551 | DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc, | ||
552 | REGS(0, NOPC, 0, 0, NOPC)), | ||
553 | |||
554 | /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ | ||
555 | DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc, | ||
556 | REGS(0, NOPC, 0, 0, 0)), | ||
557 | |||
558 | /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ | ||
559 | DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc, | ||
560 | REGS(0, NOPC, 0, 0, NOPCX)), | ||
561 | |||
562 | DECODE_END | ||
563 | }; | ||
564 | |||
565 | static const union decode_item arm_cccc_01xx_table[] = { | ||
566 | /* Load/store word and unsigned byte */ | ||
567 | |||
568 | /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */ | ||
569 | DECODE_REJECT (0x0c40f000, 0x0440f000), | ||
570 | |||
571 | /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */ | ||
572 | /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */ | ||
573 | /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */ | ||
574 | /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */ | ||
575 | DECODE_REJECT (0x0d200000, 0x04200000), | ||
576 | |||
577 | /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
578 | /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
579 | DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str, | ||
580 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
581 | |||
582 | /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
583 | /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
584 | DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr, | ||
585 | REGS(NOPCWB, ANY, 0, 0, 0)), | ||
586 | |||
587 | /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
588 | /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
589 | DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str, | ||
590 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
591 | |||
592 | /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
593 | /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ | ||
594 | DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr, | ||
595 | REGS(NOPCWB, ANY, 0, 0, NOPC)), | ||
596 | |||
597 | DECODE_END | ||
598 | }; | ||
599 | |||
600 | static const union decode_item arm_cccc_100x_table[] = { | ||
601 | /* Block data transfer instructions */ | ||
602 | |||
603 | /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | ||
604 | /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ | ||
605 | DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm), | ||
606 | |||
607 | /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ | ||
608 | /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */ | ||
609 | /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */ | ||
610 | DECODE_END | ||
611 | }; | ||
612 | |||
613 | const union decode_item kprobe_decode_arm_table[] = { | ||
614 | /* | ||
615 | * Unconditional instructions | ||
616 | * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx | ||
617 | */ | ||
618 | DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table), | ||
619 | |||
620 | /* | ||
621 | * Miscellaneous instructions | ||
622 | * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx | ||
623 | */ | ||
624 | DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table), | ||
625 | |||
626 | /* | ||
627 | * Halfword multiply and multiply-accumulate | ||
628 | * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx | ||
629 | */ | ||
630 | DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table), | ||
631 | |||
632 | /* | ||
633 | * Multiply and multiply-accumulate | ||
634 | * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx | ||
635 | */ | ||
636 | DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table), | ||
637 | |||
638 | /* | ||
639 | * Synchronization primitives | ||
640 | * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx | ||
641 | */ | ||
642 | DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table), | ||
643 | |||
644 | /* | ||
645 | * Extra load/store instructions | ||
646 | * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx | ||
647 | */ | ||
648 | DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table), | ||
649 | |||
650 | /* | ||
651 | * Data-processing (register) | ||
652 | * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx | ||
653 | * Data-processing (register-shifted register) | ||
654 | * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx | ||
655 | */ | ||
656 | DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table), | ||
657 | |||
658 | /* | ||
659 | * Data-processing (immediate) | ||
660 | * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx | ||
661 | */ | ||
662 | DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table), | ||
663 | |||
664 | /* | ||
665 | * Media instructions | ||
666 | * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx | ||
667 | */ | ||
668 | DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table), | ||
669 | DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table), | ||
670 | |||
671 | /* | ||
672 | * Load/store word and unsigned byte | ||
673 | * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx | ||
674 | */ | ||
675 | DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table), | ||
676 | |||
677 | /* | ||
678 | * Block data transfer instructions | ||
679 | * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx | ||
680 | */ | ||
681 | DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table), | ||
682 | |||
683 | /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
684 | /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
685 | DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl), | ||
686 | |||
687 | /* | ||
688 | * Supervisor Call, and coprocessor instructions | ||
689 | */ | ||
690 | |||
691 | /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */ | ||
692 | /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */ | ||
693 | /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ | ||
694 | /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ | ||
695 | /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ | ||
696 | /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ | ||
697 | /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ | ||
698 | /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ | ||
699 | DECODE_REJECT (0x0c000000, 0x0c000000), | ||
700 | |||
701 | DECODE_END | ||
702 | }; | ||
703 | #ifdef CONFIG_ARM_KPROBES_TEST_MODULE | ||
704 | EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); | ||
705 | #endif | ||
706 | |||
707 | static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) | ||
708 | { | ||
709 | regs->ARM_pc += 4; | ||
710 | p->ainsn.insn_handler(p, regs); | ||
711 | } | ||
712 | |||
713 | /* Return: | ||
714 | * INSN_REJECTED If instruction is one not allowed to kprobe, | ||
715 | * INSN_GOOD If instruction is supported and uses instruction slot, | ||
716 | * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. | ||
717 | * | ||
718 | * For instructions we don't want to kprobe (INSN_REJECTED return result): | ||
719 | * These are generally ones that modify the processor state making | ||
720 | * them "hard" to simulate such as switches processor modes or | ||
721 | * make accesses in alternate modes. Any of these could be simulated | ||
722 | * if the work was put into it, but low return considering they | ||
723 | * should also be very rare. | ||
724 | */ | ||
725 | enum kprobe_insn __kprobes | ||
726 | arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | ||
727 | { | ||
728 | asi->insn_singlestep = arm_singlestep; | ||
729 | asi->insn_check_cc = kprobe_condition_checks[insn>>28]; | ||
730 | return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false); | ||
731 | } | ||
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h new file mode 100644 index 000000000000..86084727d36d --- /dev/null +++ b/arch/arm/kernel/probes-arm.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes-arm.h | ||
3 | * | ||
4 | * Copyright 2013 Linaro Ltd. | ||
5 | * Written by: David A. Long | ||
6 | * | ||
7 | * The code contained herein is licensed under the GNU General Public | ||
8 | * License. You may obtain a copy of the GNU General Public License | ||
9 | * Version 2 or later at the following locations: | ||
10 | * | ||
11 | * http://www.opensource.org/licenses/gpl-license.html | ||
12 | * http://www.gnu.org/copyleft/gpl.html | ||
13 | */ | ||
14 | |||
15 | #ifndef _ARM_KERNEL_PROBES_ARM_H | ||
16 | #define _ARM_KERNEL_PROBES_ARM_H | ||
17 | |||
18 | void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs); | ||
19 | void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs); | ||
20 | void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs); | ||
21 | void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs); | ||
22 | void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs); | ||
23 | |||
24 | void __kprobes emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs); | ||
25 | void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs); | ||
26 | void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs); | ||
27 | void __kprobes emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, | ||
28 | struct pt_regs *regs); | ||
29 | void __kprobes emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, | ||
30 | struct pt_regs *regs); | ||
31 | void __kprobes emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, | ||
32 | struct pt_regs *regs); | ||
33 | void __kprobes emulate_rd12rm0_noflags_nopc(struct kprobe *p, | ||
34 | struct pt_regs *regs); | ||
35 | void __kprobes emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, | ||
36 | struct pt_regs *regs); | ||
37 | |||
38 | #endif | ||
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c new file mode 100644 index 000000000000..3a63f8f83cf8 --- /dev/null +++ b/arch/arm/kernel/probes.c | |||
@@ -0,0 +1,443 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | ||
5 | * | ||
6 | * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is | ||
7 | * Copyright (C) 2006, 2007 Motorola Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/kprobes.h> | ||
17 | #include <asm/system_info.h> | ||
18 | #include <asm/ptrace.h> | ||
19 | #include <linux/bug.h> | ||
20 | |||
21 | #include "kprobes.h" | ||
22 | |||
23 | |||
24 | #ifndef find_str_pc_offset | ||
25 | |||
26 | /* | ||
27 | * For STR and STM instructions, an ARM core may choose to use either | ||
28 | * a +8 or a +12 displacement from the current instruction's address. | ||
29 | * Whichever value is chosen for a given core, it must be the same for | ||
30 | * both instructions and may not change. This function measures it. | ||
31 | */ | ||
32 | |||
33 | int str_pc_offset; | ||
34 | |||
35 | void __init find_str_pc_offset(void) | ||
36 | { | ||
37 | int addr, scratch, ret; | ||
38 | |||
39 | __asm__ ( | ||
40 | "sub %[ret], pc, #4 \n\t" | ||
41 | "str pc, %[addr] \n\t" | ||
42 | "ldr %[scr], %[addr] \n\t" | ||
43 | "sub %[ret], %[scr], %[ret] \n\t" | ||
44 | : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr)); | ||
45 | |||
46 | str_pc_offset = ret; | ||
47 | } | ||
48 | |||
49 | #endif /* !find_str_pc_offset */ | ||
50 | |||
51 | |||
52 | #ifndef test_load_write_pc_interworking | ||
53 | |||
54 | bool load_write_pc_interworks; | ||
55 | |||
56 | void __init test_load_write_pc_interworking(void) | ||
57 | { | ||
58 | int arch = cpu_architecture(); | ||
59 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
60 | load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T; | ||
61 | } | ||
62 | |||
63 | #endif /* !test_load_write_pc_interworking */ | ||
64 | |||
65 | |||
66 | #ifndef test_alu_write_pc_interworking | ||
67 | |||
68 | bool alu_write_pc_interworks; | ||
69 | |||
70 | void __init test_alu_write_pc_interworking(void) | ||
71 | { | ||
72 | int arch = cpu_architecture(); | ||
73 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
74 | alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; | ||
75 | } | ||
76 | |||
77 | #endif /* !test_alu_write_pc_interworking */ | ||
78 | |||
79 | |||
80 | void __init arm_kprobe_decode_init(void) | ||
81 | { | ||
82 | find_str_pc_offset(); | ||
83 | test_load_write_pc_interworking(); | ||
84 | test_alu_write_pc_interworking(); | ||
85 | } | ||
86 | |||
87 | |||
88 | static unsigned long __kprobes __check_eq(unsigned long cpsr) | ||
89 | { | ||
90 | return cpsr & PSR_Z_BIT; | ||
91 | } | ||
92 | |||
93 | static unsigned long __kprobes __check_ne(unsigned long cpsr) | ||
94 | { | ||
95 | return (~cpsr) & PSR_Z_BIT; | ||
96 | } | ||
97 | |||
98 | static unsigned long __kprobes __check_cs(unsigned long cpsr) | ||
99 | { | ||
100 | return cpsr & PSR_C_BIT; | ||
101 | } | ||
102 | |||
103 | static unsigned long __kprobes __check_cc(unsigned long cpsr) | ||
104 | { | ||
105 | return (~cpsr) & PSR_C_BIT; | ||
106 | } | ||
107 | |||
108 | static unsigned long __kprobes __check_mi(unsigned long cpsr) | ||
109 | { | ||
110 | return cpsr & PSR_N_BIT; | ||
111 | } | ||
112 | |||
113 | static unsigned long __kprobes __check_pl(unsigned long cpsr) | ||
114 | { | ||
115 | return (~cpsr) & PSR_N_BIT; | ||
116 | } | ||
117 | |||
118 | static unsigned long __kprobes __check_vs(unsigned long cpsr) | ||
119 | { | ||
120 | return cpsr & PSR_V_BIT; | ||
121 | } | ||
122 | |||
123 | static unsigned long __kprobes __check_vc(unsigned long cpsr) | ||
124 | { | ||
125 | return (~cpsr) & PSR_V_BIT; | ||
126 | } | ||
127 | |||
128 | static unsigned long __kprobes __check_hi(unsigned long cpsr) | ||
129 | { | ||
130 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
131 | return cpsr & PSR_C_BIT; | ||
132 | } | ||
133 | |||
134 | static unsigned long __kprobes __check_ls(unsigned long cpsr) | ||
135 | { | ||
136 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
137 | return (~cpsr) & PSR_C_BIT; | ||
138 | } | ||
139 | |||
140 | static unsigned long __kprobes __check_ge(unsigned long cpsr) | ||
141 | { | ||
142 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
143 | return (~cpsr) & PSR_N_BIT; | ||
144 | } | ||
145 | |||
146 | static unsigned long __kprobes __check_lt(unsigned long cpsr) | ||
147 | { | ||
148 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
149 | return cpsr & PSR_N_BIT; | ||
150 | } | ||
151 | |||
152 | static unsigned long __kprobes __check_gt(unsigned long cpsr) | ||
153 | { | ||
154 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
155 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
156 | return (~temp) & PSR_N_BIT; | ||
157 | } | ||
158 | |||
159 | static unsigned long __kprobes __check_le(unsigned long cpsr) | ||
160 | { | ||
161 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
162 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
163 | return temp & PSR_N_BIT; | ||
164 | } | ||
165 | |||
166 | static unsigned long __kprobes __check_al(unsigned long cpsr) | ||
167 | { | ||
168 | return true; | ||
169 | } | ||
170 | |||
171 | kprobe_check_cc * const kprobe_condition_checks[16] = { | ||
172 | &__check_eq, &__check_ne, &__check_cs, &__check_cc, | ||
173 | &__check_mi, &__check_pl, &__check_vs, &__check_vc, | ||
174 | &__check_hi, &__check_ls, &__check_ge, &__check_lt, | ||
175 | &__check_gt, &__check_le, &__check_al, &__check_al | ||
176 | }; | ||
177 | |||
178 | |||
179 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs) | ||
180 | { | ||
181 | } | ||
182 | |||
183 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs) | ||
184 | { | ||
185 | p->ainsn.insn_fn(); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Prepare an instruction slot to receive an instruction for emulating. | ||
190 | * This is done by placing a subroutine return after the location where the | ||
191 | * instruction will be placed. We also modify ARM instructions to be | ||
192 | * unconditional as the condition code will already be checked before any | ||
193 | * emulation handler is called. | ||
194 | */ | ||
195 | static kprobe_opcode_t __kprobes | ||
196 | prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
197 | bool thumb) | ||
198 | { | ||
199 | #ifdef CONFIG_THUMB2_KERNEL | ||
200 | if (thumb) { | ||
201 | u16 *thumb_insn = (u16 *)asi->insn; | ||
202 | thumb_insn[1] = 0x4770; /* Thumb bx lr */ | ||
203 | thumb_insn[2] = 0x4770; /* Thumb bx lr */ | ||
204 | return insn; | ||
205 | } | ||
206 | asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ | ||
207 | #else | ||
208 | asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ | ||
209 | #endif | ||
210 | /* Make an ARM instruction unconditional */ | ||
211 | if (insn < 0xe0000000) | ||
212 | insn = (insn | 0xe0000000) & ~0x10000000; | ||
213 | return insn; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Write a (probably modified) instruction into the slot previously prepared by | ||
218 | * prepare_emulated_insn | ||
219 | */ | ||
220 | static void __kprobes | ||
221 | set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
222 | bool thumb) | ||
223 | { | ||
224 | #ifdef CONFIG_THUMB2_KERNEL | ||
225 | if (thumb) { | ||
226 | u16 *ip = (u16 *)asi->insn; | ||
227 | if (is_wide_instruction(insn)) | ||
228 | *ip++ = insn >> 16; | ||
229 | *ip++ = insn; | ||
230 | return; | ||
231 | } | ||
232 | #endif | ||
233 | asi->insn[0] = insn; | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * When we modify the register numbers encoded in an instruction to be emulated, | ||
238 | * the new values come from this define. For ARM and 32-bit Thumb instructions | ||
239 | * this gives... | ||
240 | * | ||
241 | * bit position 16 12 8 4 0 | ||
242 | * ---------------+---+---+---+---+---+ | ||
243 | * register r2 r0 r1 -- r3 | ||
244 | */ | ||
245 | #define INSN_NEW_BITS 0x00020103 | ||
246 | |||
247 | /* Each nibble has same value as that at INSN_NEW_BITS bit 16 */ | ||
248 | #define INSN_SAMEAS16_BITS 0x22222222 | ||
249 | |||
250 | /* | ||
251 | * Validate and modify each of the registers encoded in an instruction. | ||
252 | * | ||
253 | * Each nibble in regs contains a value from enum decode_reg_type. For each | ||
254 | * non-zero value, the corresponding nibble in pinsn is validated and modified | ||
255 | * according to the type. | ||
256 | */ | ||
257 | static bool __kprobes decode_regs(kprobe_opcode_t *pinsn, u32 regs) | ||
258 | { | ||
259 | kprobe_opcode_t insn = *pinsn; | ||
260 | kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */ | ||
261 | |||
262 | for (; regs != 0; regs >>= 4, mask <<= 4) { | ||
263 | |||
264 | kprobe_opcode_t new_bits = INSN_NEW_BITS; | ||
265 | |||
266 | switch (regs & 0xf) { | ||
267 | |||
268 | case REG_TYPE_NONE: | ||
269 | /* Nibble not a register, skip to next */ | ||
270 | continue; | ||
271 | |||
272 | case REG_TYPE_ANY: | ||
273 | /* Any register is allowed */ | ||
274 | break; | ||
275 | |||
276 | case REG_TYPE_SAMEAS16: | ||
277 | /* Replace register with same as at bit position 16 */ | ||
278 | new_bits = INSN_SAMEAS16_BITS; | ||
279 | break; | ||
280 | |||
281 | case REG_TYPE_SP: | ||
282 | /* Only allow SP (R13) */ | ||
283 | if ((insn ^ 0xdddddddd) & mask) | ||
284 | goto reject; | ||
285 | break; | ||
286 | |||
287 | case REG_TYPE_PC: | ||
288 | /* Only allow PC (R15) */ | ||
289 | if ((insn ^ 0xffffffff) & mask) | ||
290 | goto reject; | ||
291 | break; | ||
292 | |||
293 | case REG_TYPE_NOSP: | ||
294 | /* Reject SP (R13) */ | ||
295 | if (((insn ^ 0xdddddddd) & mask) == 0) | ||
296 | goto reject; | ||
297 | break; | ||
298 | |||
299 | case REG_TYPE_NOSPPC: | ||
300 | case REG_TYPE_NOSPPCX: | ||
301 | /* Reject SP and PC (R13 and R15) */ | ||
302 | if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0) | ||
303 | goto reject; | ||
304 | break; | ||
305 | |||
306 | case REG_TYPE_NOPCWB: | ||
307 | if (!is_writeback(insn)) | ||
308 | break; /* No writeback, so any register is OK */ | ||
309 | /* fall through... */ | ||
310 | case REG_TYPE_NOPC: | ||
311 | case REG_TYPE_NOPCX: | ||
312 | /* Reject PC (R15) */ | ||
313 | if (((insn ^ 0xffffffff) & mask) == 0) | ||
314 | goto reject; | ||
315 | break; | ||
316 | } | ||
317 | |||
318 | /* Replace value of nibble with new register number... */ | ||
319 | insn &= ~mask; | ||
320 | insn |= new_bits & mask; | ||
321 | } | ||
322 | |||
323 | *pinsn = insn; | ||
324 | return true; | ||
325 | |||
326 | reject: | ||
327 | return false; | ||
328 | } | ||
329 | |||
330 | static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | ||
331 | [DECODE_TYPE_TABLE] = sizeof(struct decode_table), | ||
332 | [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), | ||
333 | [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), | ||
334 | [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), | ||
335 | [DECODE_TYPE_OR] = sizeof(struct decode_or), | ||
336 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * kprobe_decode_insn operates on data tables in order to decode an ARM | ||
341 | * architecture instruction onto which a kprobe has been placed. | ||
342 | * | ||
343 | * These instruction decoding tables are a concatenation of entries each | ||
344 | * of which consist of one of the following structs: | ||
345 | * | ||
346 | * decode_table | ||
347 | * decode_custom | ||
348 | * decode_simulate | ||
349 | * decode_emulate | ||
350 | * decode_or | ||
351 | * decode_reject | ||
352 | * | ||
353 | * Each of these starts with a struct decode_header which has the following | ||
354 | * fields: | ||
355 | * | ||
356 | * type_regs | ||
357 | * mask | ||
358 | * value | ||
359 | * | ||
360 | * The least significant DECODE_TYPE_BITS of type_regs contains a value | ||
361 | * from enum decode_type, this indicates which of the decode_* structs | ||
362 | * the entry contains. The value DECODE_TYPE_END indicates the end of the | ||
363 | * table. | ||
364 | * | ||
365 | * When the table is parsed, each entry is checked in turn to see if it | ||
366 | * matches the instruction to be decoded using the test: | ||
367 | * | ||
368 | * (insn & mask) == value | ||
369 | * | ||
370 | * If no match is found before the end of the table is reached then decoding | ||
371 | * fails with INSN_REJECTED. | ||
372 | * | ||
373 | * When a match is found, decode_regs() is called to validate and modify each | ||
374 | * of the registers encoded in the instruction; the data it uses to do this | ||
375 | * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding | ||
376 | * to fail with INSN_REJECTED. | ||
377 | * | ||
378 | * Once the instruction has passed the above tests, further processing | ||
379 | * depends on the type of the table entry's decode struct. | ||
380 | * | ||
381 | */ | ||
382 | int __kprobes | ||
383 | kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
384 | const union decode_item *table, bool thumb) | ||
385 | { | ||
386 | const struct decode_header *h = (struct decode_header *)table; | ||
387 | const struct decode_header *next; | ||
388 | bool matched = false; | ||
389 | |||
390 | insn = prepare_emulated_insn(insn, asi, thumb); | ||
391 | |||
392 | for (;; h = next) { | ||
393 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; | ||
394 | u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; | ||
395 | |||
396 | if (type == DECODE_TYPE_END) | ||
397 | return INSN_REJECTED; | ||
398 | |||
399 | next = (struct decode_header *) | ||
400 | ((uintptr_t)h + decode_struct_sizes[type]); | ||
401 | |||
402 | if (!matched && (insn & h->mask.bits) != h->value.bits) | ||
403 | continue; | ||
404 | |||
405 | if (!decode_regs(&insn, regs)) | ||
406 | return INSN_REJECTED; | ||
407 | |||
408 | switch (type) { | ||
409 | |||
410 | case DECODE_TYPE_TABLE: { | ||
411 | struct decode_table *d = (struct decode_table *)h; | ||
412 | next = (struct decode_header *)d->table.table; | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | case DECODE_TYPE_CUSTOM: { | ||
417 | struct decode_custom *d = (struct decode_custom *)h; | ||
418 | return (*d->decoder.decoder)(insn, asi); | ||
419 | } | ||
420 | |||
421 | case DECODE_TYPE_SIMULATE: { | ||
422 | struct decode_simulate *d = (struct decode_simulate *)h; | ||
423 | asi->insn_handler = d->handler.handler; | ||
424 | return INSN_GOOD_NO_SLOT; | ||
425 | } | ||
426 | |||
427 | case DECODE_TYPE_EMULATE: { | ||
428 | struct decode_emulate *d = (struct decode_emulate *)h; | ||
429 | asi->insn_handler = d->handler.handler; | ||
430 | set_emulated_insn(insn, asi, thumb); | ||
431 | return INSN_GOOD; | ||
432 | } | ||
433 | |||
434 | case DECODE_TYPE_OR: | ||
435 | matched = true; | ||
436 | break; | ||
437 | |||
438 | case DECODE_TYPE_REJECT: | ||
439 | default: | ||
440 | return INSN_REJECTED; | ||
441 | } | ||
442 | } | ||
443 | } | ||
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h new file mode 100644 index 000000000000..17f656011aa3 --- /dev/null +++ b/arch/arm/kernel/probes.h | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/probes.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | ||
5 | * | ||
6 | * Some contents moved here from arch/arm/include/asm/kprobes.h which is | ||
7 | * Copyright (C) 2006, 2007 Motorola Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #ifndef _ARM_KERNEL_PROBES_H | ||
20 | #define _ARM_KERNEL_PROBES_H | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | #include <linux/stddef.h> | ||
24 | #include <linux/kprobes.h> | ||
25 | |||
26 | #if __LINUX_ARM_ARCH__ >= 7 | ||
27 | |||
28 | /* str_pc_offset is architecturally defined from ARMv7 onwards */ | ||
29 | #define str_pc_offset 8 | ||
30 | #define find_str_pc_offset() | ||
31 | |||
32 | #else /* __LINUX_ARM_ARCH__ < 7 */ | ||
33 | |||
34 | /* We need a run-time check to determine str_pc_offset */ | ||
35 | extern int str_pc_offset; | ||
36 | void __init find_str_pc_offset(void); | ||
37 | |||
38 | #endif | ||
39 | |||
40 | |||
41 | /* | ||
42 | * Update ITSTATE after normal execution of an IT block instruction. | ||
43 | * | ||
44 | * The 8 IT state bits are split into two parts in CPSR: | ||
45 | * ITSTATE<1:0> are in CPSR<26:25> | ||
46 | * ITSTATE<7:2> are in CPSR<15:10> | ||
47 | */ | ||
48 | static inline unsigned long it_advance(unsigned long cpsr) | ||
49 | { | ||
50 | if ((cpsr & 0x06000400) == 0) { | ||
51 | /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */ | ||
52 | cpsr &= ~PSR_IT_MASK; | ||
53 | } else { | ||
54 | /* We need to shift left ITSTATE<4:0> */ | ||
55 | const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */ | ||
56 | unsigned long it = cpsr & mask; | ||
57 | it <<= 1; | ||
58 | it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */ | ||
59 | it &= mask; | ||
60 | cpsr &= ~mask; | ||
61 | cpsr |= it; | ||
62 | } | ||
63 | return cpsr; | ||
64 | } | ||
65 | |||
66 | static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs) | ||
67 | { | ||
68 | long cpsr = regs->ARM_cpsr; | ||
69 | if (pcv & 0x1) { | ||
70 | cpsr |= PSR_T_BIT; | ||
71 | pcv &= ~0x1; | ||
72 | } else { | ||
73 | cpsr &= ~PSR_T_BIT; | ||
74 | pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */ | ||
75 | } | ||
76 | regs->ARM_cpsr = cpsr; | ||
77 | regs->ARM_pc = pcv; | ||
78 | } | ||
79 | |||
80 | |||
81 | #if __LINUX_ARM_ARCH__ >= 6 | ||
82 | |||
83 | /* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */ | ||
84 | #define load_write_pc_interworks true | ||
85 | #define test_load_write_pc_interworking() | ||
86 | |||
87 | #else /* __LINUX_ARM_ARCH__ < 6 */ | ||
88 | |||
89 | /* We need run-time testing to determine if load_write_pc() should interwork. */ | ||
90 | extern bool load_write_pc_interworks; | ||
91 | void __init test_load_write_pc_interworking(void); | ||
92 | |||
93 | #endif | ||
94 | |||
95 | static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs) | ||
96 | { | ||
97 | if (load_write_pc_interworks) | ||
98 | bx_write_pc(pcv, regs); | ||
99 | else | ||
100 | regs->ARM_pc = pcv; | ||
101 | } | ||
102 | |||
103 | |||
104 | #if __LINUX_ARM_ARCH__ >= 7 | ||
105 | |||
106 | #define alu_write_pc_interworks true | ||
107 | #define test_alu_write_pc_interworking() | ||
108 | |||
109 | #elif __LINUX_ARM_ARCH__ <= 5 | ||
110 | |||
111 | /* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */ | ||
112 | #define alu_write_pc_interworks false | ||
113 | #define test_alu_write_pc_interworking() | ||
114 | |||
115 | #else /* __LINUX_ARM_ARCH__ == 6 */ | ||
116 | |||
117 | /* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */ | ||
118 | extern bool alu_write_pc_interworks; | ||
119 | void __init test_alu_write_pc_interworking(void); | ||
120 | |||
121 | #endif /* __LINUX_ARM_ARCH__ == 6 */ | ||
122 | |||
123 | static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) | ||
124 | { | ||
125 | if (alu_write_pc_interworks) | ||
126 | bx_write_pc(pcv, regs); | ||
127 | else | ||
128 | regs->ARM_pc = pcv; | ||
129 | } | ||
130 | |||
131 | |||
132 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); | ||
133 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); | ||
134 | |||
135 | enum kprobe_insn __kprobes | ||
136 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); | ||
137 | |||
138 | /* | ||
139 | * Test if load/store instructions writeback the address register. | ||
140 | * if P (bit 24) == 0 or W (bit 21) == 1 | ||
141 | */ | ||
142 | #define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000) | ||
143 | |||
144 | /* | ||
145 | * The following definitions and macros are used to build instruction | ||
146 | * decoding tables for use by kprobe_decode_insn. | ||
147 | * | ||
148 | * These tables are a concatenation of entries each of which consist of one of | ||
149 | * the decode_* structs. All of the fields in every type of decode structure | ||
150 | * are of the union type decode_item, therefore the entire decode table can be | ||
151 | * viewed as an array of these and declared like: | ||
152 | * | ||
153 | * static const union decode_item table_name[] = {}; | ||
154 | * | ||
155 | * In order to construct each entry in the table, macros are used to | ||
156 | * initialise a number of sequential decode_item values in a layout which | ||
157 | * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct | ||
158 | * decode_simulate by initialising four decode_item objects like this... | ||
159 | * | ||
160 | * {.bits = _type}, | ||
161 | * {.bits = _mask}, | ||
162 | * {.bits = _value}, | ||
163 | * {.handler = _handler}, | ||
164 | * | ||
165 | * Initialising a specified member of the union means that the compiler | ||
166 | * will produce a warning if the argument is of an incorrect type. | ||
167 | * | ||
168 | * Below is a list of each of the macros used to initialise entries and a | ||
169 | * description of the action performed when that entry is matched to an | ||
170 | * instruction. A match is found when (instruction & mask) == value. | ||
171 | * | ||
172 | * DECODE_TABLE(mask, value, table) | ||
173 | * Instruction decoding jumps to parsing the new sub-table 'table'. | ||
174 | * | ||
175 | * DECODE_CUSTOM(mask, value, decoder) | ||
176 | * The custom function 'decoder' is called to the complete decoding | ||
177 | * of an instruction. | ||
178 | * | ||
179 | * DECODE_SIMULATE(mask, value, handler) | ||
180 | * Set the probes instruction handler to 'handler', this will be used | ||
181 | * to simulate the instruction when the probe is hit. Decoding returns | ||
182 | * with INSN_GOOD_NO_SLOT. | ||
183 | * | ||
184 | * DECODE_EMULATE(mask, value, handler) | ||
185 | * Set the probes instruction handler to 'handler', this will be used | ||
186 | * to emulate the instruction when the probe is hit. The modified | ||
187 | * instruction (see below) is placed in the probes instruction slot so it | ||
188 | * may be called by the emulation code. Decoding returns with INSN_GOOD. | ||
189 | * | ||
190 | * DECODE_REJECT(mask, value) | ||
191 | * Instruction decoding fails with INSN_REJECTED | ||
192 | * | ||
193 | * DECODE_OR(mask, value) | ||
194 | * This allows the mask/value test of multiple table entries to be | ||
195 | * logically ORed. Once an 'or' entry is matched the decoding action to | ||
196 | * be performed is that of the next entry which isn't an 'or'. E.g. | ||
197 | * | ||
198 | * DECODE_OR (mask1, value1) | ||
199 | * DECODE_OR (mask2, value2) | ||
200 | * DECODE_SIMULATE (mask3, value3, simulation_handler) | ||
201 | * | ||
202 | * This means that if any of the three mask/value pairs match the | ||
203 | * instruction being decoded, then 'simulation_handler' will be used | ||
204 | * for it. | ||
205 | * | ||
206 | * Both the SIMULATE and EMULATE macros have a second form which take an | ||
207 | * additional 'regs' argument. | ||
208 | * | ||
209 | * DECODE_SIMULATEX(mask, value, handler, regs) | ||
210 | * DECODE_EMULATEX (mask, value, handler, regs) | ||
211 | * | ||
212 | * These are used to specify what kind of CPU register is encoded in each of the | ||
213 | * least significant 5 nibbles of the instruction being decoded. The regs value | ||
214 | * is specified using the REGS macro, this takes any of the REG_TYPE_* values | ||
215 | * from enum decode_reg_type as arguments; only the '*' part of the name is | ||
216 | * given. E.g. | ||
217 | * | ||
218 | * REGS(0, ANY, NOPC, 0, ANY) | ||
219 | * | ||
220 | * This indicates an instruction is encoded like: | ||
221 | * | ||
222 | * bits 19..16 ignore | ||
223 | * bits 15..12 any register allowed here | ||
224 | * bits 11.. 8 any register except PC allowed here | ||
225 | * bits 7.. 4 ignore | ||
226 | * bits 3.. 0 any register allowed here | ||
227 | * | ||
228 | * This register specification is checked after a decode table entry is found to | ||
229 | * match an instruction (through the mask/value test). Any invalid register then | ||
230 | * found in the instruction will cause decoding to fail with INSN_REJECTED. In | ||
231 | * the above example this would happen if bits 11..8 of the instruction were | ||
232 | * 1111, indicating R15 or PC. | ||
233 | * | ||
234 | * As well as checking for legal combinations of registers, this data is also | ||
235 | * used to modify the registers encoded in the instructions so that an | ||
236 | * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.) | ||
237 | * | ||
238 | * Here is a real example which matches ARM instructions of the form | ||
239 | * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>" | ||
240 | * | ||
241 | * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, | ||
242 | * REGS(ANY, ANY, NOPC, 0, ANY)), | ||
243 | * ^ ^ ^ ^ | ||
244 | * Rn Rd Rs Rm | ||
245 | * | ||
246 | * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because | ||
247 | * Rs == R15 | ||
248 | * | ||
249 | * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the | ||
250 | * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into | ||
251 | * the kprobes instruction slot. This can then be called later by the handler | ||
252 | * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction. | ||
253 | */ | ||
254 | |||
255 | enum decode_type { | ||
256 | DECODE_TYPE_END, | ||
257 | DECODE_TYPE_TABLE, | ||
258 | DECODE_TYPE_CUSTOM, | ||
259 | DECODE_TYPE_SIMULATE, | ||
260 | DECODE_TYPE_EMULATE, | ||
261 | DECODE_TYPE_OR, | ||
262 | DECODE_TYPE_REJECT, | ||
263 | NUM_DECODE_TYPES /* Must be last enum */ | ||
264 | }; | ||
265 | |||
266 | #define DECODE_TYPE_BITS 4 | ||
267 | #define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1) | ||
268 | |||
269 | enum decode_reg_type { | ||
270 | REG_TYPE_NONE = 0, /* Not a register, ignore */ | ||
271 | REG_TYPE_ANY, /* Any register allowed */ | ||
272 | REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */ | ||
273 | REG_TYPE_SP, /* Register must be SP */ | ||
274 | REG_TYPE_PC, /* Register must be PC */ | ||
275 | REG_TYPE_NOSP, /* Register must not be SP */ | ||
276 | REG_TYPE_NOSPPC, /* Register must not be SP or PC */ | ||
277 | REG_TYPE_NOPC, /* Register must not be PC */ | ||
278 | REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */ | ||
279 | |||
280 | /* The following types are used when the encoding for PC indicates | ||
281 | * another instruction form. This distiction only matters for test | ||
282 | * case coverage checks. | ||
283 | */ | ||
284 | REG_TYPE_NOPCX, /* Register must not be PC */ | ||
285 | REG_TYPE_NOSPPCX, /* Register must not be SP or PC */ | ||
286 | |||
287 | /* Alias to allow '0' arg to be used in REGS macro. */ | ||
288 | REG_TYPE_0 = REG_TYPE_NONE | ||
289 | }; | ||
290 | |||
291 | #define REGS(r16, r12, r8, r4, r0) \ | ||
292 | (((REG_TYPE_##r16) << 16) + \ | ||
293 | ((REG_TYPE_##r12) << 12) + \ | ||
294 | ((REG_TYPE_##r8) << 8) + \ | ||
295 | ((REG_TYPE_##r4) << 4) + \ | ||
296 | (REG_TYPE_##r0)) | ||
297 | |||
298 | union decode_item { | ||
299 | u32 bits; | ||
300 | const union decode_item *table; | ||
301 | kprobe_insn_handler_t *handler; | ||
302 | kprobe_decode_insn_t *decoder; | ||
303 | }; | ||
304 | |||
305 | |||
306 | #define DECODE_END \ | ||
307 | {.bits = DECODE_TYPE_END} | ||
308 | |||
309 | |||
310 | struct decode_header { | ||
311 | union decode_item type_regs; | ||
312 | union decode_item mask; | ||
313 | union decode_item value; | ||
314 | }; | ||
315 | |||
316 | #define DECODE_HEADER(_type, _mask, _value, _regs) \ | ||
317 | {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \ | ||
318 | {.bits = (_mask)}, \ | ||
319 | {.bits = (_value)} | ||
320 | |||
321 | |||
322 | struct decode_table { | ||
323 | struct decode_header header; | ||
324 | union decode_item table; | ||
325 | }; | ||
326 | |||
327 | #define DECODE_TABLE(_mask, _value, _table) \ | ||
328 | DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \ | ||
329 | {.table = (_table)} | ||
330 | |||
331 | |||
332 | struct decode_custom { | ||
333 | struct decode_header header; | ||
334 | union decode_item decoder; | ||
335 | }; | ||
336 | |||
337 | #define DECODE_CUSTOM(_mask, _value, _decoder) \ | ||
338 | DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \ | ||
339 | {.decoder = (_decoder)} | ||
340 | |||
341 | |||
342 | struct decode_simulate { | ||
343 | struct decode_header header; | ||
344 | union decode_item handler; | ||
345 | }; | ||
346 | |||
347 | #define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \ | ||
348 | DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \ | ||
349 | {.handler = (_handler)} | ||
350 | |||
351 | #define DECODE_SIMULATE(_mask, _value, _handler) \ | ||
352 | DECODE_SIMULATEX(_mask, _value, _handler, 0) | ||
353 | |||
354 | |||
355 | struct decode_emulate { | ||
356 | struct decode_header header; | ||
357 | union decode_item handler; | ||
358 | }; | ||
359 | |||
360 | #define DECODE_EMULATEX(_mask, _value, _handler, _regs) \ | ||
361 | DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \ | ||
362 | {.handler = (_handler)} | ||
363 | |||
364 | #define DECODE_EMULATE(_mask, _value, _handler) \ | ||
365 | DECODE_EMULATEX(_mask, _value, _handler, 0) | ||
366 | |||
367 | |||
368 | struct decode_or { | ||
369 | struct decode_header header; | ||
370 | }; | ||
371 | |||
372 | #define DECODE_OR(_mask, _value) \ | ||
373 | DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0) | ||
374 | |||
375 | |||
376 | struct decode_reject { | ||
377 | struct decode_header header; | ||
378 | }; | ||
379 | |||
380 | #define DECODE_REJECT(_mask, _value) \ | ||
381 | DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) | ||
382 | |||
383 | |||
384 | #ifdef CONFIG_THUMB2_KERNEL | ||
385 | extern const union decode_item kprobe_decode_thumb16_table[]; | ||
386 | extern const union decode_item kprobe_decode_thumb32_table[]; | ||
387 | #else | ||
388 | extern const union decode_item kprobe_decode_arm_table[]; | ||
389 | #endif | ||
390 | |||
391 | extern kprobe_check_cc * const kprobe_condition_checks[16]; | ||
392 | |||
393 | |||
394 | int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, | ||
395 | const union decode_item *table, bool thumb16); | ||
396 | |||
397 | #endif | ||