aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid A. Long <dave.long@linaro.org>2014-03-05 21:40:12 -0500
committerDavid A. Long <dave.long@linaro.org>2014-03-18 16:39:39 -0400
commit602cd2609eee92d338a83e400774e97c60535ba2 (patch)
tree43a6513e831fbfccca7889d897af7b70ed27812a
parent47e190fafde49ff8ca732fa137e39cb2b8baba8c (diff)
ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions
Add an emulate flag into the instruction interpreter, primarily for uprobes support. Signed-off-by: David A. Long <dave.long@linaro.org> Acked-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r--arch/arm/kernel/kprobes.c2
-rw-r--r--arch/arm/kernel/kprobes.h1
-rw-r--r--arch/arm/kernel/probes-arm.c4
-rw-r--r--arch/arm/kernel/probes-arm.h2
-rw-r--r--arch/arm/kernel/probes-thumb.c8
-rw-r--r--arch/arm/kernel/probes-thumb.h4
-rw-r--r--arch/arm/kernel/probes.c18
-rw-r--r--arch/arm/kernel/probes.h2
8 files changed, 25 insertions, 16 deletions
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 468d4a980c6c..8795f9f819d5 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -89,7 +89,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
89 p->opcode = insn; 89 p->opcode = insn;
90 p->ainsn.insn = tmp_insn; 90 p->ainsn.insn = tmp_insn;
91 91
92 switch ((*decode_insn)(insn, &p->ainsn, actions)) { 92 switch ((*decode_insn)(insn, &p->ainsn, true, actions)) {
93 case INSN_REJECTED: /* not supported */ 93 case INSN_REJECTED: /* not supported */
94 return -EINVAL; 94 return -EINVAL;
95 95
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index eee8089b1b93..d0a24b73bcfa 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -35,6 +35,7 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
35 35
36typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, 36typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t,
37 struct arch_specific_insn *, 37 struct arch_specific_insn *,
38 bool,
38 const union decode_action *); 39 const union decode_action *);
39 40
40#ifdef CONFIG_THUMB2_KERNEL 41#ifdef CONFIG_THUMB2_KERNEL
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 738e5fc58928..8e7fde876521 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -725,10 +725,10 @@ static void __kprobes arm_singlestep(probes_opcode_t insn,
725 */ 725 */
726enum probes_insn __kprobes 726enum probes_insn __kprobes
727arm_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, 727arm_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
728 const union decode_action *actions) 728 bool emulate, const union decode_action *actions)
729{ 729{
730 asi->insn_singlestep = arm_singlestep; 730 asi->insn_singlestep = arm_singlestep;
731 asi->insn_check_cc = probes_condition_checks[insn>>28]; 731 asi->insn_check_cc = probes_condition_checks[insn>>28];
732 return probes_decode_insn(insn, asi, probes_decode_arm_table, false, 732 return probes_decode_insn(insn, asi, probes_decode_arm_table, false,
733 actions); 733 emulate, actions);
734} 734}
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index 7a5cce497a9b..ea614dc5aaa3 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -67,7 +67,7 @@ void __kprobes simulate_mov_ipsp(probes_opcode_t opcode,
67extern const union decode_item probes_decode_arm_table[]; 67extern const union decode_item probes_decode_arm_table[];
68 68
69enum probes_insn arm_probes_decode_insn(probes_opcode_t, 69enum probes_insn arm_probes_decode_insn(probes_opcode_t,
70 struct arch_specific_insn *, 70 struct arch_specific_insn *, bool emulate,
71 const union decode_action *actions); 71 const union decode_action *actions);
72 72
73#endif 73#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index eab440f6b2d4..23e2cbdb37cb 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -863,20 +863,20 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode,
863 863
864enum probes_insn __kprobes 864enum probes_insn __kprobes
865thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, 865thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
866 const union decode_action *actions) 866 bool emulate, const union decode_action *actions)
867{ 867{
868 asi->insn_singlestep = thumb16_singlestep; 868 asi->insn_singlestep = thumb16_singlestep;
869 asi->insn_check_cc = thumb_check_cc; 869 asi->insn_check_cc = thumb_check_cc;
870 return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, 870 return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true,
871 actions); 871 emulate, actions);
872} 872}
873 873
874enum probes_insn __kprobes 874enum probes_insn __kprobes
875thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, 875thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
876 const union decode_action *actions) 876 bool emulate, const union decode_action *actions)
877{ 877{
878 asi->insn_singlestep = thumb32_singlestep; 878 asi->insn_singlestep = thumb32_singlestep;
879 asi->insn_check_cc = thumb_check_cc; 879 asi->insn_check_cc = thumb_check_cc;
880 return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, 880 return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true,
881 actions); 881 emulate, actions);
882} 882}
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
index d6f67c1df7af..65e4250e9b78 100644
--- a/arch/arm/kernel/probes-thumb.h
+++ b/arch/arm/kernel/probes-thumb.h
@@ -89,9 +89,9 @@ extern const union decode_item probes_decode_thumb16_table[];
89 89
90enum probes_insn __kprobes 90enum probes_insn __kprobes
91thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, 91thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
92 const union decode_action *actions); 92 bool emulate, const union decode_action *actions);
93enum probes_insn __kprobes 93enum probes_insn __kprobes
94thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, 94thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
95 const union decode_action *actions); 95 bool emulate, const union decode_action *actions);
96 96
97#endif 97#endif
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;
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 0c72e544175d..33cc30c50cf5 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -401,7 +401,7 @@ probes_insn_handler_t probes_emulate_none;
401 401
402int __kprobes 402int __kprobes
403probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, 403probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
404 const union decode_item *table, bool thumb, 404 const union decode_item *table, bool thumb, bool emulate,
405 const union decode_action *actions); 405 const union decode_action *actions);
406 406
407#endif 407#endif