aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-06-13 13:39:29 -0400
committerTixy <tixy@medhuaa1.miniserver.com>2011-07-13 13:32:51 -0400
commit8f2ffa00fb3c05ec0659cd7b056c4e8e106072f1 (patch)
tree859596b031ebfde5a44ade734a4c61ff22b1eb8b
parent0239269db6ba1ea908006fe309ade12991dd4e21 (diff)
ARM: kprobes: Remove now unused code
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
-rw-r--r--arch/arm/kernel/kprobes-arm.c738
1 files changed, 0 insertions, 738 deletions
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 8a58c99f658d..79203ee1d039 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -74,300 +74,6 @@
74 "mov pc, "reg" \n\t" 74 "mov pc, "reg" \n\t"
75#endif 75#endif
76 76
77#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
78
79#define PSR_fs (PSR_f|PSR_s)
80
81#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */
82
83typedef long (insn_0arg_fn_t)(void);
84typedef long (insn_1arg_fn_t)(long);
85typedef long (insn_2arg_fn_t)(long, long);
86typedef long (insn_3arg_fn_t)(long, long, long);
87typedef long (insn_4arg_fn_t)(long, long, long, long);
88typedef long long (insn_llret_0arg_fn_t)(void);
89typedef long long (insn_llret_3arg_fn_t)(long, long, long);
90typedef long long (insn_llret_4arg_fn_t)(long, long, long, long);
91
92union reg_pair {
93 long long dr;
94#ifdef __LITTLE_ENDIAN
95 struct { long r0, r1; };
96#else
97 struct { long r1, r0; };
98#endif
99};
100
101/*
102 * The insnslot_?arg_r[w]flags() functions below are to keep the
103 * msr -> *fn -> mrs instruction sequences indivisible so that
104 * the state of the CPSR flags aren't inadvertently modified
105 * just before or just after the call.
106 */
107
108static inline long __kprobes
109insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn)
110{
111 register long ret asm("r0");
112
113 __asm__ __volatile__ (
114 "msr cpsr_fs, %[cpsr] \n\t"
115 "mov lr, pc \n\t"
116 "mov pc, %[fn] \n\t"
117 : "=r" (ret)
118 : [cpsr] "r" (cpsr), [fn] "r" (fn)
119 : "lr", "cc"
120 );
121 return ret;
122}
123
124static inline long long __kprobes
125insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn)
126{
127 register long ret0 asm("r0");
128 register long ret1 asm("r1");
129 union reg_pair fnr;
130
131 __asm__ __volatile__ (
132 "msr cpsr_fs, %[cpsr] \n\t"
133 "mov lr, pc \n\t"
134 "mov pc, %[fn] \n\t"
135 : "=r" (ret0), "=r" (ret1)
136 : [cpsr] "r" (cpsr), [fn] "r" (fn)
137 : "lr", "cc"
138 );
139 fnr.r0 = ret0;
140 fnr.r1 = ret1;
141 return fnr.dr;
142}
143
144static inline long __kprobes
145insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn)
146{
147 register long rr0 asm("r0") = r0;
148 register long ret asm("r0");
149
150 __asm__ __volatile__ (
151 "msr cpsr_fs, %[cpsr] \n\t"
152 "mov lr, pc \n\t"
153 "mov pc, %[fn] \n\t"
154 : "=r" (ret)
155 : "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn)
156 : "lr", "cc"
157 );
158 return ret;
159}
160
161static inline long __kprobes
162insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn)
163{
164 register long rr0 asm("r0") = r0;
165 register long rr1 asm("r1") = r1;
166 register long ret asm("r0");
167
168 __asm__ __volatile__ (
169 "msr cpsr_fs, %[cpsr] \n\t"
170 "mov lr, pc \n\t"
171 "mov pc, %[fn] \n\t"
172 : "=r" (ret)
173 : "0" (rr0), "r" (rr1),
174 [cpsr] "r" (cpsr), [fn] "r" (fn)
175 : "lr", "cc"
176 );
177 return ret;
178}
179
180static inline long __kprobes
181insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn)
182{
183 register long rr0 asm("r0") = r0;
184 register long rr1 asm("r1") = r1;
185 register long rr2 asm("r2") = r2;
186 register long ret asm("r0");
187
188 __asm__ __volatile__ (
189 "msr cpsr_fs, %[cpsr] \n\t"
190 "mov lr, pc \n\t"
191 "mov pc, %[fn] \n\t"
192 : "=r" (ret)
193 : "0" (rr0), "r" (rr1), "r" (rr2),
194 [cpsr] "r" (cpsr), [fn] "r" (fn)
195 : "lr", "cc"
196 );
197 return ret;
198}
199
200static inline long long __kprobes
201insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr,
202 insn_llret_3arg_fn_t *fn)
203{
204 register long rr0 asm("r0") = r0;
205 register long rr1 asm("r1") = r1;
206 register long rr2 asm("r2") = r2;
207 register long ret0 asm("r0");
208 register long ret1 asm("r1");
209 union reg_pair fnr;
210
211 __asm__ __volatile__ (
212 "msr cpsr_fs, %[cpsr] \n\t"
213 "mov lr, pc \n\t"
214 "mov pc, %[fn] \n\t"
215 : "=r" (ret0), "=r" (ret1)
216 : "0" (rr0), "r" (rr1), "r" (rr2),
217 [cpsr] "r" (cpsr), [fn] "r" (fn)
218 : "lr", "cc"
219 );
220 fnr.r0 = ret0;
221 fnr.r1 = ret1;
222 return fnr.dr;
223}
224
225static inline long __kprobes
226insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr,
227 insn_4arg_fn_t *fn)
228{
229 register long rr0 asm("r0") = r0;
230 register long rr1 asm("r1") = r1;
231 register long rr2 asm("r2") = r2;
232 register long rr3 asm("r3") = r3;
233 register long ret asm("r0");
234
235 __asm__ __volatile__ (
236 "msr cpsr_fs, %[cpsr] \n\t"
237 "mov lr, pc \n\t"
238 "mov pc, %[fn] \n\t"
239 : "=r" (ret)
240 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
241 [cpsr] "r" (cpsr), [fn] "r" (fn)
242 : "lr", "cc"
243 );
244 return ret;
245}
246
247static inline long __kprobes
248insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn)
249{
250 register long rr0 asm("r0") = r0;
251 register long ret asm("r0");
252 long oldcpsr = *cpsr;
253 long newcpsr;
254
255 __asm__ __volatile__ (
256 "msr cpsr_fs, %[oldcpsr] \n\t"
257 "mov lr, pc \n\t"
258 "mov pc, %[fn] \n\t"
259 "mrs %[newcpsr], cpsr \n\t"
260 : "=r" (ret), [newcpsr] "=r" (newcpsr)
261 : "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
262 : "lr", "cc"
263 );
264 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
265 return ret;
266}
267
268static inline long __kprobes
269insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn)
270{
271 register long rr0 asm("r0") = r0;
272 register long rr1 asm("r1") = r1;
273 register long ret asm("r0");
274 long oldcpsr = *cpsr;
275 long newcpsr;
276
277 __asm__ __volatile__ (
278 "msr cpsr_fs, %[oldcpsr] \n\t"
279 "mov lr, pc \n\t"
280 "mov pc, %[fn] \n\t"
281 "mrs %[newcpsr], cpsr \n\t"
282 : "=r" (ret), [newcpsr] "=r" (newcpsr)
283 : "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
284 : "lr", "cc"
285 );
286 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
287 return ret;
288}
289
290static inline long __kprobes
291insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr,
292 insn_3arg_fn_t *fn)
293{
294 register long rr0 asm("r0") = r0;
295 register long rr1 asm("r1") = r1;
296 register long rr2 asm("r2") = r2;
297 register long ret asm("r0");
298 long oldcpsr = *cpsr;
299 long newcpsr;
300
301 __asm__ __volatile__ (
302 "msr cpsr_fs, %[oldcpsr] \n\t"
303 "mov lr, pc \n\t"
304 "mov pc, %[fn] \n\t"
305 "mrs %[newcpsr], cpsr \n\t"
306 : "=r" (ret), [newcpsr] "=r" (newcpsr)
307 : "0" (rr0), "r" (rr1), "r" (rr2),
308 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
309 : "lr", "cc"
310 );
311 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
312 return ret;
313}
314
315static inline long __kprobes
316insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
317 insn_4arg_fn_t *fn)
318{
319 register long rr0 asm("r0") = r0;
320 register long rr1 asm("r1") = r1;
321 register long rr2 asm("r2") = r2;
322 register long rr3 asm("r3") = r3;
323 register long ret asm("r0");
324 long oldcpsr = *cpsr;
325 long newcpsr;
326
327 __asm__ __volatile__ (
328 "msr cpsr_fs, %[oldcpsr] \n\t"
329 "mov lr, pc \n\t"
330 "mov pc, %[fn] \n\t"
331 "mrs %[newcpsr], cpsr \n\t"
332 : "=r" (ret), [newcpsr] "=r" (newcpsr)
333 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
334 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
335 : "lr", "cc"
336 );
337 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
338 return ret;
339}
340
341static inline long long __kprobes
342insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
343 insn_llret_4arg_fn_t *fn)
344{
345 register long rr0 asm("r0") = r0;
346 register long rr1 asm("r1") = r1;
347 register long rr2 asm("r2") = r2;
348 register long rr3 asm("r3") = r3;
349 register long ret0 asm("r0");
350 register long ret1 asm("r1");
351 long oldcpsr = *cpsr;
352 long newcpsr;
353 union reg_pair fnr;
354
355 __asm__ __volatile__ (
356 "msr cpsr_fs, %[oldcpsr] \n\t"
357 "mov lr, pc \n\t"
358 "mov pc, %[fn] \n\t"
359 "mrs %[newcpsr], cpsr \n\t"
360 : "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr)
361 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
362 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
363 : "lr", "cc"
364 );
365 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
366 fnr.r0 = ret0;
367 fnr.r1 = ret1;
368 return fnr.dr;
369}
370
371/* 77/*
372 * To avoid the complications of mimicing single-stepping on a 78 * To avoid the complications of mimicing single-stepping on a
373 * processor without a Next-PC or a single-step mode, and to 79 * processor without a Next-PC or a single-step mode, and to
@@ -449,450 +155,6 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
449 regs->uregs[12] = regs->uregs[13]; 155 regs->uregs[12] = regs->uregs[13];
450} 156}
451 157
452static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
453{
454 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
455 kprobe_opcode_t insn = p->opcode;
456 long ppc = (long)p->addr + 8;
457 int rd = (insn >> 12) & 0xf;
458 int rn = (insn >> 16) & 0xf;
459 int rm = insn & 0xf; /* rm may be invalid, don't care. */
460 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
461 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
462
463 /* Not following the C calling convention here, so need asm(). */
464 __asm__ __volatile__ (
465 "ldr r0, %[rn] \n\t"
466 "ldr r1, %[rm] \n\t"
467 "msr cpsr_fs, %[cpsr]\n\t"
468 "mov lr, pc \n\t"
469 "mov pc, %[i_fn] \n\t"
470 "str r0, %[rn] \n\t" /* in case of writeback */
471 "str r2, %[rd0] \n\t"
472 "str r3, %[rd1] \n\t"
473 : [rn] "+m" (rnv),
474 [rd0] "=m" (regs->uregs[rd]),
475 [rd1] "=m" (regs->uregs[rd+1])
476 : [rm] "m" (rmv),
477 [cpsr] "r" (regs->ARM_cpsr),
478 [i_fn] "r" (i_fn)
479 : "r0", "r1", "r2", "r3", "lr", "cc"
480 );
481 if (is_writeback(insn))
482 regs->uregs[rn] = rnv;
483}
484
485static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
486{
487 insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
488 kprobe_opcode_t insn = p->opcode;
489 long ppc = (long)p->addr + 8;
490 int rd = (insn >> 12) & 0xf;
491 int rn = (insn >> 16) & 0xf;
492 int rm = insn & 0xf;
493 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
494 /* rm/rmv may be invalid, don't care. */
495 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
496 long rnv_wb;
497
498 rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
499 regs->uregs[rd+1],
500 regs->ARM_cpsr, i_fn);
501 if (is_writeback(insn))
502 regs->uregs[rn] = rnv_wb;
503}
504
505static void __kprobes emulate_ldr_old(struct kprobe *p, struct pt_regs *regs)
506{
507 insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];
508 kprobe_opcode_t insn = p->opcode;
509 long ppc = (long)p->addr + 8;
510 union reg_pair fnr;
511 int rd = (insn >> 12) & 0xf;
512 int rn = (insn >> 16) & 0xf;
513 int rm = insn & 0xf;
514 long rdv;
515 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
516 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
517 long cpsr = regs->ARM_cpsr;
518
519 fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
520 if (rn != 15)
521 regs->uregs[rn] = fnr.r0; /* Save Rn in case of writeback. */
522 rdv = fnr.r1;
523
524 if (rd == 15) {
525#if __LINUX_ARM_ARCH__ >= 5
526 cpsr &= ~PSR_T_BIT;
527 if (rdv & 0x1)
528 cpsr |= PSR_T_BIT;
529 regs->ARM_cpsr = cpsr;
530 rdv &= ~0x1;
531#else
532 rdv &= ~0x2;
533#endif
534 }
535 regs->uregs[rd] = rdv;
536}
537
538static void __kprobes emulate_str_old(struct kprobe *p, struct pt_regs *regs)
539{
540 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
541 kprobe_opcode_t insn = p->opcode;
542 long iaddr = (long)p->addr;
543 int rd = (insn >> 12) & 0xf;
544 int rn = (insn >> 16) & 0xf;
545 int rm = insn & 0xf;
546 long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
547 long rnv = (rn == 15) ? iaddr + 8 : regs->uregs[rn];
548 long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */
549 long rnv_wb;
550
551 rnv_wb = insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
552 if (rn != 15)
553 regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */
554}
555
556static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
557{
558 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
559 kprobe_opcode_t insn = p->opcode;
560 int rd = (insn >> 12) & 0xf;
561 int rm = insn & 0xf;
562 long rmv = regs->uregs[rm];
563
564 /* Writes Q flag */
565 regs->uregs[rd] = insnslot_1arg_rwflags(rmv, &regs->ARM_cpsr, i_fn);
566}
567
568static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)
569{
570 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
571 kprobe_opcode_t insn = p->opcode;
572 int rd = (insn >> 12) & 0xf;
573 int rn = (insn >> 16) & 0xf;
574 int rm = insn & 0xf;
575 long rnv = regs->uregs[rn];
576 long rmv = regs->uregs[rm];
577
578 /* Reads GE bits */
579 regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);
580}
581
582static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
583{
584 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
585
586 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
587}
588
589static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)
590{
591}
592
593static void __kprobes
594emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)
595{
596 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
597 kprobe_opcode_t insn = p->opcode;
598 int rd = (insn >> 12) & 0xf;
599 long rdv = regs->uregs[rd];
600
601 regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);
602}
603
604static void __kprobes
605emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)
606{
607 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
608 kprobe_opcode_t insn = p->opcode;
609 int rd = (insn >> 12) & 0xf;
610 int rn = insn & 0xf;
611 long rdv = regs->uregs[rd];
612 long rnv = regs->uregs[rn];
613
614 regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);
615}
616
617static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
618{
619 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
620 kprobe_opcode_t insn = p->opcode;
621 int rd = (insn >> 12) & 0xf;
622 int rm = insn & 0xf;
623 long rmv = regs->uregs[rm];
624
625 regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);
626}
627
628static void __kprobes
629emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
630{
631 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
632 kprobe_opcode_t insn = p->opcode;
633 int rd = (insn >> 12) & 0xf;
634 int rn = (insn >> 16) & 0xf;
635 int rm = insn & 0xf;
636 long rnv = regs->uregs[rn];
637 long rmv = regs->uregs[rm];
638
639 regs->uregs[rd] =
640 insnslot_2arg_rwflags(rnv, rmv, &regs->ARM_cpsr, i_fn);
641}
642
643static void __kprobes
644emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
645{
646 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
647 kprobe_opcode_t insn = p->opcode;
648 int rd = (insn >> 16) & 0xf;
649 int rn = (insn >> 12) & 0xf;
650 int rs = (insn >> 8) & 0xf;
651 int rm = insn & 0xf;
652 long rnv = regs->uregs[rn];
653 long rsv = regs->uregs[rs];
654 long rmv = regs->uregs[rm];
655
656 regs->uregs[rd] =
657 insnslot_3arg_rwflags(rnv, rsv, rmv, &regs->ARM_cpsr, i_fn);
658}
659
660static void __kprobes
661emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
662{
663 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
664 kprobe_opcode_t insn = p->opcode;
665 int rd = (insn >> 16) & 0xf;
666 int rs = (insn >> 8) & 0xf;
667 int rm = insn & 0xf;
668 long rsv = regs->uregs[rs];
669 long rmv = regs->uregs[rm];
670
671 regs->uregs[rd] =
672 insnslot_2arg_rwflags(rsv, rmv, &regs->ARM_cpsr, i_fn);
673}
674
675static void __kprobes
676emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
677{
678 insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];
679 kprobe_opcode_t insn = p->opcode;
680 union reg_pair fnr;
681 int rdhi = (insn >> 16) & 0xf;
682 int rdlo = (insn >> 12) & 0xf;
683 int rs = (insn >> 8) & 0xf;
684 int rm = insn & 0xf;
685 long rsv = regs->uregs[rs];
686 long rmv = regs->uregs[rm];
687
688 fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],
689 regs->uregs[rdlo], rsv, rmv,
690 &regs->ARM_cpsr, i_fn);
691 regs->uregs[rdhi] = fnr.r0;
692 regs->uregs[rdlo] = fnr.r1;
693}
694
695static void __kprobes
696emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)
697{
698 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
699 kprobe_opcode_t insn = p->opcode;
700 int rd = (insn >> 12) & 0xf;
701 int rn = (insn >> 16) & 0xf;
702 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
703
704 regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
705}
706
707static void __kprobes
708emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
709{
710 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
711 kprobe_opcode_t insn = p->opcode;
712 int rd = (insn >> 12) & 0xf;
713 int rn = (insn >> 16) & 0xf;
714 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
715
716 regs->uregs[rd] = insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
717}
718
719static void __kprobes
720emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)
721{
722 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
723 kprobe_opcode_t insn = p->opcode;
724 int rn = (insn >> 16) & 0xf;
725 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
726
727 insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
728}
729
730static void __kprobes
731emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
732{
733 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
734 kprobe_opcode_t insn = p->opcode;
735 long ppc = (long)p->addr + 8;
736 int rd = (insn >> 12) & 0xf;
737 int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */
738 int rs = (insn >> 8) & 0xf; /* invalid, don't care. */
739 int rm = insn & 0xf;
740 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
741 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
742 long rsv = regs->uregs[rs];
743
744 regs->uregs[rd] =
745 insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);
746}
747
748static void __kprobes
749emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
750{
751 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
752 kprobe_opcode_t insn = p->opcode;
753 long ppc = (long)p->addr + 8;
754 int rd = (insn >> 12) & 0xf;
755 int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */
756 int rs = (insn >> 8) & 0xf; /* invalid, don't care. */
757 int rm = insn & 0xf;
758 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
759 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
760 long rsv = regs->uregs[rs];
761
762 regs->uregs[rd] =
763 insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
764}
765
766static void __kprobes
767emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)
768{
769 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
770 kprobe_opcode_t insn = p->opcode;
771 long ppc = (long)p->addr + 8;
772 int rn = (insn >> 16) & 0xf;
773 int rs = (insn >> 8) & 0xf; /* rs/rsv may be invalid, don't care. */
774 int rm = insn & 0xf;
775 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
776 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
777 long rsv = regs->uregs[rs];
778
779 insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
780}
781
782static enum kprobe_insn __kprobes
783prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
784{
785 int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))
786 : (~insn & (1 << 22));
787
788 if (is_writeback(insn) && is_r15(insn, 16))
789 return INSN_REJECTED; /* Writeback to PC */
790
791 insn &= 0xfff00fff;
792 insn |= 0x00001000; /* Rn = r0, Rd = r1 */
793 if (not_imm) {
794 insn &= ~0xf;
795 insn |= 2; /* Rm = r2 */
796 }
797 asi->insn[0] = insn;
798 asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr_old : emulate_str_old;
799 return INSN_GOOD;
800}
801
802static enum kprobe_insn __kprobes
803prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)
804{
805 if (is_r15(insn, 12))
806 return INSN_REJECTED; /* Rd is PC */
807
808 insn &= 0xffff0fff; /* Rd = r0 */
809 asi->insn[0] = insn;
810 asi->insn_handler = emulate_rd12_modify;
811 return INSN_GOOD;
812}
813
814static enum kprobe_insn __kprobes
815prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,
816 struct arch_specific_insn *asi)
817{
818 if (is_r15(insn, 12))
819 return INSN_REJECTED; /* Rd is PC */
820
821 insn &= 0xffff0ff0; /* Rd = r0 */
822 insn |= 0x00000001; /* Rn = r1 */
823 asi->insn[0] = insn;
824 asi->insn_handler = emulate_rd12rn0_modify;
825 return INSN_GOOD;
826}
827
828static enum kprobe_insn __kprobes
829prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
830{
831 if (is_r15(insn, 12))
832 return INSN_REJECTED; /* Rd is PC */
833
834 insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */
835 asi->insn[0] = insn;
836 asi->insn_handler = emulate_rd12rm0;
837 return INSN_GOOD;
838}
839
840static enum kprobe_insn __kprobes
841prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
842 struct arch_specific_insn *asi)
843{
844 if (is_r15(insn, 12))
845 return INSN_REJECTED; /* Rd is PC */
846
847 insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */
848 insn |= 0x00000001; /* Rm = r1 */
849 asi->insn[0] = insn;
850 asi->insn_handler = emulate_rd12rn16rm0_rwflags;
851 return INSN_GOOD;
852}
853
854static enum kprobe_insn __kprobes
855prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
856 struct arch_specific_insn *asi)
857{
858 if (is_r15(insn, 16))
859 return INSN_REJECTED; /* Rd is PC */
860
861 insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */
862 insn |= 0x00000001; /* Rm = r1 */
863 asi->insn[0] = insn;
864 asi->insn_handler = emulate_rd16rs8rm0_rwflags;
865 return INSN_GOOD;
866}
867
868static enum kprobe_insn __kprobes
869prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
870 struct arch_specific_insn *asi)
871{
872 if (is_r15(insn, 16))
873 return INSN_REJECTED; /* Rd is PC */
874
875 insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */
876 insn |= 0x00000102; /* Rs = r1, Rm = r2 */
877 asi->insn[0] = insn;
878 asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;
879 return INSN_GOOD;
880}
881
882static enum kprobe_insn __kprobes
883prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
884 struct arch_specific_insn *asi)
885{
886 if (is_r15(insn, 16) || is_r15(insn, 12))
887 return INSN_REJECTED; /* RdHi or RdLo is PC */
888
889 insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */
890 insn |= 0x00001203; /* Rs = r2, Rm = r3 */
891 asi->insn[0] = insn;
892 asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;
893 return INSN_GOOD;
894}
895
896static void __kprobes 158static void __kprobes
897emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) 159emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
898{ 160{