diff options
-rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 252 |
1 files changed, 116 insertions, 136 deletions
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index e590ff6603c2..ef350a5cd9b0 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
@@ -997,7 +997,99 @@ static const union decode_item arm_1111_table[] = { | |||
997 | DECODE_END | 997 | DECODE_END |
998 | }; | 998 | }; |
999 | 999 | ||
1000 | static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { | ||
1001 | /* Miscellaneous instructions */ | ||
1002 | |||
1003 | /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
1004 | DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs, | ||
1005 | REGS(0, NOPC, 0, 0, 0)), | ||
1006 | |||
1007 | /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
1008 | DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx), | ||
1009 | |||
1010 | /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
1011 | DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx, | ||
1012 | REGS(0, 0, 0, 0, NOPC)), | ||
1013 | |||
1014 | /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
1015 | DECODE_CUSTOM (0x0ff000f0, 0x01600010, prep_emulate_rd12rm0), | ||
1016 | |||
1017 | /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ | ||
1018 | /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ | ||
1019 | /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ | ||
1020 | /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ | ||
1021 | DECODE_CUSTOM (0x0f9000f0, 0x01000050, prep_emulate_rd12rn16rm0_wflags), | ||
1022 | |||
1023 | /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ | ||
1024 | /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ | ||
1025 | /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ | ||
1026 | /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ | ||
1027 | /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ | ||
1028 | /* And unallocated instructions... */ | ||
1029 | DECODE_END | ||
1030 | }; | ||
1031 | |||
1032 | static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { | ||
1033 | /* Halfword multiply and multiply-accumulate */ | ||
1034 | |||
1035 | /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | ||
1036 | DECODE_CUSTOM (0x0ff00090, 0x01400080, prep_emulate_rdhi16rdlo12rs8rm0_wflags), | ||
1037 | |||
1038 | /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | ||
1039 | DECODE_OR (0x0ff000b0, 0x012000a0), | ||
1040 | /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | ||
1041 | DECODE_CUSTOM (0x0ff00090, 0x01600080, prep_emulate_rd16rs8rm0_wflags), | ||
1042 | |||
1043 | /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ | ||
1044 | DECODE_OR (0x0ff00090, 0x01000080), | ||
1045 | /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ | ||
1046 | DECODE_CUSTOM (0x0ff000b0, 0x01200080, prep_emulate_rd16rn12rs8rm0_wflags), | ||
1047 | |||
1048 | DECODE_END | ||
1049 | }; | ||
1050 | |||
1051 | static const union decode_item arm_cccc_0000_____1001_table[] = { | ||
1052 | /* Multiply and multiply-accumulate */ | ||
1053 | |||
1054 | /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ | ||
1055 | /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ | ||
1056 | DECODE_CUSTOM (0x0fe000f0, 0x00000090, prep_emulate_rd16rs8rm0_wflags), | ||
1057 | |||
1058 | /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ | ||
1059 | /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ | ||
1060 | DECODE_OR (0x0fe000f0, 0x00200090), | ||
1061 | /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ | ||
1062 | DECODE_CUSTOM (0x0ff000f0, 0x00600090, prep_emulate_rd16rn12rs8rm0_wflags), | ||
1063 | |||
1064 | /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ | ||
1065 | DECODE_OR (0x0ff000f0, 0x00400090), | ||
1066 | /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */ | ||
1067 | /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */ | ||
1068 | /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */ | ||
1069 | /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */ | ||
1070 | /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */ | ||
1071 | /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ | ||
1072 | /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ | ||
1073 | /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ | ||
1074 | DECODE_CUSTOM (0x0f8000f0, 0x00800090, prep_emulate_rdhi16rdlo12rs8rm0_wflags), | ||
1075 | |||
1076 | DECODE_END | ||
1077 | }; | ||
1078 | |||
1079 | static const union decode_item arm_cccc_0001_____1001_table[] = { | ||
1080 | /* Synchronization primitives */ | ||
1081 | |||
1082 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ | ||
1083 | DECODE_CUSTOM (0x0fb000f0, 0x01000090, prep_emulate_rd12rn16rm0_wflags), | ||
1084 | |||
1085 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ | ||
1086 | /* And unallocated instructions... */ | ||
1087 | DECODE_END | ||
1088 | }; | ||
1089 | |||
1000 | static const union decode_item arm_cccc_000x_____1xx1_table[] = { | 1090 | static const union decode_item arm_cccc_000x_____1xx1_table[] = { |
1091 | /* Extra load/store instructions */ | ||
1092 | |||
1001 | /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ | 1093 | /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ |
1002 | DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), | 1094 | DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), |
1003 | 1095 | ||
@@ -1011,6 +1103,20 @@ static const union decode_item arm_cccc_000x_____1xx1_table[] = { | |||
1011 | DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, | 1103 | DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, |
1012 | REGS(NOPCWB, NOPCX, 0, 0, 0)), | 1104 | REGS(NOPCWB, NOPCX, 0, 0, 0)), |
1013 | 1105 | ||
1106 | /* Reject Rd is PC */ | ||
1107 | /* TODO: fold this into next entry when it is made a DECODE_EMULATE */ | ||
1108 | DECODE_REJECT (0x0000f000, 0x0000f000), | ||
1109 | |||
1110 | /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ | ||
1111 | /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ | ||
1112 | /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ | ||
1113 | /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ | ||
1114 | /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ | ||
1115 | /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ | ||
1116 | /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ | ||
1117 | /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ | ||
1118 | DECODE_CUSTOM (0x0e000090, 0x00000090, prep_emulate_ldr_str), | ||
1119 | |||
1014 | DECODE_END | 1120 | DECODE_END |
1015 | }; | 1121 | }; |
1016 | 1122 | ||
@@ -1079,146 +1185,20 @@ static const union decode_item arm_cccc_000x_table[] = { | |||
1079 | static enum kprobe_insn __kprobes | 1185 | static enum kprobe_insn __kprobes |
1080 | space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 1186 | space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) |
1081 | { | 1187 | { |
1082 | /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */ | 1188 | if ((insn & 0x0f900080) == 0x01000000) |
1083 | if ((insn & 0x0f900010) == 0x01000000) { | 1189 | return kprobe_decode_insn(insn, asi, arm_cccc_0001_0xx0____0xxx_table, false); |
1084 | |||
1085 | /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ | ||
1086 | if ((insn & 0x0ff000f0) == 0x01000000) { | ||
1087 | if (is_r15(insn, 12)) | ||
1088 | return INSN_REJECTED; /* Rd is PC */ | ||
1089 | asi->insn_handler = simulate_mrs; | ||
1090 | return INSN_GOOD_NO_SLOT; | ||
1091 | } | ||
1092 | |||
1093 | /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ | ||
1094 | if ((insn & 0x0ff00090) == 0x01400080) | ||
1095 | return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, | ||
1096 | asi); | ||
1097 | |||
1098 | /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ | ||
1099 | /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ | ||
1100 | if ((insn & 0x0ff000b0) == 0x012000a0 || | ||
1101 | (insn & 0x0ff00090) == 0x01600080) | ||
1102 | return prep_emulate_rd16rs8rm0_wflags(insn, asi); | ||
1103 | |||
1104 | /* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */ | ||
1105 | /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */ | ||
1106 | if ((insn & 0x0ff00090) == 0x01000080 || | ||
1107 | (insn & 0x0ff000b0) == 0x01200080) | ||
1108 | return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); | ||
1109 | |||
1110 | /* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ | ||
1111 | /* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ | ||
1112 | /* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ | ||
1113 | |||
1114 | /* Other instruction encodings aren't yet defined */ | ||
1115 | return INSN_REJECTED; | ||
1116 | } | ||
1117 | |||
1118 | /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */ | ||
1119 | else if ((insn & 0x0f900090) == 0x01000010) { | ||
1120 | |||
1121 | /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ | ||
1122 | /* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ | ||
1123 | if ((insn & 0x0ff000d0) == 0x01200010) { | ||
1124 | if ((insn & 0x0ff000ff) == 0x0120003f) | ||
1125 | return INSN_REJECTED; /* BLX pc */ | ||
1126 | asi->insn_handler = simulate_blx2bx; | ||
1127 | return INSN_GOOD_NO_SLOT; | ||
1128 | } | ||
1129 | |||
1130 | /* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ | ||
1131 | if ((insn & 0x0ff000f0) == 0x01600010) | ||
1132 | return prep_emulate_rd12rm0(insn, asi); | ||
1133 | 1190 | ||
1134 | /* QADD : cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx :Q */ | 1191 | if ((insn & 0x0f900090) == 0x01000080) |
1135 | /* QSUB : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */ | 1192 | return kprobe_decode_insn(insn, asi, arm_cccc_0001_0xx0____1xx0_table, false); |
1136 | /* QDADD : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */ | ||
1137 | /* QDSUB : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */ | ||
1138 | if ((insn & 0x0f9000f0) == 0x01000050) | ||
1139 | return prep_emulate_rd12rn16rm0_wflags(insn, asi); | ||
1140 | 1193 | ||
1141 | /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ | 1194 | if ((insn & 0x0f0000f0) == 0x00000090) |
1142 | /* SMC : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ | 1195 | return kprobe_decode_insn(insn, asi, arm_cccc_0000_____1001_table, false); |
1143 | 1196 | ||
1144 | /* Other instruction encodings aren't yet defined */ | 1197 | if ((insn & 0x0f0000f0) == 0x01000090) |
1145 | return INSN_REJECTED; | 1198 | return kprobe_decode_insn(insn, asi, arm_cccc_0001_____1001_table, false); |
1146 | } | ||
1147 | 1199 | ||
1148 | /* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */ | 1200 | if ((insn & 0x0e000090) == 0x00000090) |
1149 | else if ((insn & 0x0f0000f0) == 0x00000090) { | 1201 | return kprobe_decode_insn(insn, asi, arm_cccc_000x_____1xx1_table, false); |
1150 | |||
1151 | /* MUL : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx : */ | ||
1152 | /* MULS : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */ | ||
1153 | /* MLA : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx : */ | ||
1154 | /* MLAS : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */ | ||
1155 | /* UMAAL : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx : */ | ||
1156 | /* undef : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx : */ | ||
1157 | /* MLS : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx : */ | ||
1158 | /* undef : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx : */ | ||
1159 | /* UMULL : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx : */ | ||
1160 | /* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */ | ||
1161 | /* UMLAL : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx : */ | ||
1162 | /* UMLALS : cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx :cc */ | ||
1163 | /* SMULL : cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx : */ | ||
1164 | /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */ | ||
1165 | /* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */ | ||
1166 | /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */ | ||
1167 | if ((insn & 0x00d00000) == 0x00500000) | ||
1168 | return INSN_REJECTED; | ||
1169 | else if ((insn & 0x00e00000) == 0x00000000) | ||
1170 | return prep_emulate_rd16rs8rm0_wflags(insn, asi); | ||
1171 | else if ((insn & 0x00a00000) == 0x00200000) | ||
1172 | return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); | ||
1173 | else | ||
1174 | return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, | ||
1175 | asi); | ||
1176 | } | ||
1177 | |||
1178 | /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */ | ||
1179 | else if ((insn & 0x0e000090) == 0x00000090) { | ||
1180 | |||
1181 | /* SWP : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */ | ||
1182 | /* SWPB : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */ | ||
1183 | /* ??? : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */ | ||
1184 | /* ??? : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */ | ||
1185 | /* ??? : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */ | ||
1186 | /* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */ | ||
1187 | /* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */ | ||
1188 | /* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */ | ||
1189 | /* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */ | ||
1190 | /* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */ | ||
1191 | /* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */ | ||
1192 | /* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */ | ||
1193 | /* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */ | ||
1194 | |||
1195 | /* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */ | ||
1196 | /* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */ | ||
1197 | /* LDRH : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */ | ||
1198 | /* STRH : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */ | ||
1199 | /* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */ | ||
1200 | /* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */ | ||
1201 | if ((insn & 0x0f0000f0) == 0x01000090) { | ||
1202 | if ((insn & 0x0fb000f0) == 0x01000090) { | ||
1203 | /* SWP/SWPB */ | ||
1204 | return prep_emulate_rd12rn16rm0_wflags(insn, | ||
1205 | asi); | ||
1206 | } else { | ||
1207 | /* STREX/LDREX variants and unallocaed space */ | ||
1208 | return INSN_REJECTED; | ||
1209 | } | ||
1210 | |||
1211 | } else if ((insn & 0x0e1000d0) == 0x00000d0) { | ||
1212 | |||
1213 | return kprobe_decode_insn(insn, asi, arm_cccc_000x_____1xx1_table, | ||
1214 | false); | ||
1215 | } | ||
1216 | |||
1217 | /* LDRH/STRH/LDRSB/LDRSH */ | ||
1218 | if (is_r15(insn, 12)) | ||
1219 | return INSN_REJECTED; /* Rd is PC */ | ||
1220 | return prep_emulate_ldr_str(insn, asi); | ||
1221 | } | ||
1222 | 1202 | ||
1223 | return kprobe_decode_insn(insn, asi, arm_cccc_000x_table, false); | 1203 | return kprobe_decode_insn(insn, asi, arm_cccc_000x_table, false); |
1224 | } | 1204 | } |