diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/kernel/kprobes-decode.c | 131 |
1 files changed, 23 insertions, 108 deletions
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c index 03b85ad525ab..15eeff6aea0e 100644 --- a/arch/arm/kernel/kprobes-decode.c +++ b/arch/arm/kernel/kprobes-decode.c | |||
@@ -34,9 +34,6 @@ | |||
34 | * | 34 | * |
35 | * *) If the PC is written to by the instruction, the | 35 | * *) If the PC is written to by the instruction, the |
36 | * instruction must be fully simulated in software. | 36 | * instruction must be fully simulated in software. |
37 | * If it is a conditional instruction, the handler | ||
38 | * will use insn[0] to copy its condition code to | ||
39 | * set r0 to 1 and insn[1] to "mov pc, lr" to return. | ||
40 | * | 37 | * |
41 | * *) Otherwise, a modified form of the instruction is | 38 | * *) Otherwise, a modified form of the instruction is |
42 | * directly executed. Its handler calls the | 39 | * directly executed. Its handler calls the |
@@ -1026,7 +1023,8 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1026 | 1023 | ||
1027 | /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | 1024 | /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ |
1028 | if ((insn & 0x0ff00090) == 0x01400080) | 1025 | if ((insn & 0x0ff00090) == 0x01400080) |
1029 | return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi); | 1026 | return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, |
1027 | asi); | ||
1030 | 1028 | ||
1031 | /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | 1029 | /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ |
1032 | /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | 1030 | /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ |
@@ -1097,15 +1095,15 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1097 | /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */ | 1095 | /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */ |
1098 | /* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */ | 1096 | /* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */ |
1099 | /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */ | 1097 | /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */ |
1100 | if ((insn & 0x00d00000) == 0x00500000) { | 1098 | if ((insn & 0x00d00000) == 0x00500000) |
1101 | return INSN_REJECTED; | 1099 | return INSN_REJECTED; |
1102 | } else if ((insn & 0x00e00000) == 0x00000000) { | 1100 | else if ((insn & 0x00e00000) == 0x00000000) |
1103 | return prep_emulate_rd16rs8rm0_wflags(insn, asi); | 1101 | return prep_emulate_rd16rs8rm0_wflags(insn, asi); |
1104 | } else if ((insn & 0x00a00000) == 0x00200000) { | 1102 | else if ((insn & 0x00a00000) == 0x00200000) |
1105 | return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); | 1103 | return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); |
1106 | } else { | 1104 | else |
1107 | return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi); | 1105 | return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, |
1108 | } | 1106 | asi); |
1109 | } | 1107 | } |
1110 | 1108 | ||
1111 | /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */ | 1109 | /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */ |
@@ -1171,7 +1169,7 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1171 | 1169 | ||
1172 | /* | 1170 | /* |
1173 | * ALU op with S bit and Rd == 15 : | 1171 | * ALU op with S bit and Rd == 15 : |
1174 | * cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx | 1172 | * cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx |
1175 | */ | 1173 | */ |
1176 | if ((insn & 0x0e10f000) == 0x0010f000) | 1174 | if ((insn & 0x0e10f000) == 0x0010f000) |
1177 | return INSN_REJECTED; | 1175 | return INSN_REJECTED; |
@@ -1401,11 +1399,10 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1401 | if ((insn & 0x00300000) == 0x00100000) | 1399 | if ((insn & 0x00300000) == 0x00100000) |
1402 | return INSN_REJECTED; /* Unallocated space */ | 1400 | return INSN_REJECTED; /* Unallocated space */ |
1403 | 1401 | ||
1404 | if ((insn & 0x000f0000) == 0x000f0000) { | 1402 | if ((insn & 0x000f0000) == 0x000f0000) |
1405 | return prep_emulate_rd12rm0(insn, asi); | 1403 | return prep_emulate_rd12rm0(insn, asi); |
1406 | } else { | 1404 | else |
1407 | return prep_emulate_rd12rn16rm0_wflags(insn, asi); | 1405 | return prep_emulate_rd12rn16rm0_wflags(insn, asi); |
1408 | } | ||
1409 | } | 1406 | } |
1410 | 1407 | ||
1411 | /* Other instruction encodings aren't yet defined */ | 1408 | /* Other instruction encodings aren't yet defined */ |
@@ -1436,11 +1433,10 @@ space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1436 | (insn & 0x0ff000d0) == 0x07500010 || | 1433 | (insn & 0x0ff000d0) == 0x07500010 || |
1437 | (insn & 0x0ff000f0) == 0x07800010) { | 1434 | (insn & 0x0ff000f0) == 0x07800010) { |
1438 | 1435 | ||
1439 | if ((insn & 0x0000f000) == 0x0000f000) { | 1436 | if ((insn & 0x0000f000) == 0x0000f000) |
1440 | return prep_emulate_rd16rs8rm0_wflags(insn, asi); | 1437 | return prep_emulate_rd16rs8rm0_wflags(insn, asi); |
1441 | } else { | 1438 | else |
1442 | return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); | 1439 | return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); |
1443 | } | ||
1444 | } | 1440 | } |
1445 | 1441 | ||
1446 | /* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */ | 1442 | /* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */ |
@@ -1633,40 +1629,38 @@ arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1633 | asi->insn_check_cc = condition_checks[insn>>28]; | 1629 | asi->insn_check_cc = condition_checks[insn>>28]; |
1634 | asi->insn[1] = KPROBE_RETURN_INSTRUCTION; | 1630 | asi->insn[1] = KPROBE_RETURN_INSTRUCTION; |
1635 | 1631 | ||
1636 | if ((insn & 0xf0000000) == 0xf0000000) { | 1632 | if ((insn & 0xf0000000) == 0xf0000000) |
1637 | 1633 | ||
1638 | return space_1111(insn, asi); | 1634 | return space_1111(insn, asi); |
1639 | 1635 | ||
1640 | } else if ((insn & 0x0e000000) == 0x00000000) { | 1636 | else if ((insn & 0x0e000000) == 0x00000000) |
1641 | 1637 | ||
1642 | return space_cccc_000x(insn, asi); | 1638 | return space_cccc_000x(insn, asi); |
1643 | 1639 | ||
1644 | } else if ((insn & 0x0e000000) == 0x02000000) { | 1640 | else if ((insn & 0x0e000000) == 0x02000000) |
1645 | 1641 | ||
1646 | return space_cccc_001x(insn, asi); | 1642 | return space_cccc_001x(insn, asi); |
1647 | 1643 | ||
1648 | } else if ((insn & 0x0f000010) == 0x06000010) { | 1644 | else if ((insn & 0x0f000010) == 0x06000010) |
1649 | 1645 | ||
1650 | return space_cccc_0110__1(insn, asi); | 1646 | return space_cccc_0110__1(insn, asi); |
1651 | 1647 | ||
1652 | } else if ((insn & 0x0f000010) == 0x07000010) { | 1648 | else if ((insn & 0x0f000010) == 0x07000010) |
1653 | 1649 | ||
1654 | return space_cccc_0111__1(insn, asi); | 1650 | return space_cccc_0111__1(insn, asi); |
1655 | 1651 | ||
1656 | } else if ((insn & 0x0c000000) == 0x04000000) { | 1652 | else if ((insn & 0x0c000000) == 0x04000000) |
1657 | 1653 | ||
1658 | return space_cccc_01xx(insn, asi); | 1654 | return space_cccc_01xx(insn, asi); |
1659 | 1655 | ||
1660 | } else if ((insn & 0x0e000000) == 0x08000000) { | 1656 | else if ((insn & 0x0e000000) == 0x08000000) |
1661 | 1657 | ||
1662 | return space_cccc_100x(insn, asi); | 1658 | return space_cccc_100x(insn, asi); |
1663 | 1659 | ||
1664 | } else if ((insn & 0x0e000000) == 0x0a000000) { | 1660 | else if ((insn & 0x0e000000) == 0x0a000000) |
1665 | 1661 | ||
1666 | return space_cccc_101x(insn, asi); | 1662 | return space_cccc_101x(insn, asi); |
1667 | 1663 | ||
1668 | } | ||
1669 | |||
1670 | return space_cccc_11xx(insn, asi); | 1664 | return space_cccc_11xx(insn, asi); |
1671 | } | 1665 | } |
1672 | 1666 | ||
@@ -1674,82 +1668,3 @@ void __init arm_kprobe_decode_init(void) | |||
1674 | { | 1668 | { |
1675 | find_str_pc_offset(); | 1669 | find_str_pc_offset(); |
1676 | } | 1670 | } |
1677 | |||
1678 | |||
1679 | /* | ||
1680 | * All ARM instructions listed below. | ||
1681 | * | ||
1682 | * Instructions and their general purpose registers are given. | ||
1683 | * If a particular register may not use R15, it is prefixed with a "!". | ||
1684 | * If marked with a "*" means the value returned by reading R15 | ||
1685 | * is implementation defined. | ||
1686 | * | ||
1687 | * ADC/ADD/AND/BIC/CMN/CMP/EOR/MOV/MVN/ORR/RSB/RSC/SBC/SUB/TEQ | ||
1688 | * TST: Rd, Rn, Rm, !Rs | ||
1689 | * BX: Rm | ||
1690 | * BLX(2): !Rm | ||
1691 | * BX: Rm (R15 legal, but discouraged) | ||
1692 | * BXJ: !Rm, | ||
1693 | * CLZ: !Rd, !Rm | ||
1694 | * CPY: Rd, Rm | ||
1695 | * LDC/2,STC/2 immediate offset & unindex: Rn | ||
1696 | * LDC/2,STC/2 immediate pre/post-indexed: !Rn | ||
1697 | * LDM(1/3): !Rn, register_list | ||
1698 | * LDM(2): !Rn, !register_list | ||
1699 | * LDR,STR,PLD immediate offset: Rd, Rn | ||
1700 | * LDR,STR,PLD register offset: Rd, Rn, !Rm | ||
1701 | * LDR,STR,PLD scaled register offset: Rd, !Rn, !Rm | ||
1702 | * LDR,STR immediate pre/post-indexed: Rd, !Rn | ||
1703 | * LDR,STR register pre/post-indexed: Rd, !Rn, !Rm | ||
1704 | * LDR,STR scaled register pre/post-indexed: Rd, !Rn, !Rm | ||
1705 | * LDRB,STRB immediate offset: !Rd, Rn | ||
1706 | * LDRB,STRB register offset: !Rd, Rn, !Rm | ||
1707 | * LDRB,STRB scaled register offset: !Rd, !Rn, !Rm | ||
1708 | * LDRB,STRB immediate pre/post-indexed: !Rd, !Rn | ||
1709 | * LDRB,STRB register pre/post-indexed: !Rd, !Rn, !Rm | ||
1710 | * LDRB,STRB scaled register pre/post-indexed: !Rd, !Rn, !Rm | ||
1711 | * LDRT,LDRBT,STRBT immediate pre/post-indexed: !Rd, !Rn | ||
1712 | * LDRT,LDRBT,STRBT register pre/post-indexed: !Rd, !Rn, !Rm | ||
1713 | * LDRT,LDRBT,STRBT scaled register pre/post-indexed: !Rd, !Rn, !Rm | ||
1714 | * LDRH/SH/SB/D,STRH/SH/SB/D immediate offset: !Rd, Rn | ||
1715 | * LDRH/SH/SB/D,STRH/SH/SB/D register offset: !Rd, Rn, !Rm | ||
1716 | * LDRH/SH/SB/D,STRH/SH/SB/D immediate pre/post-indexed: !Rd, !Rn | ||
1717 | * LDRH/SH/SB/D,STRH/SH/SB/D register pre/post-indexed: !Rd, !Rn, !Rm | ||
1718 | * LDREX: !Rd, !Rn | ||
1719 | * MCR/2: !Rd | ||
1720 | * MCRR/2,MRRC/2: !Rd, !Rn | ||
1721 | * MLA: !Rd, !Rn, !Rm, !Rs | ||
1722 | * MOV: Rd | ||
1723 | * MRC/2: !Rd (if Rd==15, only changes cond codes, not the register) | ||
1724 | * MRS,MSR: !Rd | ||
1725 | * MUL: !Rd, !Rm, !Rs | ||
1726 | * PKH{BT,TB}: !Rd, !Rn, !Rm | ||
1727 | * QDADD,[U]QADD/16/8/SUBX: !Rd, !Rm, !Rn | ||
1728 | * QDSUB,[U]QSUB/16/8/ADDX: !Rd, !Rm, !Rn | ||
1729 | * REV/16/SH: !Rd, !Rm | ||
1730 | * RFE: !Rn | ||
1731 | * {S,U}[H]ADD{16,8,SUBX},{S,U}[H]SUB{16,8,ADDX}: !Rd, !Rn, !Rm | ||
1732 | * SEL: !Rd, !Rn, !Rm | ||
1733 | * SMLA<x><y>,SMLA{D,W<y>},SMLSD,SMML{A,S}: !Rd, !Rn, !Rm, !Rs | ||
1734 | * SMLAL<x><y>,SMLA{D,LD},SMLSLD,SMMULL,SMULW<y>: !RdHi, !RdLo, !Rm, !Rs | ||
1735 | * SMMUL,SMUAD,SMUL<x><y>,SMUSD: !Rd, !Rm, !Rs | ||
1736 | * SSAT/16: !Rd, !Rm | ||
1737 | * STM(1/2): !Rn, register_list* (R15 in reg list not recommended) | ||
1738 | * STRT immediate pre/post-indexed: Rd*, !Rn | ||
1739 | * STRT register pre/post-indexed: Rd*, !Rn, !Rm | ||
1740 | * STRT scaled register pre/post-indexed: Rd*, !Rn, !Rm | ||
1741 | * STREX: !Rd, !Rn, !Rm | ||
1742 | * SWP/B: !Rd, !Rn, !Rm | ||
1743 | * {S,U}XTA{B,B16,H}: !Rd, !Rn, !Rm | ||
1744 | * {S,U}XT{B,B16,H}: !Rd, !Rm | ||
1745 | * UM{AA,LA,UL}L: !RdHi, !RdLo, !Rm, !Rs | ||
1746 | * USA{D8,A8,T,T16}: !Rd, !Rm, !Rs | ||
1747 | * | ||
1748 | * May transfer control by writing R15 (possible mode changes or alternate | ||
1749 | * mode accesses marked by "*"): | ||
1750 | * ALU op (* with s-bit), B, BL, BKPT, BLX(1/2), BX, BXJ, CPS*, CPY, | ||
1751 | * LDM(1), LDM(2/3)*, LDR, MOV, RFE*, SWI* | ||
1752 | * | ||
1753 | * Instructions that do not take general registers, nor transfer control: | ||
1754 | * CDP/2, SETEND, SRS* | ||
1755 | */ | ||