aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/probes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/probes.c')
-rw-r--r--arch/arm/kernel/probes.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index b6d9b855273c..f9dff12cf85c 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -257,7 +257,7 @@ set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
257 * non-zero value, the corresponding nibble in pinsn is validated and modified 257 * non-zero value, the corresponding nibble in pinsn is validated and modified
258 * according to the type. 258 * according to the type.
259 */ 259 */
260static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs) 260static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify)
261{ 261{
262 probes_opcode_t insn = *pinsn; 262 probes_opcode_t insn = *pinsn;
263 probes_opcode_t mask = 0xf; /* Start at least significant nibble */ 263 probes_opcode_t mask = 0xf; /* Start at least significant nibble */
@@ -323,7 +323,9 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs)
323 insn |= new_bits & mask; 323 insn |= new_bits & mask;
324 } 324 }
325 325
326 *pinsn = insn; 326 if (modify)
327 *pinsn = insn;
328
327 return true; 329 return true;
328 330
329reject: 331reject:
@@ -385,13 +387,14 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
385int __kprobes 387int __kprobes
386probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, 388probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
387 const union decode_item *table, bool thumb, 389 const union decode_item *table, bool thumb,
388 const union decode_action *actions) 390 bool emulate, const union decode_action *actions)
389{ 391{
390 const struct decode_header *h = (struct decode_header *)table; 392 const struct decode_header *h = (struct decode_header *)table;
391 const struct decode_header *next; 393 const struct decode_header *next;
392 bool matched = false; 394 bool matched = false;
393 395
394 insn = prepare_emulated_insn(insn, asi, thumb); 396 if (emulate)
397 insn = prepare_emulated_insn(insn, asi, thumb);
395 398
396 for (;; h = next) { 399 for (;; h = next) {
397 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; 400 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
@@ -406,7 +409,7 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
406 if (!matched && (insn & h->mask.bits) != h->value.bits) 409 if (!matched && (insn & h->mask.bits) != h->value.bits)
407 continue; 410 continue;
408 411
409 if (!decode_regs(&insn, regs)) 412 if (!decode_regs(&insn, regs, emulate))
410 return INSN_REJECTED; 413 return INSN_REJECTED;
411 414
412 switch (type) { 415 switch (type) {
@@ -430,6 +433,11 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
430 433
431 case DECODE_TYPE_EMULATE: { 434 case DECODE_TYPE_EMULATE: {
432 struct decode_emulate *d = (struct decode_emulate *)h; 435 struct decode_emulate *d = (struct decode_emulate *)h;
436
437 if (!emulate)
438 return actions[d->handler.action].decoder(insn,
439 asi, h);
440
433 asi->insn_handler = actions[d->handler.action].handler; 441 asi->insn_handler = actions[d->handler.action].handler;
434 set_emulated_insn(insn, asi, thumb); 442 set_emulated_insn(insn, asi, thumb);
435 return INSN_GOOD; 443 return INSN_GOOD;