diff options
-rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 116 |
1 files changed, 50 insertions, 66 deletions
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index ef350a5cd9b0..f2eed03f5522 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
@@ -1203,72 +1203,56 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1203 | return kprobe_decode_insn(insn, asi, arm_cccc_000x_table, false); | 1203 | return kprobe_decode_insn(insn, asi, arm_cccc_000x_table, false); |
1204 | } | 1204 | } |
1205 | 1205 | ||
1206 | static enum kprobe_insn __kprobes | 1206 | static const union decode_item arm_cccc_001x_table[] = { |
1207 | space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 1207 | /* Data-processing (immediate) */ |
1208 | { | 1208 | |
1209 | /* MOVW : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | 1209 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ |
1210 | /* MOVT : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | 1210 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ |
1211 | if ((insn & 0x0fb00000) == 0x03000000) | 1211 | DECODE_CUSTOM (0x0fb00000, 0x03000000, prep_emulate_rd12_modify), |
1212 | return prep_emulate_rd12_modify(insn, asi); | 1212 | |
1213 | 1213 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | |
1214 | /* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | 1214 | DECODE_OR (0x0fff00ff, 0x03200001), |
1215 | if ((insn & 0x0fff0000) == 0x03200000) { | 1215 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ |
1216 | unsigned op2 = insn & 0x000000ff; | 1216 | DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none), |
1217 | if (op2 == 0x01 || op2 == 0x04) { | 1217 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ |
1218 | /* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | 1218 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ |
1219 | /* SEV : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | 1219 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ |
1220 | asi->insn[0] = insn; | 1220 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop), |
1221 | asi->insn_handler = emulate_none; | 1221 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ |
1222 | return INSN_GOOD; | 1222 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ |
1223 | } else if (op2 <= 0x03) { | 1223 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ |
1224 | /* NOP : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | 1224 | DECODE_REJECT (0x0fb00000, 0x03200000), |
1225 | /* WFE : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | 1225 | |
1226 | /* WFI : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | 1226 | /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ |
1227 | /* | 1227 | DECODE_REJECT (0x0e10f000, 0x0210f000), |
1228 | * We make WFE and WFI true NOPs to avoid stalls due | 1228 | |
1229 | * to missing events whilst processing the probe. | 1229 | /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */ |
1230 | */ | 1230 | /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ |
1231 | asi->insn_handler = emulate_nop; | 1231 | /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ |
1232 | return INSN_GOOD_NO_SLOT; | 1232 | /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ |
1233 | } | 1233 | DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags, |
1234 | /* For DBG and unallocated hints it's safest to reject them */ | 1234 | REGS(ANY, 0, 0, 0, 0)), |
1235 | return INSN_REJECTED; | 1235 | |
1236 | } | 1236 | /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ |
1237 | /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ | ||
1238 | DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags, | ||
1239 | REGS(0, ANY, 0, 0, 0)), | ||
1240 | |||
1241 | /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ | ||
1242 | /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */ | ||
1243 | /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */ | ||
1244 | /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */ | ||
1245 | /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */ | ||
1246 | /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */ | ||
1247 | /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */ | ||
1248 | /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ | ||
1249 | /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ | ||
1250 | /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ | ||
1251 | DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags, | ||
1252 | REGS(ANY, ANY, 0, 0, 0)), | ||
1237 | 1253 | ||
1238 | /* | 1254 | DECODE_END |
1239 | * MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx | 1255 | }; |
1240 | * ALU op with S bit and Rd == 15 : | ||
1241 | * cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx | ||
1242 | */ | ||
1243 | if ((insn & 0x0fb00000) == 0x03200000 || /* MSR */ | ||
1244 | (insn & 0x0e10f000) == 0x0210f000) /* ALU s-bit, R15 */ | ||
1245 | return INSN_REJECTED; | ||
1246 | |||
1247 | /* | ||
1248 | * Data processing: 32-bit Immediate | ||
1249 | * ALU op : cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx | ||
1250 | * MOV : cccc 0011 101x xxxx xxxx xxxx xxxx xxxx | ||
1251 | * *S (bit 20) updates condition codes | ||
1252 | * ADC/SBC/RSC reads the C flag | ||
1253 | */ | ||
1254 | insn &= 0xfff00fff; /* Rn = r0 and Rd = r0 */ | ||
1255 | asi->insn[0] = insn; | ||
1256 | |||
1257 | if ((insn & 0x0f900000) == 0x03100000) { | ||
1258 | /* | ||
1259 | * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx | ||
1260 | * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx | ||
1261 | * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx | ||
1262 | * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx | ||
1263 | */ | ||
1264 | asi->insn_handler = emulate_alu_tests_imm; | ||
1265 | } else { | ||
1266 | /* ALU ops which write to Rd */ | ||
1267 | asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */ | ||
1268 | emulate_alu_imm_rwflags : emulate_alu_imm_rflags; | ||
1269 | } | ||
1270 | return INSN_GOOD; | ||
1271 | } | ||
1272 | 1256 | ||
1273 | static enum kprobe_insn __kprobes | 1257 | static enum kprobe_insn __kprobes |
1274 | space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 1258 | space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) |
@@ -1548,7 +1532,7 @@ arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1548 | 1532 | ||
1549 | else if ((insn & 0x0e000000) == 0x02000000) | 1533 | else if ((insn & 0x0e000000) == 0x02000000) |
1550 | 1534 | ||
1551 | return space_cccc_001x(insn, asi); | 1535 | return kprobe_decode_insn(insn, asi, arm_cccc_001x_table, false); |
1552 | 1536 | ||
1553 | else if ((insn & 0x0f000010) == 0x06000010) | 1537 | else if ((insn & 0x0f000010) == 0x06000010) |
1554 | 1538 | ||