diff options
Diffstat (limited to 'arch/arm/kernel/kprobes-arm.c')
-rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 58 |
1 files changed, 7 insertions, 51 deletions
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index a1143e86a09a..c6f2c693b1b6 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
@@ -437,54 +437,6 @@ static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) | |||
437 | regs->uregs[rd] = regs->ARM_cpsr & mask; | 437 | regs->uregs[rd] = regs->ARM_cpsr & mask; |
438 | } | 438 | } |
439 | 439 | ||
440 | static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) | ||
441 | { | ||
442 | kprobe_opcode_t insn = p->opcode; | ||
443 | int rn = (insn >> 16) & 0xf; | ||
444 | int lbit = insn & (1 << 20); | ||
445 | int wbit = insn & (1 << 21); | ||
446 | int ubit = insn & (1 << 23); | ||
447 | int pbit = insn & (1 << 24); | ||
448 | long *addr = (long *)regs->uregs[rn]; | ||
449 | int reg_bit_vector; | ||
450 | int reg_count; | ||
451 | |||
452 | reg_count = 0; | ||
453 | reg_bit_vector = insn & 0xffff; | ||
454 | while (reg_bit_vector) { | ||
455 | reg_bit_vector &= (reg_bit_vector - 1); | ||
456 | ++reg_count; | ||
457 | } | ||
458 | |||
459 | if (!ubit) | ||
460 | addr -= reg_count; | ||
461 | addr += (!pbit == !ubit); | ||
462 | |||
463 | reg_bit_vector = insn & 0xffff; | ||
464 | while (reg_bit_vector) { | ||
465 | int reg = __ffs(reg_bit_vector); | ||
466 | reg_bit_vector &= (reg_bit_vector - 1); | ||
467 | if (lbit) | ||
468 | regs->uregs[reg] = *addr++; | ||
469 | else | ||
470 | *addr++ = regs->uregs[reg]; | ||
471 | } | ||
472 | |||
473 | if (wbit) { | ||
474 | if (!ubit) | ||
475 | addr -= reg_count; | ||
476 | addr -= (!pbit == !ubit); | ||
477 | regs->uregs[rn] = (long)addr; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs) | ||
482 | { | ||
483 | regs->ARM_pc = (long)p->addr + str_pc_offset; | ||
484 | simulate_ldm1stm1(p, regs); | ||
485 | regs->ARM_pc = (long)p->addr + 4; | ||
486 | } | ||
487 | |||
488 | static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) | 440 | static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) |
489 | { | 441 | { |
490 | regs->uregs[12] = regs->uregs[13]; | 442 | regs->uregs[12] = regs->uregs[13]; |
@@ -1463,9 +1415,13 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1463 | 1415 | ||
1464 | /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ | 1416 | /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ |
1465 | /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ | 1417 | /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ |
1466 | asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */ | 1418 | |
1467 | simulate_stm1_pc : simulate_ldm1stm1; | 1419 | /* |
1468 | return INSN_GOOD_NO_SLOT; | 1420 | * Make the instruction unconditional because the new emulation |
1421 | * functions don't bother to setup the PSR context. | ||
1422 | */ | ||
1423 | insn = (insn | 0xe0000000) & ~0x10000000; | ||
1424 | return kprobe_decode_ldmstm(insn, asi); | ||
1469 | } | 1425 | } |
1470 | 1426 | ||
1471 | static enum kprobe_insn __kprobes | 1427 | static enum kprobe_insn __kprobes |