aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/kprobes-decode.c113
1 files changed, 11 insertions, 102 deletions
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
index 8391dac41855..ff3970741653 100644
--- a/arch/arm/kernel/kprobes-decode.c
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -520,17 +520,6 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
520 regs->uregs[12] = regs->uregs[13]; 520 regs->uregs[12] = regs->uregs[13];
521} 521}
522 522
523static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs)
524{
525 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
526 kprobe_opcode_t insn = p->opcode;
527 int rn = (insn >> 16) & 0xf;
528 long rnv = regs->uregs[rn];
529
530 /* Save Rn in case of writeback. */
531 regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
532}
533
534static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs) 523static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
535{ 524{
536 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; 525 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
@@ -635,31 +624,6 @@ static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
635 regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */ 624 regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */
636} 625}
637 626
638static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
639{
640 insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
641 kprobe_opcode_t insn = p->opcode;
642 union reg_pair fnr;
643 int rd = (insn >> 12) & 0xf;
644 int rn = (insn >> 16) & 0xf;
645
646 fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
647 regs->uregs[rn] = fnr.r0;
648 regs->uregs[rd] = fnr.r1;
649}
650
651static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
652{
653 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
654 kprobe_opcode_t insn = p->opcode;
655 int rd = (insn >> 12) & 0xf;
656 int rn = (insn >> 16) & 0xf;
657 long rnv = regs->uregs[rn];
658 long rdv = regs->uregs[rd];
659
660 insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
661}
662
663static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs) 627static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
664{ 628{
665 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; 629 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
@@ -693,24 +657,6 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
693 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn); 657 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
694} 658}
695 659
696static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
697{
698 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
699 kprobe_opcode_t insn = p->opcode;
700 int rd = (insn >> 12) & 0xf;
701
702 regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
703}
704
705static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
706{
707 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
708 kprobe_opcode_t insn = p->opcode;
709 int ird = (insn >> 12) & 0xf;
710
711 insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
712}
713
714static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs) 660static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
715{ 661{
716 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; 662 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
@@ -1010,40 +956,22 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1010 } 956 }
1011 957
1012 /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ 958 /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
1013 /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ 959 if ((insn & 0xffff00f0) == 0xf1010000) {
1014 if ((insn & 0xffff00f0) == 0xf1010000 ||
1015 (insn & 0xff000010) == 0xfe000000) {
1016 asi->insn[0] = insn; 960 asi->insn[0] = insn;
1017 asi->insn_handler = emulate_none; 961 asi->insn_handler = emulate_none;
1018 return INSN_GOOD; 962 return INSN_GOOD;
1019 } 963 }
1020 964
965 /* Coprocessor instructions... */
1021 /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */ 966 /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
1022 /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */ 967 /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
1023 if ((insn & 0xffe00000) == 0xfc400000) { 968 /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
1024 insn &= 0xfff00fff; /* Rn = r0 */ 969 /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1025 insn |= 0x00001000; /* Rd = r1 */ 970 /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
1026 asi->insn[0] = insn; 971 /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1027 asi->insn_handler = 972 /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1028 (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
1029 return INSN_GOOD;
1030 }
1031 973
1032 /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ 974 return INSN_REJECTED;
1033 /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1034 if ((insn & 0xfe000000) == 0xfc000000) {
1035 insn &= 0xfff0ffff; /* Rn = r0 */
1036 asi->insn[0] = insn;
1037 asi->insn_handler = emulate_ldcstc;
1038 return INSN_GOOD;
1039 }
1040
1041 /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1042 /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1043 insn &= 0xffff0fff; /* Rd = r0 */
1044 asi->insn[0] = insn;
1045 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1046 return INSN_GOOD;
1047} 975}
1048 976
1049static enum kprobe_insn __kprobes 977static enum kprobe_insn __kprobes
@@ -1504,14 +1432,7 @@ space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1504{ 1432{
1505 /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ 1433 /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1506 /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ 1434 /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1507 if (is_r15(insn, 16) || is_r15(insn, 12)) 1435 return INSN_REJECTED;
1508 return INSN_REJECTED; /* Rn or Rd is PC */
1509
1510 insn &= 0xfff00fff;
1511 insn |= 0x00001000; /* Rn = r0, Rd = r1 */
1512 asi->insn[0] = insn;
1513 asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
1514 return INSN_GOOD;
1515} 1436}
1516 1437
1517static enum kprobe_insn __kprobes 1438static enum kprobe_insn __kprobes
@@ -1519,10 +1440,7 @@ space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1519{ 1440{
1520 /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ 1441 /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
1521 /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ 1442 /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1522 insn &= 0xfff0ffff; /* Rn = r0 */ 1443 return INSN_REJECTED;
1523 asi->insn[0] = insn;
1524 asi->insn_handler = emulate_ldcstc;
1525 return INSN_GOOD;
1526} 1444}
1527 1445
1528static enum kprobe_insn __kprobes 1446static enum kprobe_insn __kprobes
@@ -1535,18 +1453,9 @@ space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1535 return INSN_REJECTED; 1453 return INSN_REJECTED;
1536 1454
1537 /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ 1455 /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
1538 if ((insn & 0x0f000010) == 0x0e000000) {
1539 asi->insn[0] = insn;
1540 asi->insn_handler = emulate_none;
1541 return INSN_GOOD;
1542 }
1543
1544 /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ 1456 /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1545 /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ 1457 /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1546 insn &= 0xffff0fff; /* Rd = r0 */ 1458 return INSN_REJECTED;
1547 asi->insn[0] = insn;
1548 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1549 return INSN_GOOD;
1550} 1459}
1551 1460
1552static unsigned long __kprobes __check_eq(unsigned long cpsr) 1461static unsigned long __kprobes __check_eq(unsigned long cpsr)