diff options
author | Jon Medhurst <tixy@yxit.co.uk> | 2011-06-13 13:39:29 -0400 |
---|---|---|
committer | Tixy <tixy@medhuaa1.miniserver.com> | 2011-07-13 13:32:51 -0400 |
commit | 8f2ffa00fb3c05ec0659cd7b056c4e8e106072f1 (patch) | |
tree | 859596b031ebfde5a44ade734a4c61ff22b1eb8b /arch | |
parent | 0239269db6ba1ea908006fe309ade12991dd4e21 (diff) |
ARM: kprobes: Remove now unused code
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 738 |
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 | |||
83 | typedef long (insn_0arg_fn_t)(void); | ||
84 | typedef long (insn_1arg_fn_t)(long); | ||
85 | typedef long (insn_2arg_fn_t)(long, long); | ||
86 | typedef long (insn_3arg_fn_t)(long, long, long); | ||
87 | typedef long (insn_4arg_fn_t)(long, long, long, long); | ||
88 | typedef long long (insn_llret_0arg_fn_t)(void); | ||
89 | typedef long long (insn_llret_3arg_fn_t)(long, long, long); | ||
90 | typedef long long (insn_llret_4arg_fn_t)(long, long, long, long); | ||
91 | |||
92 | union 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 | |||
108 | static inline long __kprobes | ||
109 | insnslot_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 | |||
124 | static inline long long __kprobes | ||
125 | insnslot_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 | |||
144 | static inline long __kprobes | ||
145 | insnslot_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 | |||
161 | static inline long __kprobes | ||
162 | insnslot_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 | |||
180 | static inline long __kprobes | ||
181 | insnslot_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 | |||
200 | static inline long long __kprobes | ||
201 | insnslot_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 | |||
225 | static inline long __kprobes | ||
226 | insnslot_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 | |||
247 | static inline long __kprobes | ||
248 | insnslot_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 | |||
268 | static inline long __kprobes | ||
269 | insnslot_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 | |||
290 | static inline long __kprobes | ||
291 | insnslot_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 | |||
315 | static inline long __kprobes | ||
316 | insnslot_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 | |||
341 | static inline long long __kprobes | ||
342 | insnslot_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 | ||
452 | static 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 | |||
485 | static 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 | |||
505 | static 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 | |||
538 | static 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 | |||
556 | static 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, ®s->ARM_cpsr, i_fn); | ||
566 | } | ||
567 | |||
568 | static 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 | |||
582 | static 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 | |||
589 | static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs) | ||
590 | { | ||
591 | } | ||
592 | |||
593 | static void __kprobes | ||
594 | emulate_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 | |||
604 | static void __kprobes | ||
605 | emulate_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 | |||
617 | static 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 | |||
628 | static void __kprobes | ||
629 | emulate_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, ®s->ARM_cpsr, i_fn); | ||
641 | } | ||
642 | |||
643 | static void __kprobes | ||
644 | emulate_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, ®s->ARM_cpsr, i_fn); | ||
658 | } | ||
659 | |||
660 | static void __kprobes | ||
661 | emulate_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, ®s->ARM_cpsr, i_fn); | ||
673 | } | ||
674 | |||
675 | static void __kprobes | ||
676 | emulate_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 | ®s->ARM_cpsr, i_fn); | ||
691 | regs->uregs[rdhi] = fnr.r0; | ||
692 | regs->uregs[rdlo] = fnr.r1; | ||
693 | } | ||
694 | |||
695 | static void __kprobes | ||
696 | emulate_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 | |||
707 | static void __kprobes | ||
708 | emulate_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, ®s->ARM_cpsr, i_fn); | ||
717 | } | ||
718 | |||
719 | static void __kprobes | ||
720 | emulate_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, ®s->ARM_cpsr, i_fn); | ||
728 | } | ||
729 | |||
730 | static void __kprobes | ||
731 | emulate_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 | |||
748 | static void __kprobes | ||
749 | emulate_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, ®s->ARM_cpsr, i_fn); | ||
764 | } | ||
765 | |||
766 | static void __kprobes | ||
767 | emulate_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, ®s->ARM_cpsr, i_fn); | ||
780 | } | ||
781 | |||
782 | static enum kprobe_insn __kprobes | ||
783 | prep_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 | |||
802 | static enum kprobe_insn __kprobes | ||
803 | prep_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 | |||
814 | static enum kprobe_insn __kprobes | ||
815 | prep_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 | |||
828 | static enum kprobe_insn __kprobes | ||
829 | prep_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 | |||
840 | static enum kprobe_insn __kprobes | ||
841 | prep_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 | |||
854 | static enum kprobe_insn __kprobes | ||
855 | prep_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 | |||
868 | static enum kprobe_insn __kprobes | ||
869 | prep_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 | |||
882 | static enum kprobe_insn __kprobes | ||
883 | prep_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 | |||
896 | static void __kprobes | 158 | static void __kprobes |
897 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) | 159 | emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) |
898 | { | 160 | { |