summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid A. Long <dave.long@linaro.org>2014-03-07 11:19:32 -0500
committerDavid A. Long <dave.long@linaro.org>2014-03-18 16:39:37 -0400
commit7579f4b3764337b39087d10496af0e741cbfe570 (patch)
tree009a68f8615a04fa038874522493006c2efb8022
parent3e6cd394bb10c2d65322e5f5d2ff0a9074d903a1 (diff)
ARM: Remove use of struct kprobe from generic probes code
Change the generic ARM probes code to pass in the opcode and architecture-specific structure separately instead of using struct kprobe, so we do not pollute code being used only for uprobes or other non-kprobes instruction interpretation. Signed-off-by: David A. Long <dave.long@linaro.org> Acked-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r--arch/arm/include/asm/probes.h9
-rw-r--r--arch/arm/kernel/kprobes-arm.c61
-rw-r--r--arch/arm/kernel/kprobes-common.c40
-rw-r--r--arch/arm/kernel/kprobes-thumb.c175
-rw-r--r--arch/arm/kernel/kprobes.c2
-rw-r--r--arch/arm/kernel/probes-arm.c33
-rw-r--r--arch/arm/kernel/probes-arm.h15
-rw-r--r--arch/arm/kernel/probes-thumb.c15
-rw-r--r--arch/arm/kernel/probes.c13
-rw-r--r--arch/arm/kernel/probes.h8
10 files changed, 201 insertions, 170 deletions
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index 737a9b310efc..4d014c4aa1e7 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -21,9 +21,14 @@
21 21
22struct kprobe; 22struct kprobe;
23 23
24typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); 24struct arch_specific_insn;
25typedef void (kprobe_insn_handler_t)(kprobe_opcode_t,
26 struct arch_specific_insn *,
27 struct pt_regs *);
25typedef unsigned long (kprobe_check_cc)(unsigned long); 28typedef unsigned long (kprobe_check_cc)(unsigned long);
26typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); 29typedef void (kprobe_insn_singlestep_t)(kprobe_opcode_t,
30 struct arch_specific_insn *,
31 struct pt_regs *);
27typedef void (kprobe_insn_fn_t)(void); 32typedef void (kprobe_insn_fn_t)(void);
28 33
29/* Architecture specific copy of original instruction. */ 34/* Architecture specific copy of original instruction. */
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 8ebd84c48867..4a232e682e5a 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -72,12 +72,11 @@
72 "mov pc, "reg" \n\t" 72 "mov pc, "reg" \n\t"
73#endif 73#endif
74 74
75
76static void __kprobes 75static void __kprobes
77emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) 76emulate_ldrdstrd(kprobe_opcode_t insn,
77 struct arch_specific_insn *asi, struct pt_regs *regs)
78{ 78{
79 kprobe_opcode_t insn = p->opcode; 79 unsigned long pc = regs->ARM_pc + 4;
80 unsigned long pc = (unsigned long)p->addr + 8;
81 int rt = (insn >> 12) & 0xf; 80 int rt = (insn >> 12) & 0xf;
82 int rn = (insn >> 16) & 0xf; 81 int rn = (insn >> 16) & 0xf;
83 int rm = insn & 0xf; 82 int rm = insn & 0xf;
@@ -92,7 +91,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
92 BLX("%[fn]") 91 BLX("%[fn]")
93 : "=r" (rtv), "=r" (rt2v), "=r" (rnv) 92 : "=r" (rtv), "=r" (rt2v), "=r" (rnv)
94 : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), 93 : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
95 [fn] "r" (p->ainsn.insn_fn) 94 [fn] "r" (asi->insn_fn)
96 : "lr", "memory", "cc" 95 : "lr", "memory", "cc"
97 ); 96 );
98 97
@@ -103,10 +102,10 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
103} 102}
104 103
105static void __kprobes 104static void __kprobes
106emulate_ldr(struct kprobe *p, struct pt_regs *regs) 105emulate_ldr(kprobe_opcode_t insn,
106 struct arch_specific_insn *asi, struct pt_regs *regs)
107{ 107{
108 kprobe_opcode_t insn = p->opcode; 108 unsigned long pc = regs->ARM_pc + 4;
109 unsigned long pc = (unsigned long)p->addr + 8;
110 int rt = (insn >> 12) & 0xf; 109 int rt = (insn >> 12) & 0xf;
111 int rn = (insn >> 16) & 0xf; 110 int rn = (insn >> 16) & 0xf;
112 int rm = insn & 0xf; 111 int rm = insn & 0xf;
@@ -119,7 +118,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs)
119 __asm__ __volatile__ ( 118 __asm__ __volatile__ (
120 BLX("%[fn]") 119 BLX("%[fn]")
121 : "=r" (rtv), "=r" (rnv) 120 : "=r" (rtv), "=r" (rnv)
122 : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) 121 : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
123 : "lr", "memory", "cc" 122 : "lr", "memory", "cc"
124 ); 123 );
125 124
@@ -133,11 +132,11 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs)
133} 132}
134 133
135static void __kprobes 134static void __kprobes
136emulate_str(struct kprobe *p, struct pt_regs *regs) 135emulate_str(kprobe_opcode_t insn,
136 struct arch_specific_insn *asi, struct pt_regs *regs)
137{ 137{
138 kprobe_opcode_t insn = p->opcode; 138 unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
139 unsigned long rtpc = (unsigned long)p->addr + str_pc_offset; 139 unsigned long rnpc = regs->ARM_pc + 4;
140 unsigned long rnpc = (unsigned long)p->addr + 8;
141 int rt = (insn >> 12) & 0xf; 140 int rt = (insn >> 12) & 0xf;
142 int rn = (insn >> 16) & 0xf; 141 int rn = (insn >> 16) & 0xf;
143 int rm = insn & 0xf; 142 int rm = insn & 0xf;
@@ -151,7 +150,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs)
151 __asm__ __volatile__ ( 150 __asm__ __volatile__ (
152 BLX("%[fn]") 151 BLX("%[fn]")
153 : "=r" (rnv) 152 : "=r" (rnv)
154 : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) 153 : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
155 : "lr", "memory", "cc" 154 : "lr", "memory", "cc"
156 ); 155 );
157 156
@@ -160,10 +159,10 @@ emulate_str(struct kprobe *p, struct pt_regs *regs)
160} 159}
161 160
162static void __kprobes 161static void __kprobes
163emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) 162emulate_rd12rn16rm0rs8_rwflags(kprobe_opcode_t insn,
163 struct arch_specific_insn *asi, struct pt_regs *regs)
164{ 164{
165 kprobe_opcode_t insn = p->opcode; 165 unsigned long pc = regs->ARM_pc + 4;
166 unsigned long pc = (unsigned long)p->addr + 8;
167 int rd = (insn >> 12) & 0xf; 166 int rd = (insn >> 12) & 0xf;
168 int rn = (insn >> 16) & 0xf; 167 int rn = (insn >> 16) & 0xf;
169 int rm = insn & 0xf; 168 int rm = insn & 0xf;
@@ -183,7 +182,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
183 "mrs %[cpsr], cpsr \n\t" 182 "mrs %[cpsr], cpsr \n\t"
184 : "=r" (rdv), [cpsr] "=r" (cpsr) 183 : "=r" (rdv), [cpsr] "=r" (cpsr)
185 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 184 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
186 "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) 185 "1" (cpsr), [fn] "r" (asi->insn_fn)
187 : "lr", "memory", "cc" 186 : "lr", "memory", "cc"
188 ); 187 );
189 188
@@ -195,9 +194,9 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
195} 194}
196 195
197static void __kprobes 196static void __kprobes
198emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) 197emulate_rd12rn16rm0_rwflags_nopc(kprobe_opcode_t insn,
198 struct arch_specific_insn *asi, struct pt_regs *regs)
199{ 199{
200 kprobe_opcode_t insn = p->opcode;
201 int rd = (insn >> 12) & 0xf; 200 int rd = (insn >> 12) & 0xf;
202 int rn = (insn >> 16) & 0xf; 201 int rn = (insn >> 16) & 0xf;
203 int rm = insn & 0xf; 202 int rm = insn & 0xf;
@@ -213,7 +212,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
213 "mrs %[cpsr], cpsr \n\t" 212 "mrs %[cpsr], cpsr \n\t"
214 : "=r" (rdv), [cpsr] "=r" (cpsr) 213 : "=r" (rdv), [cpsr] "=r" (cpsr)
215 : "0" (rdv), "r" (rnv), "r" (rmv), 214 : "0" (rdv), "r" (rnv), "r" (rmv),
216 "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) 215 "1" (cpsr), [fn] "r" (asi->insn_fn)
217 : "lr", "memory", "cc" 216 : "lr", "memory", "cc"
218 ); 217 );
219 218
@@ -222,9 +221,10 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
222} 221}
223 222
224static void __kprobes 223static void __kprobes
225emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) 224emulate_rd16rn12rm0rs8_rwflags_nopc(kprobe_opcode_t insn,
225 struct arch_specific_insn *asi,
226 struct pt_regs *regs)
226{ 227{
227 kprobe_opcode_t insn = p->opcode;
228 int rd = (insn >> 16) & 0xf; 228 int rd = (insn >> 16) & 0xf;
229 int rn = (insn >> 12) & 0xf; 229 int rn = (insn >> 12) & 0xf;
230 int rm = insn & 0xf; 230 int rm = insn & 0xf;
@@ -242,7 +242,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
242 "mrs %[cpsr], cpsr \n\t" 242 "mrs %[cpsr], cpsr \n\t"
243 : "=r" (rdv), [cpsr] "=r" (cpsr) 243 : "=r" (rdv), [cpsr] "=r" (cpsr)
244 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 244 : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
245 "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) 245 "1" (cpsr), [fn] "r" (asi->insn_fn)
246 : "lr", "memory", "cc" 246 : "lr", "memory", "cc"
247 ); 247 );
248 248
@@ -251,9 +251,9 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
251} 251}
252 252
253static void __kprobes 253static void __kprobes
254emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) 254emulate_rd12rm0_noflags_nopc(kprobe_opcode_t insn,
255 struct arch_specific_insn *asi, struct pt_regs *regs)
255{ 256{
256 kprobe_opcode_t insn = p->opcode;
257 int rd = (insn >> 12) & 0xf; 257 int rd = (insn >> 12) & 0xf;
258 int rm = insn & 0xf; 258 int rm = insn & 0xf;
259 259
@@ -263,7 +263,7 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
263 __asm__ __volatile__ ( 263 __asm__ __volatile__ (
264 BLX("%[fn]") 264 BLX("%[fn]")
265 : "=r" (rdv) 265 : "=r" (rdv)
266 : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) 266 : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
267 : "lr", "memory", "cc" 267 : "lr", "memory", "cc"
268 ); 268 );
269 269
@@ -271,9 +271,10 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
271} 271}
272 272
273static void __kprobes 273static void __kprobes
274emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) 274emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(kprobe_opcode_t insn,
275 struct arch_specific_insn *asi,
276 struct pt_regs *regs)
275{ 277{
276 kprobe_opcode_t insn = p->opcode;
277 int rdlo = (insn >> 12) & 0xf; 278 int rdlo = (insn >> 12) & 0xf;
278 int rdhi = (insn >> 16) & 0xf; 279 int rdhi = (insn >> 16) & 0xf;
279 int rn = insn & 0xf; 280 int rn = insn & 0xf;
@@ -291,7 +292,7 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
291 "mrs %[cpsr], cpsr \n\t" 292 "mrs %[cpsr], cpsr \n\t"
292 : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) 293 : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
293 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), 294 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
294 "2" (cpsr), [fn] "r" (p->ainsn.insn_fn) 295 "2" (cpsr), [fn] "r" (asi->insn_fn)
295 : "lr", "memory", "cc" 296 : "lr", "memory", "cc"
296 ); 297 );
297 298
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 029b79c6face..abe03890f84d 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -17,9 +17,10 @@
17#include "kprobes.h" 17#include "kprobes.h"
18 18
19 19
20static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) 20static void __kprobes simulate_ldm1stm1(kprobe_opcode_t insn,
21 struct arch_specific_insn *asi,
22 struct pt_regs *regs)
21{ 23{
22 kprobe_opcode_t insn = p->opcode;
23 int rn = (insn >> 16) & 0xf; 24 int rn = (insn >> 16) & 0xf;
24 int lbit = insn & (1 << 20); 25 int lbit = insn & (1 << 20);
25 int wbit = insn & (1 << 21); 26 int wbit = insn & (1 << 21);
@@ -58,24 +59,31 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
58 } 59 }
59} 60}
60 61
61static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs) 62static void __kprobes simulate_stm1_pc(kprobe_opcode_t insn,
63 struct arch_specific_insn *asi,
64 struct pt_regs *regs)
62{ 65{
63 regs->ARM_pc = (long)p->addr + str_pc_offset; 66 unsigned long addr = regs->ARM_pc - 4;
64 simulate_ldm1stm1(p, regs); 67
65 regs->ARM_pc = (long)p->addr + 4; 68 regs->ARM_pc = (long)addr + str_pc_offset;
69 simulate_ldm1stm1(insn, asi, regs);
70 regs->ARM_pc = (long)addr + 4;
66} 71}
67 72
68static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs) 73static void __kprobes simulate_ldm1_pc(kprobe_opcode_t insn,
74 struct arch_specific_insn *asi,
75 struct pt_regs *regs)
69{ 76{
70 simulate_ldm1stm1(p, regs); 77 simulate_ldm1stm1(insn, asi, regs);
71 load_write_pc(regs->ARM_pc, regs); 78 load_write_pc(regs->ARM_pc, regs);
72} 79}
73 80
74static void __kprobes 81static void __kprobes
75emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs) 82emulate_generic_r0_12_noflags(kprobe_opcode_t insn,
83 struct arch_specific_insn *asi, struct pt_regs *regs)
76{ 84{
77 register void *rregs asm("r1") = regs; 85 register void *rregs asm("r1") = regs;
78 register void *rfn asm("lr") = p->ainsn.insn_fn; 86 register void *rfn asm("lr") = asi->insn_fn;
79 87
80 __asm__ __volatile__ ( 88 __asm__ __volatile__ (
81 "stmdb sp!, {%[regs], r11} \n\t" 89 "stmdb sp!, {%[regs], r11} \n\t"
@@ -99,15 +107,19 @@ emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
99} 107}
100 108
101static void __kprobes 109static void __kprobes
102emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs) 110emulate_generic_r2_14_noflags(kprobe_opcode_t insn,
111 struct arch_specific_insn *asi, struct pt_regs *regs)
103{ 112{
104 emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2)); 113 emulate_generic_r0_12_noflags(insn, asi,
114 (struct pt_regs *)(regs->uregs+2));
105} 115}
106 116
107static void __kprobes 117static void __kprobes
108emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs) 118emulate_ldm_r3_15(kprobe_opcode_t insn,
119 struct arch_specific_insn *asi, struct pt_regs *regs)
109{ 120{
110 emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3)); 121 emulate_generic_r0_12_noflags(insn, asi,
122 (struct pt_regs *)(regs->uregs+3));
111 load_write_pc(regs->ARM_pc, regs); 123 load_write_pc(regs->ARM_pc, regs);
112} 124}
113 125
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index d83f6092920a..adc08f8d4a1c 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -20,24 +20,13 @@
20#define t32_emulate_rd8rn16rm0ra12_noflags \ 20#define t32_emulate_rd8rn16rm0ra12_noflags \
21 t32_emulate_rdlo12rdhi8rn16rm0_noflags 21 t32_emulate_rdlo12rdhi8rn16rm0_noflags
22 22
23/*
24 * Return the PC value for a probe in thumb code.
25 * This is the address of the probed instruction plus 4.
26 * We subtract one because the address will have bit zero set to indicate
27 * a pointer to thumb code.
28 */
29static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
30{
31 return (unsigned long)p->addr - 1 + 4;
32}
33
34/* t32 thumb actions */ 23/* t32 thumb actions */
35 24
36static void __kprobes 25static void __kprobes
37t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) 26t32_simulate_table_branch(kprobe_opcode_t insn,
27 struct arch_specific_insn *asi, struct pt_regs *regs)
38{ 28{
39 kprobe_opcode_t insn = p->opcode; 29 unsigned long pc = regs->ARM_pc;
40 unsigned long pc = thumb_probe_pc(p);
41 int rn = (insn >> 16) & 0xf; 30 int rn = (insn >> 16) & 0xf;
42 int rm = insn & 0xf; 31 int rm = insn & 0xf;
43 32
@@ -54,19 +43,19 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
54} 43}
55 44
56static void __kprobes 45static void __kprobes
57t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs) 46t32_simulate_mrs(kprobe_opcode_t insn,
47 struct arch_specific_insn *asi, struct pt_regs *regs)
58{ 48{
59 kprobe_opcode_t insn = p->opcode;
60 int rd = (insn >> 8) & 0xf; 49 int rd = (insn >> 8) & 0xf;
61 unsigned long mask = 0xf8ff03df; /* Mask out execution state */ 50 unsigned long mask = 0xf8ff03df; /* Mask out execution state */
62 regs->uregs[rd] = regs->ARM_cpsr & mask; 51 regs->uregs[rd] = regs->ARM_cpsr & mask;
63} 52}
64 53
65static void __kprobes 54static void __kprobes
66t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) 55t32_simulate_cond_branch(kprobe_opcode_t insn,
56 struct arch_specific_insn *asi, struct pt_regs *regs)
67{ 57{
68 kprobe_opcode_t insn = p->opcode; 58 unsigned long pc = regs->ARM_pc;
69 unsigned long pc = thumb_probe_pc(p);
70 59
71 long offset = insn & 0x7ff; /* imm11 */ 60 long offset = insn & 0x7ff; /* imm11 */
72 offset += (insn & 0x003f0000) >> 5; /* imm6 */ 61 offset += (insn & 0x003f0000) >> 5; /* imm6 */
@@ -88,10 +77,10 @@ t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
88} 77}
89 78
90static void __kprobes 79static void __kprobes
91t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) 80t32_simulate_branch(kprobe_opcode_t insn,
81 struct arch_specific_insn *asi, struct pt_regs *regs)
92{ 82{
93 kprobe_opcode_t insn = p->opcode; 83 unsigned long pc = regs->ARM_pc;
94 unsigned long pc = thumb_probe_pc(p);
95 84
96 long offset = insn & 0x7ff; /* imm11 */ 85 long offset = insn & 0x7ff; /* imm11 */
97 offset += (insn & 0x03ff0000) >> 5; /* imm10 */ 86 offset += (insn & 0x03ff0000) >> 5; /* imm10 */
@@ -104,7 +93,7 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
104 93
105 if (insn & (1 << 14)) { 94 if (insn & (1 << 14)) {
106 /* BL or BLX */ 95 /* BL or BLX */
107 regs->ARM_lr = (unsigned long)p->addr + 4; 96 regs->ARM_lr = regs->ARM_pc | 1;
108 if (!(insn & (1 << 12))) { 97 if (!(insn & (1 << 12))) {
109 /* BLX so switch to ARM mode */ 98 /* BLX so switch to ARM mode */
110 regs->ARM_cpsr &= ~PSR_T_BIT; 99 regs->ARM_cpsr &= ~PSR_T_BIT;
@@ -116,10 +105,10 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
116} 105}
117 106
118static void __kprobes 107static void __kprobes
119t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) 108t32_simulate_ldr_literal(kprobe_opcode_t insn,
109 struct arch_specific_insn *asi, struct pt_regs *regs)
120{ 110{
121 kprobe_opcode_t insn = p->opcode; 111 unsigned long addr = regs->ARM_pc & ~3;
122 unsigned long addr = thumb_probe_pc(p) & ~3;
123 int rt = (insn >> 12) & 0xf; 112 int rt = (insn >> 12) & 0xf;
124 unsigned long rtv; 113 unsigned long rtv;
125 114
@@ -168,10 +157,10 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
168} 157}
169 158
170static void __kprobes 159static void __kprobes
171t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) 160t32_emulate_ldrdstrd(kprobe_opcode_t insn,
161 struct arch_specific_insn *asi, struct pt_regs *regs)
172{ 162{
173 kprobe_opcode_t insn = p->opcode; 163 unsigned long pc = regs->ARM_pc & ~3;
174 unsigned long pc = thumb_probe_pc(p) & ~3;
175 int rt1 = (insn >> 12) & 0xf; 164 int rt1 = (insn >> 12) & 0xf;
176 int rt2 = (insn >> 8) & 0xf; 165 int rt2 = (insn >> 8) & 0xf;
177 int rn = (insn >> 16) & 0xf; 166 int rn = (insn >> 16) & 0xf;
@@ -184,7 +173,7 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
184 __asm__ __volatile__ ( 173 __asm__ __volatile__ (
185 "blx %[fn]" 174 "blx %[fn]"
186 : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) 175 : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
187 : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn) 176 : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn)
188 : "lr", "memory", "cc" 177 : "lr", "memory", "cc"
189 ); 178 );
190 179
@@ -195,9 +184,9 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
195} 184}
196 185
197static void __kprobes 186static void __kprobes
198t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) 187t32_emulate_ldrstr(kprobe_opcode_t insn,
188 struct arch_specific_insn *asi, struct pt_regs *regs)
199{ 189{
200 kprobe_opcode_t insn = p->opcode;
201 int rt = (insn >> 12) & 0xf; 190 int rt = (insn >> 12) & 0xf;
202 int rn = (insn >> 16) & 0xf; 191 int rn = (insn >> 16) & 0xf;
203 int rm = insn & 0xf; 192 int rm = insn & 0xf;
@@ -209,7 +198,7 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
209 __asm__ __volatile__ ( 198 __asm__ __volatile__ (
210 "blx %[fn]" 199 "blx %[fn]"
211 : "=r" (rtv), "=r" (rnv) 200 : "=r" (rtv), "=r" (rnv)
212 : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) 201 : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
213 : "lr", "memory", "cc" 202 : "lr", "memory", "cc"
214 ); 203 );
215 204
@@ -221,9 +210,9 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
221} 210}
222 211
223static void __kprobes 212static void __kprobes
224t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) 213t32_emulate_rd8rn16rm0_rwflags(kprobe_opcode_t insn,
214 struct arch_specific_insn *asi, struct pt_regs *regs)
225{ 215{
226 kprobe_opcode_t insn = p->opcode;
227 int rd = (insn >> 8) & 0xf; 216 int rd = (insn >> 8) & 0xf;
228 int rn = (insn >> 16) & 0xf; 217 int rn = (insn >> 16) & 0xf;
229 int rm = insn & 0xf; 218 int rm = insn & 0xf;
@@ -239,7 +228,7 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
239 "mrs %[cpsr], cpsr \n\t" 228 "mrs %[cpsr], cpsr \n\t"
240 : "=r" (rdv), [cpsr] "=r" (cpsr) 229 : "=r" (rdv), [cpsr] "=r" (cpsr)
241 : "0" (rdv), "r" (rnv), "r" (rmv), 230 : "0" (rdv), "r" (rnv), "r" (rmv),
242 "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) 231 "1" (cpsr), [fn] "r" (asi->insn_fn)
243 : "lr", "memory", "cc" 232 : "lr", "memory", "cc"
244 ); 233 );
245 234
@@ -248,10 +237,10 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
248} 237}
249 238
250static void __kprobes 239static void __kprobes
251t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) 240t32_emulate_rd8pc16_noflags(kprobe_opcode_t insn,
241 struct arch_specific_insn *asi, struct pt_regs *regs)
252{ 242{
253 kprobe_opcode_t insn = p->opcode; 243 unsigned long pc = regs->ARM_pc;
254 unsigned long pc = thumb_probe_pc(p);
255 int rd = (insn >> 8) & 0xf; 244 int rd = (insn >> 8) & 0xf;
256 245
257 register unsigned long rdv asm("r1") = regs->uregs[rd]; 246 register unsigned long rdv asm("r1") = regs->uregs[rd];
@@ -260,7 +249,7 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
260 __asm__ __volatile__ ( 249 __asm__ __volatile__ (
261 "blx %[fn]" 250 "blx %[fn]"
262 : "=r" (rdv) 251 : "=r" (rdv)
263 : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) 252 : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
264 : "lr", "memory", "cc" 253 : "lr", "memory", "cc"
265 ); 254 );
266 255
@@ -268,9 +257,9 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
268} 257}
269 258
270static void __kprobes 259static void __kprobes
271t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) 260t32_emulate_rd8rn16_noflags(kprobe_opcode_t insn,
261 struct arch_specific_insn *asi, struct pt_regs *regs)
272{ 262{
273 kprobe_opcode_t insn = p->opcode;
274 int rd = (insn >> 8) & 0xf; 263 int rd = (insn >> 8) & 0xf;
275 int rn = (insn >> 16) & 0xf; 264 int rn = (insn >> 16) & 0xf;
276 265
@@ -280,7 +269,7 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
280 __asm__ __volatile__ ( 269 __asm__ __volatile__ (
281 "blx %[fn]" 270 "blx %[fn]"
282 : "=r" (rdv) 271 : "=r" (rdv)
283 : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) 272 : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
284 : "lr", "memory", "cc" 273 : "lr", "memory", "cc"
285 ); 274 );
286 275
@@ -288,9 +277,10 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
288} 277}
289 278
290static void __kprobes 279static void __kprobes
291t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) 280t32_emulate_rdlo12rdhi8rn16rm0_noflags(kprobe_opcode_t insn,
281 struct arch_specific_insn *asi,
282 struct pt_regs *regs)
292{ 283{
293 kprobe_opcode_t insn = p->opcode;
294 int rdlo = (insn >> 12) & 0xf; 284 int rdlo = (insn >> 12) & 0xf;
295 int rdhi = (insn >> 8) & 0xf; 285 int rdhi = (insn >> 8) & 0xf;
296 int rn = (insn >> 16) & 0xf; 286 int rn = (insn >> 16) & 0xf;
@@ -305,7 +295,7 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
305 "blx %[fn]" 295 "blx %[fn]"
306 : "=r" (rdlov), "=r" (rdhiv) 296 : "=r" (rdlov), "=r" (rdhiv)
307 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), 297 : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
308 [fn] "r" (p->ainsn.insn_fn) 298 [fn] "r" (asi->insn_fn)
309 : "lr", "memory", "cc" 299 : "lr", "memory", "cc"
310 ); 300 );
311 301
@@ -315,33 +305,33 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
315/* t16 thumb actions */ 305/* t16 thumb actions */
316 306
317static void __kprobes 307static void __kprobes
318t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) 308t16_simulate_bxblx(kprobe_opcode_t insn,
309 struct arch_specific_insn *asi, struct pt_regs *regs)
319{ 310{
320 kprobe_opcode_t insn = p->opcode; 311 unsigned long pc = regs->ARM_pc + 2;
321 unsigned long pc = thumb_probe_pc(p);
322 int rm = (insn >> 3) & 0xf; 312 int rm = (insn >> 3) & 0xf;
323 unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; 313 unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
324 314
325 if (insn & (1 << 7)) /* BLX ? */ 315 if (insn & (1 << 7)) /* BLX ? */
326 regs->ARM_lr = (unsigned long)p->addr + 2; 316 regs->ARM_lr = regs->ARM_pc | 1;
327 317
328 bx_write_pc(rmv, regs); 318 bx_write_pc(rmv, regs);
329} 319}
330 320
331static void __kprobes 321static void __kprobes
332t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) 322t16_simulate_ldr_literal(kprobe_opcode_t insn,
323 struct arch_specific_insn *asi, struct pt_regs *regs)
333{ 324{
334 kprobe_opcode_t insn = p->opcode; 325 unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
335 unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
336 long index = insn & 0xff; 326 long index = insn & 0xff;
337 int rt = (insn >> 8) & 0x7; 327 int rt = (insn >> 8) & 0x7;
338 regs->uregs[rt] = base[index]; 328 regs->uregs[rt] = base[index];
339} 329}
340 330
341static void __kprobes 331static void __kprobes
342t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) 332t16_simulate_ldrstr_sp_relative(kprobe_opcode_t insn,
333 struct arch_specific_insn *asi, struct pt_regs *regs)
343{ 334{
344 kprobe_opcode_t insn = p->opcode;
345 unsigned long* base = (unsigned long *)regs->ARM_sp; 335 unsigned long* base = (unsigned long *)regs->ARM_sp;
346 long index = insn & 0xff; 336 long index = insn & 0xff;
347 int rt = (insn >> 8) & 0x7; 337 int rt = (insn >> 8) & 0x7;
@@ -352,20 +342,20 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
352} 342}
353 343
354static void __kprobes 344static void __kprobes
355t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs) 345t16_simulate_reladr(kprobe_opcode_t insn,
346 struct arch_specific_insn *asi, struct pt_regs *regs)
356{ 347{
357 kprobe_opcode_t insn = p->opcode;
358 unsigned long base = (insn & 0x800) ? regs->ARM_sp 348 unsigned long base = (insn & 0x800) ? regs->ARM_sp
359 : (thumb_probe_pc(p) & ~3); 349 : ((regs->ARM_pc + 2) & ~3);
360 long offset = insn & 0xff; 350 long offset = insn & 0xff;
361 int rt = (insn >> 8) & 0x7; 351 int rt = (insn >> 8) & 0x7;
362 regs->uregs[rt] = base + offset * 4; 352 regs->uregs[rt] = base + offset * 4;
363} 353}
364 354
365static void __kprobes 355static void __kprobes
366t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) 356t16_simulate_add_sp_imm(kprobe_opcode_t insn,
357 struct arch_specific_insn *asi, struct pt_regs *regs)
367{ 358{
368 kprobe_opcode_t insn = p->opcode;
369 long imm = insn & 0x7f; 359 long imm = insn & 0x7f;
370 if (insn & 0x80) /* SUB */ 360 if (insn & 0x80) /* SUB */
371 regs->ARM_sp -= imm * 4; 361 regs->ARM_sp -= imm * 4;
@@ -374,21 +364,22 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
374} 364}
375 365
376static void __kprobes 366static void __kprobes
377t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs) 367t16_simulate_cbz(kprobe_opcode_t insn,
368 struct arch_specific_insn *asi, struct pt_regs *regs)
378{ 369{
379 kprobe_opcode_t insn = p->opcode;
380 int rn = insn & 0x7; 370 int rn = insn & 0x7;
381 kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; 371 kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
382 if (nonzero & 0x800) { 372 if (nonzero & 0x800) {
383 long i = insn & 0x200; 373 long i = insn & 0x200;
384 long imm5 = insn & 0xf8; 374 long imm5 = insn & 0xf8;
385 unsigned long pc = thumb_probe_pc(p); 375 unsigned long pc = regs->ARM_pc + 2;
386 regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); 376 regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
387 } 377 }
388} 378}
389 379
390static void __kprobes 380static void __kprobes
391t16_simulate_it(struct kprobe *p, struct pt_regs *regs) 381t16_simulate_it(kprobe_opcode_t insn,
382 struct arch_specific_insn *asi, struct pt_regs *regs)
392{ 383{
393 /* 384 /*
394 * The 8 IT state bits are split into two parts in CPSR: 385 * The 8 IT state bits are split into two parts in CPSR:
@@ -396,7 +387,6 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
396 * ITSTATE<7:2> are in CPSR<15:10> 387 * ITSTATE<7:2> are in CPSR<15:10>
397 * The new IT state is in the lower byte of insn. 388 * The new IT state is in the lower byte of insn.
398 */ 389 */
399 kprobe_opcode_t insn = p->opcode;
400 unsigned long cpsr = regs->ARM_cpsr; 390 unsigned long cpsr = regs->ARM_cpsr;
401 cpsr &= ~PSR_IT_MASK; 391 cpsr &= ~PSR_IT_MASK;
402 cpsr |= (insn & 0xfc) << 8; 392 cpsr |= (insn & 0xfc) << 8;
@@ -405,10 +395,11 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
405} 395}
406 396
407static void __kprobes 397static void __kprobes
408t16_singlestep_it(struct kprobe *p, struct pt_regs *regs) 398t16_singlestep_it(kprobe_opcode_t insn,
399 struct arch_specific_insn *asi, struct pt_regs *regs)
409{ 400{
410 regs->ARM_pc += 2; 401 regs->ARM_pc += 2;
411 t16_simulate_it(p, regs); 402 t16_simulate_it(insn, asi, regs);
412} 403}
413 404
414static enum kprobe_insn __kprobes 405static enum kprobe_insn __kprobes
@@ -420,10 +411,10 @@ t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
420} 411}
421 412
422static void __kprobes 413static void __kprobes
423t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) 414t16_simulate_cond_branch(kprobe_opcode_t insn,
415 struct arch_specific_insn *asi, struct pt_regs *regs)
424{ 416{
425 kprobe_opcode_t insn = p->opcode; 417 unsigned long pc = regs->ARM_pc + 2;
426 unsigned long pc = thumb_probe_pc(p);
427 long offset = insn & 0x7f; 418 long offset = insn & 0x7f;
428 offset -= insn & 0x80; /* Apply sign bit */ 419 offset -= insn & 0x80; /* Apply sign bit */
429 regs->ARM_pc = pc + (offset * 2); 420 regs->ARM_pc = pc + (offset * 2);
@@ -440,17 +431,18 @@ t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
440} 431}
441 432
442static void __kprobes 433static void __kprobes
443t16_simulate_branch(struct kprobe *p, struct pt_regs *regs) 434t16_simulate_branch(kprobe_opcode_t insn,
435 struct arch_specific_insn *asi, struct pt_regs *regs)
444{ 436{
445 kprobe_opcode_t insn = p->opcode; 437 unsigned long pc = regs->ARM_pc + 2;
446 unsigned long pc = thumb_probe_pc(p);
447 long offset = insn & 0x3ff; 438 long offset = insn & 0x3ff;
448 offset -= insn & 0x400; /* Apply sign bit */ 439 offset -= insn & 0x400; /* Apply sign bit */
449 regs->ARM_pc = pc + (offset * 2); 440 regs->ARM_pc = pc + (offset * 2);
450} 441}
451 442
452static unsigned long __kprobes 443static unsigned long __kprobes
453t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) 444t16_emulate_loregs(kprobe_opcode_t insn,
445 struct arch_specific_insn *asi, struct pt_regs *regs)
454{ 446{
455 unsigned long oldcpsr = regs->ARM_cpsr; 447 unsigned long oldcpsr = regs->ARM_cpsr;
456 unsigned long newcpsr; 448 unsigned long newcpsr;
@@ -463,7 +455,7 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
463 "mrs %[newcpsr], cpsr \n\t" 455 "mrs %[newcpsr], cpsr \n\t"
464 : [newcpsr] "=r" (newcpsr) 456 : [newcpsr] "=r" (newcpsr)
465 : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), 457 : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
466 [fn] "r" (p->ainsn.insn_fn) 458 [fn] "r" (asi->insn_fn)
467 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 459 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
468 "lr", "memory", "cc" 460 "lr", "memory", "cc"
469 ); 461 );
@@ -472,24 +464,26 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
472} 464}
473 465
474static void __kprobes 466static void __kprobes
475t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs) 467t16_emulate_loregs_rwflags(kprobe_opcode_t insn,
468 struct arch_specific_insn *asi, struct pt_regs *regs)
476{ 469{
477 regs->ARM_cpsr = t16_emulate_loregs(p, regs); 470 regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
478} 471}
479 472
480static void __kprobes 473static void __kprobes
481t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) 474t16_emulate_loregs_noitrwflags(kprobe_opcode_t insn,
475 struct arch_specific_insn *asi, struct pt_regs *regs)
482{ 476{
483 unsigned long cpsr = t16_emulate_loregs(p, regs); 477 unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
484 if (!in_it_block(cpsr)) 478 if (!in_it_block(cpsr))
485 regs->ARM_cpsr = cpsr; 479 regs->ARM_cpsr = cpsr;
486} 480}
487 481
488static void __kprobes 482static void __kprobes
489t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) 483t16_emulate_hiregs(kprobe_opcode_t insn,
484 struct arch_specific_insn *asi, struct pt_regs *regs)
490{ 485{
491 kprobe_opcode_t insn = p->opcode; 486 unsigned long pc = regs->ARM_pc + 2;
492 unsigned long pc = thumb_probe_pc(p);
493 int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); 487 int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
494 int rm = (insn >> 3) & 0xf; 488 int rm = (insn >> 3) & 0xf;
495 489
@@ -505,7 +499,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
505 "blx %[fn] \n\t" 499 "blx %[fn] \n\t"
506 "mrs %[cpsr], cpsr \n\t" 500 "mrs %[cpsr], cpsr \n\t"
507 : "=r" (rdnv), [cpsr] "=r" (cpsr) 501 : "=r" (rdnv), [cpsr] "=r" (cpsr)
508 : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) 502 : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn)
509 : "lr", "memory", "cc" 503 : "lr", "memory", "cc"
510 ); 504 );
511 505
@@ -528,7 +522,8 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
528} 522}
529 523
530static void __kprobes 524static void __kprobes
531t16_emulate_push(struct kprobe *p, struct pt_regs *regs) 525t16_emulate_push(kprobe_opcode_t insn,
526 struct arch_specific_insn *asi, struct pt_regs *regs)
532{ 527{
533 __asm__ __volatile__ ( 528 __asm__ __volatile__ (
534 "ldr r9, [%[regs], #13*4] \n\t" 529 "ldr r9, [%[regs], #13*4] \n\t"
@@ -537,7 +532,7 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
537 "blx %[fn] \n\t" 532 "blx %[fn] \n\t"
538 "str r9, [%[regs], #13*4] \n\t" 533 "str r9, [%[regs], #13*4] \n\t"
539 : 534 :
540 : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) 535 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
541 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", 536 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
542 "lr", "memory", "cc" 537 "lr", "memory", "cc"
543 ); 538 );
@@ -559,7 +554,8 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
559} 554}
560 555
561static void __kprobes 556static void __kprobes
562t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) 557t16_emulate_pop_nopc(kprobe_opcode_t insn,
558 struct arch_specific_insn *asi, struct pt_regs *regs)
563{ 559{
564 __asm__ __volatile__ ( 560 __asm__ __volatile__ (
565 "ldr r9, [%[regs], #13*4] \n\t" 561 "ldr r9, [%[regs], #13*4] \n\t"
@@ -568,14 +564,15 @@ t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
568 "stmia %[regs], {r0-r7} \n\t" 564 "stmia %[regs], {r0-r7} \n\t"
569 "str r9, [%[regs], #13*4] \n\t" 565 "str r9, [%[regs], #13*4] \n\t"
570 : 566 :
571 : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) 567 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
572 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 568 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
573 "lr", "memory", "cc" 569 "lr", "memory", "cc"
574 ); 570 );
575} 571}
576 572
577static void __kprobes 573static void __kprobes
578t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) 574t16_emulate_pop_pc(kprobe_opcode_t insn,
575 struct arch_specific_insn *asi, struct pt_regs *regs)
579{ 576{
580 register unsigned long pc asm("r8"); 577 register unsigned long pc asm("r8");
581 578
@@ -586,7 +583,7 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
586 "stmia %[regs], {r0-r7} \n\t" 583 "stmia %[regs], {r0-r7} \n\t"
587 "str r9, [%[regs], #13*4] \n\t" 584 "str r9, [%[regs], #13*4] \n\t"
588 : "=r" (pc) 585 : "=r" (pc)
589 : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) 586 : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
590 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 587 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
591 "lr", "memory", "cc" 588 "lr", "memory", "cc"
592 ); 589 );
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index a757c3c22381..b4a3028edffe 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -204,7 +204,7 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs)
204static inline void __kprobes 204static inline void __kprobes
205singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) 205singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
206{ 206{
207 p->ainsn.insn_singlestep(p, regs); 207 p->ainsn.insn_singlestep(p->opcode, &p->ainsn, regs);
208} 208}
209 209
210/* 210/*
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 496e0e913fa6..36002e5d0f0e 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -19,9 +19,8 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/stddef.h> 20#include <linux/stddef.h>
21#include <linux/ptrace.h> 21#include <linux/ptrace.h>
22#include <linux/kprobes.h>
23 22
24#include "kprobes.h" 23#include "probes.h"
25#include "probes-arm.h" 24#include "probes-arm.h"
26 25
27#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) 26#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
@@ -58,10 +57,10 @@
58 * read and write of flags. 57 * read and write of flags.
59 */ 58 */
60 59
61void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) 60void __kprobes simulate_bbl(kprobe_opcode_t insn,
61 struct arch_specific_insn *asi, struct pt_regs *regs)
62{ 62{
63 kprobe_opcode_t insn = p->opcode; 63 long iaddr = (long) regs->ARM_pc - 4;
64 long iaddr = (long)p->addr;
65 int disp = branch_displacement(insn); 64 int disp = branch_displacement(insn);
66 65
67 if (insn & (1 << 24)) 66 if (insn & (1 << 24))
@@ -70,10 +69,10 @@ void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
70 regs->ARM_pc = iaddr + 8 + disp; 69 regs->ARM_pc = iaddr + 8 + disp;
71} 70}
72 71
73void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) 72void __kprobes simulate_blx1(kprobe_opcode_t insn,
73 struct arch_specific_insn *asi, struct pt_regs *regs)
74{ 74{
75 kprobe_opcode_t insn = p->opcode; 75 long iaddr = (long) regs->ARM_pc - 4;
76 long iaddr = (long)p->addr;
77 int disp = branch_displacement(insn); 76 int disp = branch_displacement(insn);
78 77
79 regs->ARM_lr = iaddr + 4; 78 regs->ARM_lr = iaddr + 4;
@@ -81,14 +80,14 @@ void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
81 regs->ARM_cpsr |= PSR_T_BIT; 80 regs->ARM_cpsr |= PSR_T_BIT;
82} 81}
83 82
84void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) 83void __kprobes simulate_blx2bx(kprobe_opcode_t insn,
84 struct arch_specific_insn *asi, struct pt_regs *regs)
85{ 85{
86 kprobe_opcode_t insn = p->opcode;
87 int rm = insn & 0xf; 86 int rm = insn & 0xf;
88 long rmv = regs->uregs[rm]; 87 long rmv = regs->uregs[rm];
89 88
90 if (insn & (1 << 5)) 89 if (insn & (1 << 5))
91 regs->ARM_lr = (long)p->addr + 4; 90 regs->ARM_lr = (long) regs->ARM_pc;
92 91
93 regs->ARM_pc = rmv & ~0x1; 92 regs->ARM_pc = rmv & ~0x1;
94 regs->ARM_cpsr &= ~PSR_T_BIT; 93 regs->ARM_cpsr &= ~PSR_T_BIT;
@@ -96,15 +95,16 @@ void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
96 regs->ARM_cpsr |= PSR_T_BIT; 95 regs->ARM_cpsr |= PSR_T_BIT;
97} 96}
98 97
99void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) 98void __kprobes simulate_mrs(kprobe_opcode_t insn,
99 struct arch_specific_insn *asi, struct pt_regs *regs)
100{ 100{
101 kprobe_opcode_t insn = p->opcode;
102 int rd = (insn >> 12) & 0xf; 101 int rd = (insn >> 12) & 0xf;
103 unsigned long mask = 0xf8ff03df; /* Mask out execution state */ 102 unsigned long mask = 0xf8ff03df; /* Mask out execution state */
104 regs->uregs[rd] = regs->ARM_cpsr & mask; 103 regs->uregs[rd] = regs->ARM_cpsr & mask;
105} 104}
106 105
107void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) 106void __kprobes simulate_mov_ipsp(kprobe_opcode_t insn,
107 struct arch_specific_insn *asi, struct pt_regs *regs)
108{ 108{
109 regs->uregs[12] = regs->uregs[13]; 109 regs->uregs[12] = regs->uregs[13];
110} 110}
@@ -704,10 +704,11 @@ const union decode_item kprobe_decode_arm_table[] = {
704EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); 704EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
705#endif 705#endif
706 706
707static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) 707static void __kprobes arm_singlestep(kprobe_opcode_t insn,
708 struct arch_specific_insn *asi, struct pt_regs *regs)
708{ 709{
709 regs->ARM_pc += 4; 710 regs->ARM_pc += 4;
710 p->ainsn.insn_handler(p, regs); 711 asi->insn_handler(insn, asi, regs);
711} 712}
712 713
713/* Return: 714/* Return:
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index ef3089419a0b..d0ac8a42caa0 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -53,10 +53,15 @@ enum probes_arm_action {
53 NUM_PROBES_ARM_ACTIONS 53 NUM_PROBES_ARM_ACTIONS
54}; 54};
55 55
56void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs); 56void __kprobes simulate_bbl(kprobe_opcode_t opcode,
57void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs); 57 struct arch_specific_insn *asi, struct pt_regs *regs);
58void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs); 58void __kprobes simulate_blx1(kprobe_opcode_t opcode,
59void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs); 59 struct arch_specific_insn *asi, struct pt_regs *regs);
60void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs); 60void __kprobes simulate_blx2bx(kprobe_opcode_t opcode,
61 struct arch_specific_insn *asi, struct pt_regs *regs);
62void __kprobes simulate_mrs(kprobe_opcode_t opcode,
63 struct arch_specific_insn *asi, struct pt_regs *regs);
64void __kprobes simulate_mov_ipsp(kprobe_opcode_t opcode,
65 struct arch_specific_insn *asi, struct pt_regs *regs);
61 66
62#endif 67#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index 2abe8ceeb670..aa3176da1b29 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -10,10 +10,9 @@
10 10
11#include <linux/stddef.h> 11#include <linux/stddef.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/kprobes.h>
14#include <linux/module.h> 13#include <linux/module.h>
15 14
16#include "kprobes.h" 15#include "probes.h"
17#include "probes-thumb.h" 16#include "probes-thumb.h"
18 17
19 18
@@ -844,17 +843,21 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
844 return true; 843 return true;
845} 844}
846 845
847static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs) 846static void __kprobes thumb16_singlestep(kprobe_opcode_t opcode,
847 struct arch_specific_insn *asi,
848 struct pt_regs *regs)
848{ 849{
849 regs->ARM_pc += 2; 850 regs->ARM_pc += 2;
850 p->ainsn.insn_handler(p, regs); 851 asi->insn_handler(opcode, asi, regs);
851 regs->ARM_cpsr = it_advance(regs->ARM_cpsr); 852 regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
852} 853}
853 854
854static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs) 855static void __kprobes thumb32_singlestep(kprobe_opcode_t opcode,
856 struct arch_specific_insn *asi,
857 struct pt_regs *regs)
855{ 858{
856 regs->ARM_pc += 4; 859 regs->ARM_pc += 4;
857 p->ainsn.insn_handler(p, regs); 860 asi->insn_handler(opcode, asi, regs);
858 regs->ARM_cpsr = it_advance(regs->ARM_cpsr); 861 regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
859} 862}
860 863
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index efd92c5b4a52..f2ab8856ba2b 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -13,12 +13,11 @@
13 13
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/kprobes.h>
17#include <asm/system_info.h> 16#include <asm/system_info.h>
18#include <asm/ptrace.h> 17#include <asm/ptrace.h>
19#include <linux/bug.h> 18#include <linux/bug.h>
20 19
21#include "kprobes.h" 20#include "probes.h"
22 21
23 22
24#ifndef find_str_pc_offset 23#ifndef find_str_pc_offset
@@ -176,13 +175,17 @@ kprobe_check_cc * const kprobe_condition_checks[16] = {
176}; 175};
177 176
178 177
179void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs) 178void __kprobes kprobe_simulate_nop(kprobe_opcode_t opcode,
179 struct arch_specific_insn *asi,
180 struct pt_regs *regs)
180{ 181{
181} 182}
182 183
183void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs) 184void __kprobes kprobe_emulate_none(kprobe_opcode_t opcode,
185 struct arch_specific_insn *asi,
186 struct pt_regs *regs)
184{ 187{
185 p->ainsn.insn_fn(); 188 asi->insn_fn();
186} 189}
187 190
188/* 191/*
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 5554f161bdac..efea63c02742 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -22,6 +22,7 @@
22#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/stddef.h> 23#include <linux/stddef.h>
24#include <linux/kprobes.h> 24#include <linux/kprobes.h>
25#include "kprobes.h"
25 26
26#if __LINUX_ARM_ARCH__ >= 7 27#if __LINUX_ARM_ARCH__ >= 7
27 28
@@ -37,6 +38,7 @@ void __init find_str_pc_offset(void);
37 38
38#endif 39#endif
39 40
41struct decode_header;
40 42
41/* 43/*
42 * Update ITSTATE after normal execution of an IT block instruction. 44 * Update ITSTATE after normal execution of an IT block instruction.
@@ -129,8 +131,10 @@ static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
129} 131}
130 132
131 133
132void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); 134void __kprobes kprobe_simulate_nop(kprobe_opcode_t, struct arch_specific_insn *,
133void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); 135 struct pt_regs *regs);
136void __kprobes kprobe_emulate_none(kprobe_opcode_t, struct arch_specific_insn *,
137 struct pt_regs *regs);
134 138
135enum kprobe_insn __kprobes 139enum kprobe_insn __kprobes
136kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, 140kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,