aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kernel/kprobes-arm.c252
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
1000static 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
1032static 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
1051static 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
1079static 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
1000static const union decode_item arm_cccc_000x_____1xx1_table[] = { 1090static 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[] = {
1079static enum kprobe_insn __kprobes 1185static enum kprobe_insn __kprobes
1080space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) 1186space_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}