diff options
Diffstat (limited to 'arch/arm/kernel/probes.c')
-rw-r--r-- | arch/arm/kernel/probes.c | 18 |
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 | */ |
260 | static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs) | 260 | static 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 | ||
329 | reject: | 331 | reject: |
@@ -385,13 +387,14 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | |||
385 | int __kprobes | 387 | int __kprobes |
386 | probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, | 388 | probes_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; |